revision 2232 committed: msg#00065

Subject: revision 2232 committed
Project     : madwifi
Revision    : 2232
Author      : mickflemm (Nick Kossifidis)
Date        : 2007-03-27 19:29:30 +0200 (Tue, 27 Mar 2007)

Log Message :
* Merge code and headers as a first step to a HAL-less driver
* This contains code for 5211/5212, only tested on 5212
* Needs cleanup/testing and some fixes before merging it with dadwifi (to 
become ath5k)
* 5210 code is more tricky to include
* All functions except descriptor-related (hw descriptors are different for 
each chipset) can work directly, i only left the function pointers there for 
combatibility.
* Check TODOs

Affected Files:
* branches/madwifi-old-openhal/openhal/Makefile       updated             
* branches/madwifi-old-openhal/openhal/README         updated             
* branches/madwifi-old-openhal/openhal/ah.h           updated             
* branches/madwifi-old-openhal/openhal/ah_osdep.c     updated             
* branches/madwifi-old-openhal/openhal/ah_osdep.h     updated             
* branches/madwifi-old-openhal/openhal/ar5210.c       deleted             
* branches/madwifi-old-openhal/openhal/ar5210reg.h    deleted             
* branches/madwifi-old-openhal/openhal/ar5210var.h    deleted             
* branches/madwifi-old-openhal/openhal/ar5211.c       deleted             
* branches/madwifi-old-openhal/openhal/ar5211reg.h    deleted             
* branches/madwifi-old-openhal/openhal/ar5211var.h    deleted             
* branches/madwifi-old-openhal/openhal/ar5212.c       deleted             
* branches/madwifi-old-openhal/openhal/ar5212reg.h    deleted             
* branches/madwifi-old-openhal/openhal/ar5212var.h    deleted             
* branches/madwifi-old-openhal/openhal/ar5xxx.c       deleted             
* branches/madwifi-old-openhal/openhal/ar5xxx.h       deleted             
* branches/madwifi-old-openhal/openhal/ath5k.h        added               
* branches/madwifi-old-openhal/openhal/ath5k_hw.c     added               
* branches/madwifi-old-openhal/openhal/ath5k_hw.h     added               
* branches/madwifi-old-openhal/openhal/ath5kreg.h     added               
* branches/madwifi-old-openhal/openhal/ieee80211_regdomain.c  updated           
  


Modified: branches/madwifi-old-openhal/openhal/Makefile
===================================================================
--- branches/madwifi-old-openhal/openhal/Makefile       2007-03-27 07:43:32 UTC 
(rev 2231)
+++ branches/madwifi-old-openhal/openhal/Makefile       2007-03-27 17:29:30 UTC 
(rev 2232)
@@ -5,7 +5,7 @@
 TOP = $(obj)/..
 
 obj-m          += ath_hal.o
-ath_hal-objs   := ah_osdep.o ar5xxx.o ar5212.o ar5211.o ar5210.o 
ieee80211_regdomain.o
+ath_hal-objs   := ah_osdep.o ath5k_hw.o ieee80211_regdomain.o
 
 include $(TOP)/Makefile.inc
 

Modified: branches/madwifi-old-openhal/openhal/README
===================================================================
--- branches/madwifi-old-openhal/openhal/README 2007-03-27 07:43:32 UTC (rev 
2231)
+++ branches/madwifi-old-openhal/openhal/README 2007-03-27 17:29:30 UTC (rev 
2232)
@@ -1,13 +1,14 @@
-Linux OpenHAL 20061412
+Linux OpenHAL 20072703
 ======================
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  * This is a port of the ar5k hal for atheros device drivers that is         *
- * source-compatible with the Madwifi driver for linux                         
     *
- * (before the BSD - HEAD merge).                                           *
+ * source-compatible with the Madwifi driver for linux.                        
     *
  *                                                                          *
  * Code ported, modified for combatibility and some bugs were fixed by         
     *
  * Nick "Mick Flemm" Kossifidis (Athens Wireless Metropolitan Network)      *
- * <mickflemm'at'gmail.com> so ar5k can work propertly on Linux.            *
+ * <mickflemm'at'gmail.com> and Pavel Roskin so ar5k can work propertly      *
+ * on Linux.                                                                *
+ *                                                                          *
  * Currently only the 5212 code has been tested due to lack of hardware.     *
  *                                                                          *
  * Some code from John Bicket's port (roofnet project) was taken, you can    *
@@ -91,8 +92,7 @@
 
 WARNING: Don't delete the empty files included (ah_desc.h etc)
 
-Note: Currenty works for MadWiFi versions before HEAD - BSD merge
-(that means it works with 07/11/05 snapshot).
+Note: Currenty works for MadWiFi-old
 
 Use
 =====

Modified: branches/madwifi-old-openhal/openhal/ah.h
===================================================================
--- branches/madwifi-old-openhal/openhal/ah.h   2007-03-27 07:43:32 UTC (rev 
2231)
+++ branches/madwifi-old-openhal/openhal/ah.h   2007-03-27 17:29:30 UTC (rev 
2232)
@@ -1,6 +1 @@
-#ifndef _AR5K_AH_H
-#define _AR5K_AH_H
-
-#include "ar5xxx.h"
-
-#endif
+#include "ath5k.h"

Modified: branches/madwifi-old-openhal/openhal/ah_osdep.c
===================================================================
--- branches/madwifi-old-openhal/openhal/ah_osdep.c     2007-03-27 07:43:32 UTC 
(rev 2231)
+++ branches/madwifi-old-openhal/openhal/ah_osdep.c     2007-03-27 17:29:30 UTC 
(rev 2232)
@@ -41,7 +41,7 @@
 
 MODULE_AUTHOR("Nick Kossifidis");
 MODULE_DESCRIPTION("OpenHAL");
-MODULE_SUPPORTED_DEVICE("");
+MODULE_SUPPORTED_DEVICE("Atheros AR5xxx WLAN cards");
 #ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
 #endif
@@ -53,7 +53,7 @@
                 AR5K_BUS_TAG t, AR5K_BUS_HANDLE h, void* s)
 {
         AR5K_STATUS status;
-        struct ath_hal *ah = ath_hal_attach(devid, sc, t, h, &status);
+        struct ath_hal *ah = ath5k_hw_init(devid, sc, t, h, &status);
 
         *(AR5K_STATUS *)s = status;
         if (ah)

Modified: branches/madwifi-old-openhal/openhal/ah_osdep.h
===================================================================
--- branches/madwifi-old-openhal/openhal/ah_osdep.h     2007-03-27 07:43:32 UTC 
(rev 2231)
+++ branches/madwifi-old-openhal/openhal/ah_osdep.h     2007-03-27 17:29:30 UTC 
(rev 2232)
@@ -74,8 +74,8 @@
 #define bcopy(_a, _b, _c)       memcpy(_b, _a, _c)
 #define bzero(_a, _b)           memset(_a, 0, _b)
 
-#define AR5K_REG_WRITE(_reg, _val)      (writel(_val, hal->ah_sh + (_reg)))
+//#define AR5K_REG_WRITE(_reg, _val)      (writel(_val, hal->ah_sh + (_reg)))
 //      bus_space_write_4(hal->ah_st, hal->ah_sh, (_reg), (_val))
 
-#define AR5K_REG_READ(_reg)             (readl(hal->ah_sh + (_reg)))
+//#define AR5K_REG_READ(_reg)             (readl(hal->ah_sh + (_reg)))
 //      bus_space_read_4(hal->ah_st, hal->ah_sh, (_reg))

Deleted: branches/madwifi-old-openhal/openhal/ar5210.c

Deleted: branches/madwifi-old-openhal/openhal/ar5210reg.h

Deleted: branches/madwifi-old-openhal/openhal/ar5210var.h

Deleted: branches/madwifi-old-openhal/openhal/ar5211.c

Deleted: branches/madwifi-old-openhal/openhal/ar5211reg.h

Deleted: branches/madwifi-old-openhal/openhal/ar5211var.h

Deleted: branches/madwifi-old-openhal/openhal/ar5212.c

Deleted: branches/madwifi-old-openhal/openhal/ar5212reg.h

Deleted: branches/madwifi-old-openhal/openhal/ar5212var.h

Deleted: branches/madwifi-old-openhal/openhal/ar5xxx.c

Deleted: branches/madwifi-old-openhal/openhal/ar5xxx.h

Added: branches/madwifi-old-openhal/openhal/ath5k.h
===================================================================
--- branches/madwifi-old-openhal/openhal/ath5k.h                                
(rev 0)
+++ branches/madwifi-old-openhal/openhal/ath5k.h        2007-03-27 17:29:30 UTC 
(rev 2232)
@@ -0,0 +1,1241 @@
+/*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@xxxxxxxxxxx>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@xxxxxxxxx>
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * HAL interface for Atheros Wireless LAN devices.
+ *
+ * ar5k is a free replacement of the binary-only HAL used by some drivers
+ * for Atheros chipsets. While using a different ABI, it tries to be
+ * source-compatible with the original (non-free) HAL interface.
+ *
+ * Many thanks to various contributors who supported the development of
+ * ar5k with hard work and useful information. And, of course, for all the
+ * people who encouraged me to continue this work which has been based
+ * on my initial approach found on http://team.vantronix.net/ar5k/.
+ */
+
+#ifndef _AR5K_H
+#define _AR5K_H
+
+/*Os dependent definitions*/
+#include "ah_osdep.h"
+#include "ath5k_hw.h"
+
+/*Regulatory domain & Channel definitions*/
+#include "ieee80211_regdomain.h"
+
+/*Options*/
+#include "opt_ah.h"
+
+/*
+ *Translation for MadWiFi combatibility
+ *(damn this is changed AGAIN in if_ath.pci :P)
+ */
+#include "translation.h"
+
+/*Use with MadWiFi/net80211*/
+#include "stack_net80211.h"
+
+
+/****************************\
+  GENERIC DRIVER DEFINITIONS
+\****************************/
+
+/*
+ * C doesn't support boolean ;-(
+ * TODO: See if there is a bool definition somewere else
+ * in the kernel, we shouldn't redefine it if it does...
+ */
+#ifndef TRUE
+#define        TRUE    1
+#endif
+#ifndef FALSE
+#define        FALSE   0
+#endif
+typedef u_int8_t AR5K_BOOL;
+
+/*
+ * Error codes reported from HAL to the driver
+ */
+typedef enum {
+       AR5K_OK         = 0,    /* Everything went O.K.*/
+       AR5K_ENOMEM     = 1,    /* Unable to allocate memory for ath_hal*/
+       AR5K_EIO        = 2,    /* Hardware I/O Error*/
+       AR5K_EELOCKED   = 3,    /* Unable to access EEPROM*/
+       AR5K_EEBADSUM   = 4,    /* Invalid EEPROM checksum*/
+       AR5K_EEREAD     = 5,    /* Unable to get device caps from EEPROM */
+       AR5K_EEBADMAC   = 6,    /* Unable to read MAC address from EEPROM */
+       AR5K_EINVAL     = 7,    /* Invalid parameter to function */
+       AR5K_ENOTSUPP   = 8,    /* Hardware revision not supported */
+       AR5K_EINPROGRESS= 9,    /* Unexpected error ocured during process */
+} AR5K_STATUS;
+
+/*
+ * Some tuneable values (these should be changeable by the user)
+ */
+#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            ((MAX_PDU_LENGTH / 64) + 1)
+#define AR5K_TUNE_RSSI_THRES                   1792
+#define AR5K_TUNE_REGISTER_TIMEOUT             20000
+#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                  60
+#define AR5K_TUNE_DEFAULT_TXPOWER              30
+#define AR5K_TUNE_TPC_TXPOWER                  TRUE
+#define AR5K_TUNE_ANT_DIVERSITY                        TRUE
+#define AR5K_TUNE_HWTXTRIES                    4
+
+/* token to use for aifs, cwmin, cwmax in MadWiFi */
+#define        AR5K_TXQ_USEDEFAULT     ((u_int32_t) -1)
+
+#define IEEE80211_ADDR_LEN      6       /* size of 802.11 address */
+#define ETHER_ADDR_LEN          6       /* length of an Ethernet address */
+static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff };
+//#define etherbroadcastaddr 0xff
+
+
+
+
+/*****************************\
+  GENERIC CHIPSET DEFINITIONS
+\*****************************/
+
+/* MAC Chips*/
+enum ath5k_version {
+       AR5K_AR5210     = 0,
+       AR5K_AR5211     = 1,
+       AR5K_AR5212     = 2,
+};
+
+/*PHY Chips*/
+enum ath5k_radio {
+       AR5K_AR5110     = 0,
+       AR5K_AR5111     = 1,
+       AR5K_AR5112     = 2,
+};
+
+/*
+ * Common silicon revision/version values
+ */
+enum ath5k_srev_type {
+       AR5K_VERSION_VER,
+       AR5K_VERSION_REV,
+       AR5K_VERSION_RAD,
+       AR5K_VERSION_DEV
+};
+
+struct ath5k_srev_name {
+       const char              *sr_name;
+       enum ath5k_srev_type    sr_type;
+       u_int                   sr_val;
+};
+
+#define AR5K_SREV_NAME {                                               \
+       { "5210",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5210 }, \
+       { "5311",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5311 }, \
+       { "5311a",      AR5K_VERSION_VER,       AR5K_SREV_VER_AR5311A },\
+       { "5311b",      AR5K_VERSION_VER,       AR5K_SREV_VER_AR5311B },\
+       { "5211",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5211 }, \
+       { "5212",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5212 }, \
+       { "5213",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5213 }, \
+       { "xxxx",       AR5K_VERSION_VER,       AR5K_SREV_UNKNOWN },    \
+       { "5110",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5110 },   \
+       { "5111",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5111 },   \
+       { "2111",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2111 },   \
+       { "5112",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5112 },   \
+       { "5112a",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_5112A },  \
+       { "2112",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112 },   \
+       { "2112a",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112A },  \
+       { "xxxx",       AR5K_VERSION_RAD,       AR5K_SREV_UNKNOWN },    \
+       { "2413",       AR5K_VERSION_DEV,       AR5K_DEVID_AR2413 },    \
+       { "5413",       AR5K_VERSION_DEV,       AR5K_DEVID_AR5413 },    \
+       { "5424",       AR5K_VERSION_DEV,       AR5K_DEVID_AR5424 },    \
+       { "xxxx",       AR5K_VERSION_DEV,       AR5K_SREV_UNKNOWN }     \
+}
+
+#define AR5K_SREV_UNKNOWN      0xffff
+
+#define AR5K_SREV_VER_AR5210   0x00
+#define AR5K_SREV_VER_AR5311   0x10
+#define AR5K_SREV_VER_AR5311A  0x20
+#define AR5K_SREV_VER_AR5311B  0x30
+#define AR5K_SREV_VER_AR5211   0x40
+#define AR5K_SREV_VER_AR5212   0x50
+#define AR5K_SREV_VER_AR5213   0x55
+#define AR5K_SREV_VER_UNSUPP   0x60
+
+#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_2112     0x40
+#define AR5K_SREV_RAD_2112A    0x45
+#define AR5K_SREV_RAD_UNSUPP   0x50
+
+
+
+
+/****************\
+  TX DEFINITIONS
+\****************/
+
+/*
+ * Tx Descriptor
+ */
+struct ath_tx_status {
+       u_int16_t       ts_seqnum;
+       u_int16_t       ts_tstamp;
+       u_int8_t        ts_status;
+       u_int8_t        ts_rate;
+       int8_t          ts_rssi;
+       u_int8_t        ts_shortretry;
+       u_int8_t        ts_longretry;
+       u_int8_t        ts_virtcol;
+       u_int8_t        ts_antenna;
+};
+
+#define AR5K_TXSTAT_ALTRATE    0x80
+#define AR5K_TXERR_XRETRY      0x01
+#define AR5K_TXERR_FILT                0x02
+#define AR5K_TXERR_FIFO                0x04
+
+/*
+ * Queue types used to classify tx queues.
+ */
+typedef enum {
+       AR5K_TX_QUEUE_INACTIVE = 0,/*This queue is not used -see 
ath_hal_releasetxqueue*/
+       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 ater-beacon queue*/
+       AR5K_TX_QUEUE_UAPSD,      /*Unscheduled Automatic Power Save Delivery 
queue*/
+} AR5K_TX_QUEUE;
+
+#define        AR5K_NUM_TX_QUEUES      10
+
+/*
+ * 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.
+ */
+typedef enum {
+       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*/
+} AR5K_TX_QUEUE_SUBTYPE;
+
+/*
+ * Queue ID numbers as returned by the HAL, each number
+ * represents a hw queue. If hw does not support hw queues
+ * (eg 5210/5211) all data goes in one queue. These match
+ * d80211 definitions (net80211/MadWiFi don't use them).
+ */
+typedef enum {
+       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,
+} AR5K_TX_QUEUE_ID;
+
+
+/*
+ * Flags to set hw queue's parameters...
+ */
+#define AR5K_TXQ_FLAG_TXINT_ENABLE             0x0001  /* Enable TXOK and 
TXERR interrupts -not used- */
+#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE         0x0002  /* Enable TXDESC 
interrupt -not implemented- */
+#define AR5K_TXQ_FLAG_BACKOFF_DISABLE          0x0004  /* Disable random 
post-backoff */
+#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE       0x0008  /* Enable hw 
compression -not implemented-*/
+#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE        0x0010  /* Enable ready 
time expiry policy (?)*/
+#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE        0x0020  /* Enable 
backoff while bursting */
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS                0x0040  /* Disable 
backoff while bursting */
+#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE          0x0080  /* Enable TXEOL 
interrupt -not implemented-*/
+
+/*
+ * A struct to hold tx queue's parameters
+ */
+typedef struct {
+       AR5K_TX_QUEUE                   tqi_type;       /* See AR5K_TX_QUEUE */
+       AR5K_TX_QUEUE_SUBTYPE           tqi_subtype;    /* See 
AR5K_TX_QUEUE_SUBTYPE */
+       u_int16_t                       tqi_flags;      /* Tx queue flags (see 
above) */
+       u_int32_t                       tqi_aifs;       /* Arbitrated 
Interframe Space */
+       int32_t                         tqi_cw_min;     /* Minimum Contention 
Window */
+       int32_t                         tqi_cw_max;     /* Maximum Contention 
Window */
+       u_int32_t                       tqi_cbr_period; /* Constant bit rate 
period */
+       u_int32_t                       tqi_cbr_overflow_limit;
+       u_int32_t                       tqi_burst_time;
+       u_int32_t                       tqi_ready_time; /* Not used */
+       u_int32_t                       tqi_comp_buffer;/* Compression Buffer's 
phys addr */
+} AR5K_TXQ_INFO;
+
+/*
+ * Transmit packet types.
+ * These are not fully used inside OpenHAL yet
+ */
+typedef enum {
+       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,
+} AR5K_PKT_TYPE;
+
+/*
+ * TX power and TPC settings
+ */
+#define AR5K_TXPOWER_OFDM(_r, _v)      (                       \
+       ((0 & 1) << ((_v) + 6)) |                               \
+       (((hal->ah_txpower.txp_rates[(_r)]) & 0x3f) << (_v))    \
+)
+
+#define AR5K_TXPOWER_CCK(_r, _v)       (                       \
+       (hal->ah_txpower.txp_rates[(_r)] & 0x3f) << (_v)        \
+)
+
+/*
+ * Used to compute TX times
+ */
+#define AR5K_CCK_SIFS_TIME             10
+#define AR5K_CCK_PREAMBLE_BITS         144
+#define AR5K_CCK_PLCP_BITS             48
+
+#define AR5K_OFDM_SIFS_TIME            16
+#define AR5K_OFDM_PREAMBLE_TIME                20
+#define AR5K_OFDM_PLCP_BITS            22
+#define AR5K_OFDM_SYMBOL_TIME          4
+
+#define AR5K_TURBO_SIFS_TIME           8
+#define AR5K_TURBO_PREAMBLE_TIME       14
+#define AR5K_TURBO_PLCP_BITS           22
+#define AR5K_TURBO_SYMBOL_TIME         4
+
+#define AR5K_XR_SIFS_TIME              16
+#define AR5K_XR_PLCP_BITS              22
+#define AR5K_XR_SYMBOL_TIME            4
+
+/* CCK */
+#define AR5K_CCK_NUM_BITS(_frmlen) (_frmlen << 3)
+
+#define AR5K_CCK_PHY_TIME(_sp) (_sp ?                                  \
+       ((AR5K_CCK_PREAMBLE_BITS + AR5K_CCK_PLCP_BITS) >> 1) :          \
+       (AR5K_CCK_PREAMBLE_BITS + AR5K_CCK_PLCP_BITS))
+
+#define AR5K_CCK_TX_TIME(_kbps, _frmlen, _sp)                          \
+       AR5K_CCK_PHY_TIME(_sp) +                                        \
+       ((AR5K_CCK_NUM_BITS(_frmlen) * 1000) / _kbps) +         \
+       AR5K_CCK_SIFS_TIME
+
+/* OFDM */
+#define AR5K_OFDM_NUM_BITS(_frmlen) (AR5K_OFDM_PLCP_BITS + (_frmlen << 3))
+
+#define AR5K_OFDM_NUM_BITS_PER_SYM(_kbps) ((_kbps *                    \
+       AR5K_OFDM_SYMBOL_TIME) / 1000)
+
+#define AR5K_OFDM_NUM_BITS(_frmlen) (AR5K_OFDM_PLCP_BITS + (_frmlen << 3))
+
+#define AR5K_OFDM_NUM_SYMBOLS(_kbps, _frmlen)                          \
+       howmany(AR5K_OFDM_NUM_BITS(_frmlen), AR5K_OFDM_NUM_BITS_PER_SYM(_kbps))
+
+#define AR5K_OFDM_TX_TIME(_kbps, _frmlen)                              \
+       AR5K_OFDM_PREAMBLE_TIME + AR5K_OFDM_SIFS_TIME +                 \
+       (AR5K_OFDM_NUM_SYMBOLS(_kbps, _frmlen) * AR5K_OFDM_SYMBOL_TIME)
+
+/* TURBO */
+#define AR5K_TURBO_NUM_BITS(_frmlen) (AR5K_TURBO_PLCP_BITS + (_frmlen << 3))
+
+#define AR5K_TURBO_NUM_BITS_PER_SYM(_kbps) (((_kbps << 1) *            \
+       AR5K_TURBO_SYMBOL_TIME) / 1000)
+
+#define AR5K_TURBO_NUM_BITS(_frmlen) (AR5K_TURBO_PLCP_BITS + (_frmlen << 3))
+
+#define AR5K_TURBO_NUM_SYMBOLS(_kbps, _frmlen)                         \
+       howmany(AR5K_TURBO_NUM_BITS(_frmlen),                           \
+       AR5K_TURBO_NUM_BITS_PER_SYM(_kbps))
+
+#define AR5K_TURBO_TX_TIME(_kbps, _frmlen)                             \
+       AR5K_TURBO_PREAMBLE_TIME + AR5K_TURBO_SIFS_TIME +               \
+       (AR5K_TURBO_NUM_SYMBOLS(_kbps, _frmlen) * AR5K_TURBO_SYMBOL_TIME)
+
+/* eXtendent Range (?)*/
+#define AR5K_XR_PREAMBLE_TIME(_kbps) (((_kbps) < 1000) ? 173 : 76)
+
+#define AR5K_XR_NUM_BITS_PER_SYM(_kbps) ((_kbps *                      \
+       AR5K_XR_SYMBOL_TIME) / 1000)
+
+#define AR5K_XR_NUM_BITS(_frmlen) (AR5K_XR_PLCP_BITS + (_frmlen << 3))
+
+#define AR5K_XR_NUM_SYMBOLS(_kbps, _frmlen)                            \
+       howmany(AR5K_XR_NUM_BITS(_frmlen), AR5K_XR_NUM_BITS_PER_SYM(_kbps))
+
+#define AR5K_XR_TX_TIME(_kbps, _frmlen)                                \
+       AR5K_XR_PREAMBLE_TIME(_kbps) + AR5K_XR_SIFS_TIME +              \
+       (AR5K_XR_NUM_SYMBOLS(_kbps, _frmlen) * AR5K_XR_SYMBOL_TIME)
+
+/*
+ * DMA size definitions (2^n+2)
+ */
+typedef enum {
+       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
+} ath5k_dmasize_t;
+
+
+
+/****************\
+  RX DEFINITIONS
+\****************/
+
+/*
+ * Rx Descriptor
+ */
+struct ath_rx_status {
+       u_int16_t       rs_datalen;
+       u_int16_t       rs_tstamp;
+       u_int8_t        rs_status;
+       u_int8_t        rs_phyerr;
+       int8_t          rs_rssi;
+       u_int8_t        rs_keyix;
+       u_int8_t        rs_rate;
+       u_int8_t        rs_antenna;
+       u_int8_t        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   ((u_int8_t) - 1)
+#define AR5K_TXKEYIX_INVALID   ((u_int32_t) - 1)
+
+/*
+ * RX filters
+ * Most of them are not yet used inside OpenHAL
+ */
+#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 */
+#define        AR5K_RX_FILTER_PROBEREQ         0x00000080      /* Don't filter 
probe requests */
+#define        AR5K_RX_FILTER_PHYERROR         0x00000100      /* Don't filter 
phy errors */
+#define        AR5K_RX_FILTER_PHYRADAR         0x00000200      /* Don't filter 
phy radar errors*/
+
+typedef struct {
+       u_int32_t       ackrcv_bad;
+       u_int32_t       rts_bad;
+       u_int32_t       rts_good;
+       u_int32_t       fcs_bad;
+       u_int32_t       beacons;
+} AR5K_MIB_STATS;
+
+
+
+
+/**************************\
+ 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*/
+
+/*
+ * Per-station beacon timer state.
+ */
+typedef struct {
+       u_int32_t       bs_next_beacon;
+       u_int32_t       bs_next_dtim;
+       u_int32_t       bs_interval;            /*in TU's -see 
net80211/ieee80211_var.h-
+                                               can also include the above 
flags*/
+       u_int8_t        bs_dtim_period;
+       u_int8_t        bs_cfp_period;
+       u_int16_t       bs_cfp_max_duration;    /*if non-zero hw is setup to 
coexist with
+                                               a Point Coordination Function 
capable AP*/
+       u_int16_t       bs_cfp_du_remain;
+       u_int16_t       bs_tim_offset;
+       u_int16_t       bs_sleep_duration;
+       u_int16_t       bs_bmiss_threshold;
+       u_int32_t       bs_cfp_next;
+} AR5K_BEACON_STATE;
+
+
+
+
+/********************\
+  COMMON DEFINITIONS
+\********************/
+
+/*
+ * Atheros descriptor
+ */
+struct ath_desc {
+       u_int32_t       ds_link;
+       u_int32_t       ds_data;
+       u_int32_t       ds_ctl0;
+       u_int32_t       ds_ctl1;
+       u_int32_t       ds_hw[4];
+
+       union {
+               struct ath_rx_status rx;
+               struct ath_tx_status tx;
+       } ds_us;
+
+#define ds_rxstat ds_us.rx
+#define ds_txstat ds_us.tx
+
+} __packed;
+
+#define AR5K_RXDESC_INTREQ     0x0020
+
+#define AR5K_TXDESC_CLRDMASK   0x0001
+#define AR5K_TXDESC_NOACK      0x0002
+#define AR5K_TXDESC_RTSENA     0x0004
+#define AR5K_TXDESC_CTSENA     0x0008
+#define AR5K_TXDESC_INTREQ     0x0010
+#define AR5K_TXDESC_VEOL       0x0020
+
+/*
+ * 802.11 operating modes...
+ */
+#define AR5K_MODE_11A          0x01
+#define AR5K_MODE_11B          0x02
+#define AR5K_MODE_11G          0x04
+#define AR5K_MODE_TURBO        0x08
+#define AR5K_MODE_108G         0x16
+#define AR5K_MODE_XR   0x32
+#define AR5K_MODE_ALL  (AR5K_MODE_11A| \
+                       AR5K_MODE_11B|  \
+                       AR5K_MODE_11G|  \
+                       AR5K_MODE_TURBO|\
+                       AR5K_MODE_108G| \
+                       AR5K_MODE_XR)
+
+/*
+ * Channel definitions
+ */
+typedef struct {
+       u_int16_t       freq;           /* setting in Mhz */
+       u_int16_t       channel_flags;
+       u_int8_t        private_flags;  /* not used in OpenHAL yet*/
+} AR5K_CHANNEL;
+
+#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_PUREG   (CHANNEL_2GHZ|CHANNEL_OFDM)
+//#ifdef notdef
+#define        CHANNEL_G       (CHANNEL_2GHZ|CHANNEL_DYN)
+//#else
+//#define      CHANNEL_G       (CHANNEL_2GHZ|CHANNEL_OFDM)
+//#endif
+#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 in OpenHAL (ar5211.c/ar5212.c
+ * for reset_tx_queue). Also see struct AR5K_CHANNEL.
+ */
+#define IS_CHAN_XR(_c) \
+        ((_c.channel_flags & CHANNEL_XR) != 0)
+
+#define IS_CHAN_B(_c) \
+        ((_c.channel_flags & CHANNEL_B) != 0)
+
+typedef enum {
+       AR5K_CHIP_5GHZ = CHANNEL_5GHZ,
+       AR5K_CHIP_2GHZ = CHANNEL_2GHZ,
+} AR5K_CHIP;
+
+/*
+ * The following structure will be used to map 2GHz channels to
+ * 5GHz Atheros channels.
+ */
+struct ath5k_athchan_2ghz {
+       u_int32_t       a2_flags;
+       u_int16_t       a2_athchan;
+};
+
+/*
+ * Rate definitions
+ */
+
+#define AR5K_MAX_RATES 32 /*max number of rates on the rate table*/
+
+typedef struct {
+       u_int8_t        valid;          /* Valid for rate control */
+       u_int32_t       modulation;
+       u_int16_t       rate_kbps;              
+       u_int8_t        rate_code;      /* Rate mapping for h/w descriptors */
+       u_int8_t        dot11_rate;
+       u_int8_t        control_rate;
+       u_int16_t       lp_ack_duration;/* long preamble ACK duration */
+       u_int16_t       sp_ack_duration;/* short preamble ACK duration*/
+} AR5K_RATE;
+
+typedef struct {
+       u_int16_t       rate_count;                             
+       u_int8_t        rate_code_to_index[AR5K_MAX_RATES];     /* Back-mapping 
*/
+       AR5K_RATE       rates[AR5K_MAX_RATES];
+} AR5K_RATE_TABLE;
+
+/*
+ * Rate tables...
+ */
+#define AR5K_RATES_11A { 8, {                                  \
+       255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0,     \
+       7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255,     \
+       255, 255, 255, 255, 255, 255, 255, 255 }, {             \
+       { 1, MODULATION_OFDM, 6000, 11, 140, 0 },               \
+       { 1, MODULATION_OFDM, 9000, 15, 18, 0 },                \
+       { 1, MODULATION_OFDM, 12000, 10, 152, 2 },              \
+       { 1, MODULATION_OFDM, 18000, 14, 36, 2 },               \
+       { 1, MODULATION_OFDM, 24000, 9, 176, 4 },               \
+       { 1, MODULATION_OFDM, 36000, 13, 72, 4 },               \
+       { 1, MODULATION_OFDM, 48000, 8, 96, 4 },                \
+       { 1, MODULATION_OFDM, 54000, 12, 108, 4 } }             \
+}
+
+#define AR5K_RATES_11B { 4, {                                          \
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,     \
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,     \
+       3, 2, 1, 0, 255, 255, 255, 255 }, {                             \
+       { 1, MODULATION_CCK, 1000, 27, 130, 0 },        \
+       { 1, MODULATION_CCK, 2000, 26, 132, 1 },        \
+       { 1, MODULATION_CCK, 5500, 25, 139, 1 },        \
+       { 1, MODULATION_CCK, 11000, 24, 150, 1 } }      \
+}
+
+#define AR5K_RATES_11G { 12, {                                 \
+       255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4,    \
+       11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255,    \
+       3, 2, 1, 0, 255, 255, 255, 255 }, {                     \
+       { 1, MODULATION_CCK, 1000, 27, 2, 0 },          \
+       { 1, MODULATION_CCK, 2000, 26, 4, 1 },          \
+       { 1, MODULATION_CCK, 5500, 25, 11, 1 },         \
+       { 1, MODULATION_CCK, 11000, 24, 22, 1 },        \
+       { 0, MODULATION_OFDM, 6000, 11, 12, 4 },        \
+       { 0, MODULATION_OFDM, 9000, 15, 18, 4 },        \
+       { 1, MODULATION_OFDM, 12000, 10, 24, 6 },       \
+       { 1, MODULATION_OFDM, 18000, 14, 36, 6 },       \
+       { 1, MODULATION_OFDM, 24000, 9, 48, 8 },        \
+       { 1, MODULATION_OFDM, 36000, 13, 72, 8 },       \
+       { 1, MODULATION_OFDM, 48000, 8, 96, 8 },        \
+       { 1, MODULATION_OFDM, 54000, 12, 108, 8 } }     \
+}
+
+#define AR5K_RATES_TURBO { 8, {                                        \
+       255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0,     \
+       7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255,     \
+       255, 255, 255, 255, 255, 255, 255, 255 }, {             \
+       { 1, MODULATION_TURBO, 6000, 11, 140, 0 },      \
+       { 1, MODULATION_TURBO, 9000, 15, 18, 0 },       \
+       { 1, MODULATION_TURBO, 12000, 10, 152, 2 },     \
+       { 1, MODULATION_TURBO, 18000, 14, 36, 2 },      \
+       { 1, MODULATION_TURBO, 24000, 9, 176, 4 },      \
+       { 1, MODULATION_TURBO, 36000, 13, 72, 4 },      \
+       { 1, MODULATION_TURBO, 48000, 8, 96, 4 },       \
+       { 1, MODULATION_TURBO, 54000, 12, 108, 4 } }    \
+}
+
+#define AR5K_RATES_XR { 12, {                                  \
+       255, 3, 1, 255, 255, 255, 2, 0, 10, 8, 6, 4,            \
+       11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255,    \
+       255, 255, 255, 255, 255, 255, 255, 255 }, {             \
+       { 1, MODULATION_XR, 500, 7, 129, 0 },           \
+       { 1, MODULATION_XR, 1000, 2, 139, 1 },          \
+       { 1, MODULATION_XR, 2000, 6, 150, 2 },          \
+       { 1, MODULATION_XR, 3000, 1, 150, 3 },          \
+       { 1, MODULATION_OFDM, 6000, 11, 140, 4 },       \
+       { 1, MODULATION_OFDM, 9000, 15, 18, 4 },        \
+       { 1, MODULATION_OFDM, 12000, 10, 152, 6 },      \
+       { 1, MODULATION_OFDM, 18000, 14, 36, 6 },       \
+       { 1, MODULATION_OFDM, 24000, 9, 176, 8 },       \
+       { 1, MODULATION_OFDM, 36000, 13, 72, 8 },       \
+       { 1, MODULATION_OFDM, 48000, 8, 96, 8 },        \
+       { 1, MODULATION_OFDM, 54000, 12, 108, 8 } }     \
+}
+
+/*
+ * Crypto definitions
+ */
+
+/* key types */
+typedef enum {
+       AR5K_CIPHER_WEP         = 0,
+       AR5K_CIPHER_AES_OCB     = 1,
+       AR5K_CIPHER_AES_CCM     = 2,
+       AR5K_CIPHER_CKIP        = 3,
+       AR5K_CIPHER_TKIP        = 4,
+       AR5K_CIPHER_CLR         = 5,    /* no encryption */
+       AR5K_CIPHER_MIC         = 127   /* used for Message 
+                                          Integrity Code */
+} AR5K_CIPHER;
+
+#define AR5K_KEYVAL_LENGTH_40  5
+#define AR5K_KEYVAL_LENGTH_104 13
+#define AR5K_KEYVAL_LENGTH_128 16
+#define AR5K_KEYVAL_LENGTH_MAX AR5K_KEYVAL_LENGTH_128
+
+typedef struct {
+       int             wk_len;         /* key's length */
+       u_int8_t        wk_key[AR5K_KEYVAL_LENGTH_MAX];
+       u_int8_t        wk_type;        /* see above */
+       u_int8_t        wk_mic[8];      /* TKIP MIC key */
+} AR5K_KEYVAL;
+
+
+
+/***********************\
+ 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)
+
+
+typedef struct {
+       u_int32_t       ns_avgbrssi;    /* average beacon rssi */
+       u_int32_t       ns_avgrssi;     /* average data rssi */
+       u_int32_t       ns_avgtxrssi;   /* average tx rssi */
+} AR5K_NODE_STATS;
+
+typedef enum {
+       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,
+} AR5K_ANT_SETTING;
+
+/*
+ * HAL interrupt abstraction
+ */
+
+/*
+ * These are maped to take advantage of some common bits
+ * between the MAC chips, to be able to set intr properties
+ * easier. Some of them are not used yet inside OpenHAL.
+ */
+typedef enum {
+       AR5K_INT_RX     = 0x00000001,
+       AR5K_INT_RXDESC = 0x00000002,
+       AR5K_INT_RXNOFRM = 0x00000008,
+       AR5K_INT_RXEOL  = 0x00000010,
+       AR5K_INT_RXORN  = 0x00000020,
+       AR5K_INT_TX     = 0x00000040,
+       AR5K_INT_TXDESC = 0x00000080,
+       AR5K_INT_TXURN  = 0x00000800,
+       AR5K_INT_MIB    = 0x00001000,
+       AR5K_INT_RXPHY  = 0x00004000,
+       AR5K_INT_RXKCM  = 0x00008000,
+       AR5K_INT_SWBA   = 0x00010000,
+       AR5K_INT_BMISS  = 0x00040000,
+       AR5K_INT_BNR    = 0x00100000,
+       AR5K_INT_GPIO   = 0x01000000,
+       AR5K_INT_FATAL  = 0x40000000,
+       AR5K_INT_GLOBAL = 0x80000000,
+
+       /*A sum of all the common bits*/
+       AR5K_INT_COMMON  = AR5K_INT_RXNOFRM
+                       | AR5K_INT_RXDESC
+                       | AR5K_INT_RXEOL
+                       | AR5K_INT_RXORN
+                       | AR5K_INT_TXURN
+                       | AR5K_INT_TXDESC
+                       | AR5K_INT_MIB
+                       | AR5K_INT_RXPHY
+                       | AR5K_INT_RXKCM
+                       | AR5K_INT_SWBA
+                       | AR5K_INT_BMISS
+                       | AR5K_INT_GPIO,
+       AR5K_INT_NOCARD = 0xffffffff /*Declare that the card 
+                                      has been removed*/
+} AR5K_INT;
+
+/*
+ * Power management
+ */
+typedef enum {
+       AR5K_PM_UNDEFINED = 0,
+       AR5K_PM_AUTO,
+       AR5K_PM_AWAKE,
+       AR5K_PM_FULL_SLEEP,
+       AR5K_PM_NETWORK_SLEEP,
+} AR5K_POWER_MODE;
+
+
+/*
+ * LED states
+ */
+typedef int AR5K_LED_STATE;
+
+/*
+ * These match net80211 definitions (not used in
+ * d80211).
+ */
+#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 ath_hal_getcapability-
+ * get_capability function is not yet fully implemented
+ * in OpenHAL so most of these don't work yet...
+ */
+typedef enum {
+       AR5K_CAP_REG_DMN                = 0,    /* Used to get current reg. 
domain id */
+       AR5K_CAP_CIPHER                 = 1,    /* Can handle encryption */
+       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 */
+} AR5K_CAPABILITY_TYPE;
+
+typedef struct {
+       /*
+        * Supported PHY modes
+        * (ie. CHANNEL_A, CHANNEL_B, ...)
+        */
+       u_int16_t       cap_mode;
+
+       /*
+        * Frequency range (without regulation restrictions)
+        */
+       struct {
+               u_int16_t       range_2ghz_min;
+               u_int16_t       range_2ghz_max;
+               u_int16_t       range_5ghz_min;
+               u_int16_t       range_5ghz_max;
+       } cap_range;
+
+       /*
+        * Active regulation domain settings
+        */
+       struct {
+               ieee80211_regdomain_t   reg_current;
+               ieee80211_regdomain_t   reg_hw;
+       } cap_regdomain;
+
+       /*
+        * Values stored in the EEPROM (some of them...)
+        */
+       struct ath5k_eeprom_info        cap_eeprom;
+
+       /*
+        * Queue information
+        */
+       struct {
+               u_int8_t        q_tx_num;
+       } cap_queues;
+} ath5k_capabilities_t;
+
+
+/***************************************\
+  HARDWARE ABSTRACTION LAYER STRUCTURE
+\***************************************/
+
+/*
+ * Regulation stuff
+ */
+typedef enum ieee80211_countrycode AR5K_CTRY_CODE;
+
+/* Default regulation domain if stored value EEPROM value is invalid */
+#define AR5K_TUNE_REGDOMAIN    DMN_FCC2_FCCA   /* Canada */
+#define AR5K_TUNE_CTRY         CTRY_DEFAULT
+
+/*
+ * Misc defines
+ */
+
+#define AR5K_ELEMENTS(_array)  (sizeof(_array) / sizeof(_array[0]))
+
+typedef struct ath_hal * (ath5k_attach_t)
+       (u_int16_t, AR5K_SOFTC, AR5K_BUS_TAG, AR5K_BUS_HANDLE, AR5K_STATUS *);
+
+typedef AR5K_BOOL (ath5k_rfgain_t)
+       (struct ath_hal *, AR5K_CHANNEL *, u_int);
+
+/*
+ * HAL Functions that have different implementations for each chipset...
+ */
+#define AR5K_HAL_FUNCTION(_hal, _n, _f)        (_hal)->ah_##_f = 
ath5k_##_n##_##_f
+#define AR5K_HAL_FUNCTIONS(_t, _n, _a) \
+       _t const AR5K_RATE_TABLE *(_a _n##_get_rate_table)(struct ath_hal *, 
u_int mode);       \
+       _t void (_a _n##_detach)(struct ath_hal *);                             
                \
+       /* Reset functions */                                                   
                \
+       _t AR5K_BOOL (_a _n##_reset)(struct ath_hal *, AR5K_OPMODE, 
AR5K_CHANNEL *,             \
+                               AR5K_BOOL change_channel, AR5K_STATUS *status); 
                \
+       _t void (_a _n##_set_opmode)(struct ath_hal *);                         
        \
+       _t AR5K_BOOL (_a _n##_calibrate)(struct ath_hal*, AR5K_CHANNEL *);      
                \
+       /* Transmit functions */                                                
                \
+       _t AR5K_BOOL (_a _n##_update_tx_triglevel)(struct ath_hal*, AR5K_BOOL 
level);           \
+       _t int (_a _n##_setup_tx_queue)(struct ath_hal *, AR5K_TX_QUEUE, 
AR5K_TXQ_INFO *);      \
+       _t AR5K_BOOL (_a _n##_setup_tx_queueprops)(struct ath_hal *, int queue, 
                \
+                               const AR5K_TXQ_INFO *);                         
                \
+       _t AR5K_BOOL (_a _n##_release_tx_queue)(struct ath_hal *, u_int queue); 
                \
+       _t AR5K_BOOL (_a _n##_reset_tx_queue)(struct ath_hal *, u_int queue);   
                \
+       _t u_int32_t (_a _n##_get_tx_buf)(struct ath_hal *, u_int queue);       
                \
+       _t AR5K_BOOL (_a _n##_put_tx_buf)(struct ath_hal *, u_int, u_int32_t 
phys_addr);        \
+       _t AR5K_BOOL (_a _n##_tx_start)(struct ath_hal *, u_int queue);         
                \
+       _t AR5K_BOOL (_a _n##_stop_tx_dma)(struct ath_hal *, u_int queue);      
                \
+       _t AR5K_BOOL (_a _n##_setup_tx_desc)(struct ath_hal *, struct ath_desc 
*,               \
+                               u_int packet_length, u_int header_length, 
AR5K_PKT_TYPE type,   \
+                               u_int txPower, u_int tx_rate0, u_int tx_tries0, 
u_int key_index,\
+                               u_int antenna_mode, u_int flags, u_int 
rtscts_rate,             \
+                               u_int rtscts_duration);                         
                \
+       _t AR5K_BOOL (_a _n##_setup_xtx_desc)(struct ath_hal *, struct ath_desc 
*,              \
+                               u_int tx_rate1, u_int tx_tries1, u_int 
tx_rate2,                \
+                               u_int tx_tries2,u_int tx_rate3, u_int 
tx_tries3);               \
+       _t AR5K_BOOL (_a _n##_fill_tx_desc)(struct ath_hal *, struct ath_desc 
*, u_int segLen,  \
+                               AR5K_BOOL firstSeg, AR5K_BOOL lastSeg, const 
struct ath_desc *);\
+       _t AR5K_STATUS (_a _n##_proc_tx_desc)(struct ath_hal *, struct ath_desc 
*);             \
+       _t AR5K_BOOL (_a _n##_has_veol)(struct ath_hal *);                      
                \
+       /* Receive Functions */                                                 
                \
+       _t u_int32_t (_a _n##_get_rx_buf)(struct ath_hal*);                     
                \
+       _t void (_a _n##_put_rx_buf)(struct ath_hal*, u_int32_t rxdp);          
                \
+       _t void (_a _n##_start_rx)(struct ath_hal*);                            
                \
+       _t AR5K_BOOL (_a _n##_stop_rx_dma)(struct ath_hal*);                    
                \
+       _t void (_a _n##_start_rx_pcu)(struct ath_hal*);                        
                \
+       _t void (_a _n##_stop_pcu_recv)(struct ath_hal*);                       
                \
+       _t void (_a _n##_set_mcast_filter)(struct ath_hal*, u_int32_t filter0,  
                \
+                               u_int32_t filter1);                             
                \
+       _t AR5K_BOOL (_a _n##_set_mcast_filterindex)(struct ath_hal*, u_int32_t 
index); \
+       _t AR5K_BOOL (_a _n##_clear_mcast_filter_idx)(struct ath_hal*,u_int32_t 
index); \
+       _t u_int32_t (_a _n##_get_rx_filter)(struct ath_hal*);                  
                \
+       _t void (_a _n##_set_rx_filter)(struct ath_hal*, u_int32_t);            
                \
+       _t AR5K_BOOL (_a _n##_setup_rx_desc)(struct ath_hal *, struct ath_desc 
*,               \
+                               u_int32_t size, u_int flags);                   
                \
+       _t AR5K_STATUS (_a _n##_proc_rx_desc)(struct ath_hal *, struct ath_desc 
*,              \
+                               u_int32_t phyAddr, struct ath_desc *next);      
                \
+       _t void (_a _n##_set_rx_signal)(struct ath_hal *, const AR5K_NODE_STATS 
*);             \
+       /* Misc Functions */                                                    
                \
+       _t void (_a _n##_dump_state)(struct ath_hal *);                         
        \
+       _t AR5K_BOOL (_a _n##_get_diag_state)(struct ath_hal *, int 
request,const void *args,   \
+                               u_int32_t argsize, void **result, u_int32_t 
*resultsize);       \
+       _t void (_a _n##_get_lladdr)(struct ath_hal *, u_int8_t *);             
                \
+       _t AR5K_BOOL (_a _n##_set_lladdr)(struct ath_hal *, const u_int8_t*);   
                \
+       _t AR5K_BOOL (_a _n##_set_regdomain)(struct ath_hal*, u_int16_t, 
AR5K_STATUS *);        \
+       _t void (_a _n##_set_ledstate)(struct ath_hal*, AR5K_LED_STATE);        
                \
+       _t void (_a _n##_set_associd)(struct ath_hal*, const u_int8_t *bssid,   
                \
+                               u_int16_t assocId);                             
                \
+       _t AR5K_BOOL (_a _n##_set_gpio_input)(struct ath_hal *, u_int32_t 
gpio);                \
+       _t AR5K_BOOL (_a _n##_set_gpio_output)(struct ath_hal *, u_int32_t 
gpio);               \
+       _t u_int32_t (_a _n##_get_gpio)(struct ath_hal *, u_int32_t gpio);      
                \
+       _t AR5K_BOOL (_a _n##_set_gpio)(struct ath_hal *, u_int32_t gpio, 
u_int32_t val);       \
+       _t void (_a _n##_set_gpio_intr)(struct ath_hal*, u_int, u_int32_t);     
                \
+       _t u_int32_t (_a _n##_get_tsf32)(struct ath_hal*);                      
                \
+       _t u_int64_t (_a _n##_get_tsf64)(struct ath_hal*);                      
                \
+       _t void (_a _n##_reset_tsf)(struct ath_hal*);                           
                \
+       _t u_int16_t (_a _n##_get_regdomain)(struct ath_hal*);                  
                \
+       _t AR5K_BOOL (_a _n##_detect_card_present)(struct ath_hal*);            
                \
+       _t void (_a _n##_update_mib_counters)(struct ath_hal*, 
AR5K_MIB_STATS*);                \
+       _t AR5K_RFGAIN (_a _n##_get_rf_gain)(struct ath_hal*);                  
                \
+       _t AR5K_BOOL (_a _n##_set_slot_time)(struct ath_hal*, u_int);           
                \
+       _t u_int (_a _n##_get_slot_time)(struct ath_hal*);                      
                \
+       _t AR5K_BOOL (_a _n##_set_ack_timeout)(struct ath_hal *, u_int);        
                \
+       _t u_int (_a _n##_get_ack_timeout)(struct ath_hal*);                    
                \
+       _t AR5K_BOOL (_a _n##_set_cts_timeout)(struct ath_hal*, u_int);         
        \
+       _t u_int (_a _n##_get_cts_timeout)(struct ath_hal*);                    
                \
+       /* Key Cache Functions */                                               
                \
+       _t AR5K_BOOL (_a _n##_is_cipher_supported)(struct ath_hal*, 
AR5K_CIPHER);               \
+       _t u_int32_t (_a _n##_get_keycache_size)(struct ath_hal*);              
                \
+       _t AR5K_BOOL (_a _n##_reset_key)(struct ath_hal*, u_int16_t);           
                \
+       _t AR5K_BOOL (_a _n##_is_key_valid)(struct ath_hal *, u_int16_t);       
                \
+       _t AR5K_BOOL (_a _n##_set_key)(struct ath_hal*, u_int16_t, const 
AR5K_KEYVAL *,         \
+                               const u_int8_t *, int);                         
                \
+       _t AR5K_BOOL (_a _n##_set_key_lladdr)(struct ath_hal*, u_int16_t, const 
u_int8_t *);    \
+       /* Power Management Functions */                                        
                \
+       _t AR5K_BOOL (_a _n##_set_power)(struct ath_hal*, AR5K_POWER_MODE mode, 
        \
+                               AR5K_BOOL set_chip, u_int16_t sleep_duration);  
                \
+       _t AR5K_POWER_MODE (_a _n##_get_power_mode)(struct ath_hal*);           
                \
+       _t AR5K_BOOL (_a _n##_query_pspoll_support)(struct ath_hal*);           
                \
+       _t AR5K_BOOL (_a _n##_init_pspoll)(struct ath_hal*);                    
                \
+       _t AR5K_BOOL (_a _n##_enable_pspoll)(struct ath_hal *, u_int8_t *, 
u_int16_t);          \
+       _t AR5K_BOOL (_a _n##_disable_pspoll)(struct ath_hal *);                
                \
+       /* Beacon Management Functions */                                       
                \
+       _t void (_a _n##_init_beacon)(struct ath_hal *, u_int32_t nexttbtt, 
u_int32_t intval);  \
+       _t void (_a _n##_set_beacon_timers)(struct ath_hal *, const 
AR5K_BEACON_STATE *);       \
+       _t void (_a _n##_reset_beacon)(struct ath_hal *);                       
                \
+       _t AR5K_BOOL (_a _n##_wait_for_beacon)(struct ath_hal *, 
AR5K_BUS_ADDR);                \
+       /* Interrupt functions */                                               
                \
+       _t AR5K_BOOL (_a _n##_is_intr_pending)(struct ath_hal *);               
                \
+       _t AR5K_BOOL (_a _n##_get_isr)(struct ath_hal *, u_int32_t *);          
                \
+       _t u_int32_t (_a _n##_get_intr)(struct ath_hal *);                      
                \
+       _t AR5K_INT (_a _n##_set_intr)(struct ath_hal *, AR5K_INT);             
                \
+       /* Chipset functions (ar5k-specific, non-HAL) */                        
                \
+       _t AR5K_BOOL (_a _n##_get_capabilities)(struct ath_hal *);              
                \
+       _t void (_a _n##_radar_alert)(struct ath_hal *, AR5K_BOOL enable);      
                \
+       _t AR5K_BOOL (_a _n##_eeprom_is_busy)(struct ath_hal *);                
                \
+       _t int (_a _n##_eeprom_read)(struct ath_hal *, u_int32_t offset, 
u_int16_t *data);      \
+       _t int (_a _n##_eeprom_write)(struct ath_hal *, u_int32_t offset, 
u_int16_t data);      \
+       /* Functions not found in OpenBSD */                                    
                \
+       _t AR5K_BOOL (_a _n##_get_tx_queueprops)(struct ath_hal *, int, 
AR5K_TXQ_INFO *);       \
+       _t AR5K_STATUS (_a _n##_get_capability)(struct ath_hal *, 
AR5K_CAPABILITY_TYPE,         \
+                               u_int32_t, u_int32_t *);                        
                \
+       _t u_int32_t  (_a _n##_num_tx_pending)(struct ath_hal *, u_int);        
                \
+       _t AR5K_BOOL (_a _n##_phy_disable)(struct ath_hal *);                   
                \
+       _t void (_a _n##_set_pcu_config)(struct ath_hal *);                     
                \
+       _t AR5K_BOOL (_a _n##_set_txpower_limit)(struct ath_hal *, u_int);      
                \
+       _t void (_a _n##_set_def_antenna)(struct ath_hal *, u_int);             
                \
+       _t u_int  (_a _n ##_get_def_antenna)(struct ath_hal *);                 
                \
+       _t AR5K_BOOL (_a _n ##_set_bssid_mask)(struct ath_hal *, const 
u_int8_t*);              \
+       /*Totaly unimplemented*/                                                
                \
+       _t AR5K_BOOL (_a _n##_set_capability)(struct ath_hal *, 
AR5K_CAPABILITY_TYPE, u_int32_t,\
+                               u_int32_t,AR5K_STATUS *) ;                      
                \
+       _t void (_a _n##_proc_mib_event)(struct ath_hal *, const 
AR5K_NODE_STATS *) ;           \
+       _t void (_a _n##_get_tx_inter_queue)(struct ath_hal *, u_int32_t *);
+
+
+#define AR5K_MAX_GPIO          10
+#define AR5K_MAX_RF_BANKS      8
+
+struct ath_hal {
+       u_int32_t               ah_magic;
+       u_int16_t               ah_device;
+       u_int16_t               ah_sub_vendor;
+
+       AR5K_SOFTC              ah_sc;
+       bus_space_tag_t         ah_st;
+       bus_space_handle_t      ah_sh;
+       AR5K_CTRY_CODE          ah_country_code;
+
+       AR5K_INT                        ah_imr;
+
+       AR5K_OPMODE             ah_op_mode;
+       AR5K_POWER_MODE         ah_power_mode;
+       AR5K_CHANNEL            ah_current_channel;
+       AR5K_BOOL               ah_turbo;
+       AR5K_BOOL               ah_calibration;
+       AR5K_BOOL               ah_running;
+       AR5K_BOOL               ah_single_chip;
+       AR5K_RFGAIN             ah_rf_gain;
+
+       AR5K_RATE_TABLE         ah_rt_11a;
+       AR5K_RATE_TABLE         ah_rt_11b;
+       AR5K_RATE_TABLE         ah_rt_11g;
+       AR5K_RATE_TABLE         ah_rt_turbo;
+       AR5K_RATE_TABLE         ah_rt_xr;
+
+       u_int32_t               ah_mac_srev;
+       u_int16_t               ah_mac_version;
+       u_int16_t               ah_mac_revision;
+       u_int16_t               ah_phy_revision;
+       u_int16_t               ah_radio_5ghz_revision;
+       u_int16_t               ah_radio_2ghz_revision;
+
+       enum ath5k_version      ah_version;
+       enum ath5k_radio                ah_radio;
+       u_int32_t               ah_phy;
+
+       AR5K_BOOL               ah_5ghz;
+       AR5K_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
+
+       u_int32_t               ah_atim_window;
+       u_int32_t               ah_aifs;
+       u_int32_t               ah_cw_min;
+       u_int32_t               ah_cw_max;
+       AR5K_BOOL               ah_software_retry;
+       u_int32_t               ah_limit_tx_retries;
+
+       u_int32_t               ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+       AR5K_BOOL               ah_ant_diversity;
+
+       u_int8_t                ah_sta_id[IEEE80211_ADDR_LEN];
+       u_int8_t                ah_bssid[IEEE80211_ADDR_LEN];
+
+       u_int32_t               ah_gpio[AR5K_MAX_GPIO];
+       int                     ah_gpio_npins;
+
+       ath5k_capabilities_t    ah_capabilities;
+
+       AR5K_TXQ_INFO           ah_txq[AR5K_NUM_TX_QUEUES];
+       u_int32_t               ah_txq_interrupts;
+
+       u_int32_t               *ah_rf_banks;
+       size_t                  ah_rf_banks_size;
+       struct ath5k_gain       ah_gain;
+       u_int32_t               ah_offset[AR5K_MAX_RF_BANKS];
+
+       struct {
+               u_int16_t       txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE];
+               u_int16_t       txp_rates[AR5K_MAX_RATES];
+               int16_t         txp_min, txp_max;
+               AR5K_BOOL       txp_tpc;
+               int16_t         txp_ofdm;
+       } ah_txpower;
+
+       struct {
+               AR5K_BOOL       r_enabled;
+               int             r_last_alert;
+               AR5K_CHANNEL    r_last_channel;
+       } ah_radar;
+
+       /*
+        * Function pointers
+        */
+       AR5K_HAL_FUNCTIONS(, ah, *)
+
+};
+
+/*
+ * Prototypes
+ */
+
+const char             *ath_hal_probe(u_int16_t, u_int16_t);
+struct ath_hal         *ath5k_hw_init(u_int16_t device, AR5K_SOFTC sc, 
AR5K_BUS_TAG,
+                                       AR5K_BUS_HANDLE, AR5K_STATUS *);
+u_int16_t              ath_hal_computetxtime(struct ath_hal *, const 
AR5K_RATE_TABLE *,
+                                       u_int32_t, u_int16_t, AR5K_BOOL);
+u_int                  ath_hal_mhz2ieee(u_int, u_int);
+u_int                  ath_hal_ieee2mhz(u_int, u_int);
+AR5K_BOOL              ath_hal_init_channels(struct ath_hal *, AR5K_CHANNEL *,
+                                       u_int, u_int *, AR5K_CTRY_CODE, 
u_int16_t, 
+                                       AR5K_BOOL, AR5K_BOOL);
+const char             *ath5k_printver(enum ath5k_srev_type, u_int32_t);
+void                   ath5k_radar_alert(struct ath_hal *);
+ieee80211_regdomain_t  ath5k_regdomain_to_ieee(u_int16_t);
+u_int16_t              ath5k_regdomain_from_ieee(ieee80211_regdomain_t);
+u_int16_t              ath5k_get_regdomain(struct ath_hal *);
+u_int32_t              ath5k_bitswap(u_int32_t, u_int);
+inline u_int           ath5k_clocktoh(u_int, AR5K_BOOL);
+inline u_int           ath5k_htoclock(u_int, AR5K_BOOL);
+void                   ath5k_rt_copy(AR5K_RATE_TABLE *, const AR5K_RATE_TABLE 
*);
+AR5K_BOOL              ath5k_register_timeout(struct ath_hal *, u_int32_t, 
u_int32_t,
+                                       u_int32_t, AR5K_BOOL);
+int                    ath5k_eeprom_init(struct ath_hal *);
+int                    ath5k_eeprom_read_mac(struct ath_hal *, u_int8_t *);
+AR5K_BOOL              ath5k_eeprom_regulation_domain(struct ath_hal *, 
AR5K_BOOL,
+                                       ieee80211_regdomain_t *);
+int                    ath5k_eeprom_read_ants(struct ath_hal *, u_int32_t *, 
u_int);
+int                    ath5k_eeprom_read_modes(struct ath_hal *, u_int32_t *, 
u_int);
+u_int16_t              ath5k_eeprom_bin2freq(struct ath_hal *, u_int16_t, 
u_int);
+
+AR5K_BOOL              ath5k_channel(struct ath_hal *, AR5K_CHANNEL *);
+AR5K_BOOL              ath5k_ar5110_channel(struct ath_hal *, AR5K_CHANNEL *);
+u_int32_t              ath5k_ar5110_chan2athchan(AR5K_CHANNEL *);
+AR5K_BOOL              ath5k_ar5111_channel(struct ath_hal *, AR5K_CHANNEL *);
+AR5K_BOOL              ath5k_ar5111_chan2athchan(u_int, struct 
ath5k_athchan_2ghz *);
+AR5K_BOOL              ath5k_ar5112_channel(struct ath_hal *, AR5K_CHANNEL *);
+AR5K_BOOL              ath5k_check_channel(struct ath_hal *, u_int16_t, u_int 
flags);
+
+AR5K_BOOL              ath5k_rfregs(struct ath_hal *, AR5K_CHANNEL *, u_int);
+AR5K_BOOL              ath5k_ar5111_rfregs(struct ath_hal *, AR5K_CHANNEL *, 
u_int);
+AR5K_BOOL              ath5k_ar5112_rfregs(struct ath_hal *, AR5K_CHANNEL *, 
u_int);
+void                   ath5k_ar5211_rfregs(struct ath_hal *, AR5K_CHANNEL *, 
u_int, u_int);
+u_int                  ath5k_rfregs_op(u_int32_t *, u_int32_t, u_int32_t, 
u_int32_t,
+                                       u_int32_t, u_int32_t, AR5K_BOOL);
+u_int32_t              ath5k_rfregs_gainf_corr(struct ath_hal *);
+AR5K_BOOL              ath5k_rfregs_gain_readback(struct ath_hal *);
+int32_t                        ath5k_rfregs_gain_adjust(struct ath_hal *);
+AR5K_BOOL              ath5k_rfgain(struct ath_hal *, u_int, u_int);
+void                   ath5k_txpower_table(struct ath_hal *, AR5K_CHANNEL *, 
int16_t);
+
+/*added*/
+extern u_int  ath_hal_getwirelessmodes(struct ath_hal*, AR5K_CTRY_CODE);
+void ath_hal_detach(struct ath_hal *ah);
+struct ath_hal * _ath_hal_attach(u_int16_t devid, AR5K_SOFTC sc, AR5K_BUS_TAG 
t,
+                                       AR5K_BUS_HANDLE h, void* s);
+#endif /* _AR5K_H */

Added: branches/madwifi-old-openhal/openhal/ath5k_hw.c
===================================================================
--- branches/madwifi-old-openhal/openhal/ath5k_hw.c                             
(rev 0)
+++ branches/madwifi-old-openhal/openhal/ath5k_hw.c     2007-03-27 17:29:30 UTC 
(rev 2232)
@@ -0,0 +1,5873 @@
+/*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@xxxxxxxxxxx>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@xxxxxxxxx>
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * HAL interface for Atheros Wireless LAN devices.
+ * (Please have a look at ar5xxx.h for further information)
+ */
+
+#include "ah_devid.h"
+#include "ath5k.h"
+#include "ath5kreg.h"
+
+/* 
+ * Known pci ids
+ */
+
+static const struct {
+       u_int16_t       vendor;
+       u_int16_t       device;
+       u_int8_t        mac_version;
+} ath5k_known_products[] = {
+       /*
+        * From pcidevs_data.h
+        */
+       /* 5210 is not supported yet
+       { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210,AR5K_AR5210},
+       { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_AP,AR5K_AR5210},
+       { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_DEFAULT,AR5K_AR5210},*/
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5211,        AR5K_AR5211},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5211_DEFAULT,AR5K_AR5211},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5311,        AR5K_AR5211},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5211_FPGA11B,AR5K_AR5211},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5211_LEGACY, AR5K_AR5211},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212,        AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_DEFAULT,AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_FPGA,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_IBM,    AR5K_AR5212},
+       { PCI_VENDOR_3COM,      PCI_PRODUCT_3COM_3CRDAG675,     AR5K_AR5212},
+       { PCI_VENDOR_3COM2,     PCI_PRODUCT_3COM2_3CRPAG175,    AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_REV2,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_REV7,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_REV8,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_0014,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_0015,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_0016,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_0017,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_0018,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5212_0019,   AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR2413,        AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5413,        AR5K_AR5212},
+       { PCI_VENDOR_ATHEROS,PCI_PRODUCT_ATHEROS_AR5424,        AR5K_AR5212},
+};
+
+/*Rate tables*/
+static const AR5K_RATE_TABLE ath5k_rt_11a = AR5K_RATES_11A;
+static const AR5K_RATE_TABLE ath5k_rt_11b = AR5K_RATES_11B;
+static const AR5K_RATE_TABLE ath5k_rt_11g = AR5K_RATES_11G;
+static const AR5K_RATE_TABLE ath5k_rt_turbo = AR5K_RATES_TURBO;
+static const AR5K_RATE_TABLE ath5k_rt_xr = AR5K_RATES_XR;
+
+/*Prototypes*/
+AR5K_BOOL      ath5k_hw_nic_reset(struct ath_hal *, u_int32_t);
+AR5K_BOOL      ath5k_hw_nic_wakeup(struct ath_hal *, u_int16_t);
+u_int16_t      ath5k_hw_radio_revision(struct ath_hal *, AR5K_CHIP);
+void           ath5k_hw_fill(struct ath_hal *);
+AR5K_BOOL      ath5k_hw_txpower(struct ath_hal *, AR5K_CHANNEL *, u_int);
+
+AR5K_HAL_FUNCTIONS(extern, ath5k_hw,);
+
+/*
+ * Supported channels
+ */
+static const struct
+ieee80211_regchannel ath5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ;
+static const struct
+ieee80211_regchannel ath5k_2ghz_channels[] = IEEE80211_CHANNELS_2GHZ;
+
+/*
+ * Initial register dumps
+ */
+static const struct ath5k_ar5212_ini ar5212_ini[] = AR5K_AR5212_INI;
+static const struct ath5k_ar5212_ini_mode ar5212_mode[] = AR5K_AR5212_INI_MODE;
+static const struct ath5k_ini ar5211_ini[] = AR5K_AR5211_INI;
+static const struct ath5k_ar5211_ini_mode ar5211_mode[] = AR5K_AR5211_INI_MODE;
+static const struct ath5k_ar5211_ini_rf ar5211_rf[] = AR5K_AR5211_INI_RF;
+
+/*
+ * Initial gain optimization values
+ */
+static const struct ath5k_gain_opt ar5111_gain_opt = AR5K_AR5111_GAIN_OPT;
+static const struct ath5k_gain_opt ar5112_gain_opt = AR5K_AR5112_GAIN_OPT;
+
+/*
+ * Initial register for the radio chipsets
+ */
+static const struct ath5k_ini_rf ar5111_rf[] = AR5K_AR5111_INI_RF;
+static const struct ath5k_ini_rf ar5112_rf[] = AR5K_AR5112_INI_RF;
+static const struct ath5k_ini_rf ar5112a_rf[] = AR5K_AR5112A_INI_RF;
+static const struct ath5k_ini_rfgain ath5k_rfg[] = AR5K_INI_RFGAIN;
+
+/*
+ * Enable to overwrite the country code (use "00" for debug)
+ */
+#if 0
+#define COUNTRYCODE "00"
+#endif
+
+/*******************\
+  General Functions
+\*******************/
+
+/*
+ * Perform a lookup if the device is supported by the HAL
+ * and return the chip name.
+ * TODO:Left here for combatibility, change it in at5k
+ */
+const char *
+ath_hal_probe(u_int16_t vendor, u_int16_t device)
+{
+       int i;
+
+       /*
+        * Perform a linear search on the table of supported devices
+        */
+       for (i = 0; i < AR5K_ELEMENTS(ath5k_known_products); i++) {
+               if (vendor == ath5k_known_products[i].vendor &&
+                   device == ath5k_known_products[i].device){
+                       switch (ath5k_known_products[i].mac_version) {
+                               case AR5K_AR5210:
+                                       return("AR5210");
+                               case AR5K_AR5211:
+                                       return("AR5211");
+                               case AR5K_AR5212:
+                                       return("AR5212");
+                               default:
+                                       return ("");
+                       }
+               }
+       }
+
+       return (NULL);
+}
+
+/*
+ * Calculate transmition time of a frame
+ * TODO:Left here for combatibility, change it in at5k
+ */
+u_int16_t /*TODO: Is this realy hardware dependent ?*/
+ath_hal_computetxtime(struct ath_hal *hal, const AR5K_RATE_TABLE *rates,
+    u_int32_t frame_length, u_int16_t rate_index, AR5K_BOOL short_preamble)
+{
+       const AR5K_RATE *rate;
+       u_int32_t value;
+
+       AR5K_ASSERT_ENTRY(rate_index, rates->rate_count);
+
+       /*
+        * Get rate by index
+        */
+       rate = &rates->rates[rate_index];
+
+       /*
+        * Calculate the transmission time by operation (PHY) mode
+        */
+       switch (rate->modulation) {
+       case MODULATION_CCK:
+               /*
+                * CCK / DS mode (802.11b)
+                */
+               value = AR5K_CCK_TX_TIME(rate->rate_kbps, frame_length,
+                   (short_preamble && (rate->modulation == 
MODULATION_CCK_SP)));
+               break;
+
+       case MODULATION_OFDM:
+               /*
+                * Orthogonal Frequency Division Multiplexing
+                */
+               if (AR5K_OFDM_NUM_BITS_PER_SYM(rate->rate_kbps) == 0)
+                       return (0);
+               value = AR5K_OFDM_TX_TIME(rate->rate_kbps, frame_length);
+               break;
+
+       case MODULATION_TURBO:
+               /*
+                * Orthogonal Frequency Division Multiplexing
+                * Atheros "Turbo Mode" (doubled rates)
+                */
+               if (AR5K_TURBO_NUM_BITS_PER_SYM(rate->rate_kbps) == 0)
+                       return (0);
+               value = AR5K_TURBO_TX_TIME(rate->rate_kbps, frame_length);
+               break;
+
+       case MODULATION_XR:
+               /*
+                * Orthogonal Frequency Division Multiplexing
+                * Atheros "eXtended Range" (XR)
+                */
+               if (AR5K_XR_NUM_BITS_PER_SYM(rate->rate_kbps) == 0)
+                       return (0);
+               value = AR5K_XR_TX_TIME(rate->rate_kbps, frame_length);
+               break;
+
+       default:
+               return (0);
+       }
+
+       return (value);
+}
+
+/*
+ * Return the supported 802.11 operation modes
+ * TODO:Left here for combatibility, change it in at5k
+ */
+u_int/*TODO:Fix this & fix g support*/
+ath_hal_getwirelessmodes(struct ath_hal *hal, AR5K_CTRY_CODE country) 
+{
+       switch(hal->ah_version){
+       case AR5K_AR5212:
+               return (AR5K_MODE_11A|AR5K_MODE_11B);
+       case AR5K_AR5211:
+               return (AR5K_MODE_11A|AR5K_MODE_11B);
+       default :
+               return(AR5K_MODE_11A);
+       }
+}
+
+/*
+ * Functions used internaly
+ */
+
+u_int32_t
+ath5k_hw_bitswap(u_int32_t val, u_int bits)
+{
+       u_int32_t retval = 0, bit, i;
+
+       for (i = 0; i < bits; i++) {
+               bit = (val >> i) & 1;
+               retval = (retval << 1) | bit;
+       }
+
+       return (retval);
+}
+
+inline u_int
+ath5k_hw_htoclock(u_int usec, AR5K_BOOL turbo)
+{
+       return (turbo == TRUE ? (usec * 80) : (usec * 40));
+}
+
+inline u_int
+ath5k_hw_clocktoh(u_int clock, AR5K_BOOL turbo)
+{
+       return (turbo == TRUE ? (clock / 80) : (clock / 40));
+}
+
+/*
+ * Copy a rate table to a new one
+ */
+inline void
+ath5k_hw_rtcopy(AR5K_RATE_TABLE *dst, const AR5K_RATE_TABLE *src)
+{
+       bzero(dst, sizeof(AR5K_RATE_TABLE));
+       dst->rate_count = src->rate_count;
+       bcopy(src->rates, dst->rates, sizeof(dst->rates));
+}
+
+/*
+ * Read from a device register
+ */
+static inline u32 ath5k_hw_reg_read(struct ath_hal *hal, u16 reg)
+{
+       return readl(hal->ah_sh + reg);
+}
+
+/*
+ * Write to a device register
+ */
+static inline void ath5k_hw_reg_write(struct ath_hal *hal, u32 val, u16 reg)
+{
+       writel(val, hal->ah_sh + reg);
+}
+
+/*
+ * Check if a register write has been completed
+ */
+AR5K_BOOL
+ath5k_hw_register_timeout(struct ath_hal *hal, u_int32_t reg, u_int32_t flag,
+    u_int32_t val, AR5K_BOOL is_set)
+{
+       int i;
+       u_int32_t data;
+
+       for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+               data = AR5K_REG_READ(reg);
+               if ((is_set == TRUE) && (data & flag))
+                       break;
+               else if ((data & flag) == val)
+                       break;
+               AR5K_DELAY(15);
+       }
+
+       if (i <= 0)
+               return (FALSE);
+
+       return (TRUE);
+}
+
+
+
+/***************************************\
+       Attach/Detach Functions
+\***************************************/
+
+/*
+ * Check if the device is supported and initialize the needed structs
+ */
+struct ath_hal *
+ath5k_hw_init(u_int16_t device, AR5K_SOFTC sc, AR5K_BUS_TAG st,
+               AR5K_BUS_HANDLE sh, AR5K_STATUS *status)
+{
+       struct ath_hal *hal = NULL;
+       u_int8_t mac[IEEE80211_ADDR_LEN];
+       u_int8_t mac_version = 255; /*Initialize this to something else than 
ath5k_version*/
+       int i;
+       u_int32_t srev;
+       *status = AR5K_EINVAL;
+
+       /*TODO:Use eeprom_magic to verify chipset*/
+
+       /*
+        * Check if device is a known one
+        */
+       for (i = 0; i < AR5K_ELEMENTS(ath5k_known_products); i++) {
+               if (device == ath5k_known_products[i].device)
+                       mac_version = ath5k_known_products[i].mac_version;
+       }
+
+       /*If there wasn't a match, the device is not supported*/
+       if (mac_version == 255) {
+               *status = AR5K_ENOTSUPP;
+               AR5K_PRINTF("device not supported: 0x%04x\n", device);
+               return (NULL);
+       }
+
+       /*If we passed the test malloc a hal struct*/
+       if ((hal = malloc(sizeof(struct ath_hal),
+                M_DEVBUF, M_NOWAIT)) == NULL) {
+               *status = AR5K_ENOMEM;
+               AR5K_PRINT("out of memory\n");
+               return (NULL);
+       }
+
+       /*Initialize it*/
+       bzero(hal, sizeof(struct ath_hal));
+
+       hal->ah_sc = sc;
+       hal->ah_st = st;
+       hal->ah_sh = sh;
+       hal->ah_device = device;
+       hal->ah_sub_vendor = 0; /* XXX unknown?! */
+
+       /*
+        * HAL information
+        */
+
+       /* Regulation Stuff */
+       hal->ah_country_code = AR5K_TUNE_CTRY;
+       ath5k_get_regdomain(hal);
+
+       hal->ah_op_mode = AR5K_M_STA;
+       hal->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
+       hal->ah_turbo = FALSE;
+       hal->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+       hal->ah_imr = 0;
+       hal->ah_atim_window = 0;
+       hal->ah_aifs = AR5K_TUNE_AIFS;
+       hal->ah_cw_min = AR5K_TUNE_CWMIN;
+       hal->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
+       hal->ah_software_retry = FALSE;
+       hal->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
+
+       switch (device) {
+               case PCI_PRODUCT_ATHEROS_AR2413:
+               case PCI_PRODUCT_ATHEROS_AR5413:
+               case PCI_PRODUCT_ATHEROS_AR5424:
+                       /*
+                        * Known single chip solutions
+                        */
+                       hal->ah_single_chip = TRUE;
+                       break;
+               default:
+                       /*
+                        * Multi chip solutions
+                        */
+                       hal->ah_single_chip = FALSE;
+                       break;
+       }
+
+       /*
+        * Set the mac revision based on the pci id
+        */
+       hal->ah_version = mac_version;
+
+       /*Fill the hal struct with the needed functions*/
+       ath5k_hw_fill(hal);
+
+       /* Bring device out of sleep and reset it's units */
+       if (ath5k_hw_nic_wakeup(hal, AR5K_INIT_MODE) != TRUE)
+               goto failed;
+
+       /* Get MAC, PHY and RADIO revisions */
+       srev = AR5K_REG_READ(AR5K_SREV);
+       hal->ah_mac_srev = srev;
+       hal->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+       hal->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
+       hal->ah_phy_revision = AR5K_REG_READ(AR5K_PHY_CHIP_ID) &
+           0x00ffffffff;
+       hal->ah_radio_5ghz_revision =
+           ath5k_hw_radio_revision(hal, AR5K_CHIP_5GHZ);
+       hal->ah_radio_2ghz_revision =
+           ath5k_hw_radio_revision(hal, AR5K_CHIP_2GHZ);
+
+       /* Single chip radio */
+       if (hal->ah_radio_2ghz_revision == hal->ah_radio_5ghz_revision)
+               hal->ah_radio_2ghz_revision = 0;
+
+       /* Identify the radio chip*/
+       hal->ah_radio = hal->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112 ?
+                                               AR5K_AR5111 : AR5K_AR5112;
+
+       hal->ah_phy = AR5K_PHY(0);
+
+       /*Is this bcopy O.K. ?*/
+       bcopy(etherbroadcastaddr, mac, IEEE80211_ADDR_LEN);
+
+       ath5k_hw_set_associd(hal, mac, 0);
+       ath5k_hw_get_lladdr(hal, mac);
+       ath5k_hw_set_opmode(hal);
+               
+#ifdef AR5K_DEBUG
+       hal->ah_dump_state(hal);
+#endif
+
+       /*
+        * Get card capabilities, values, ...
+        */
+
+       if (ath5k_eeprom_init(hal) != 0) {
+               *status = AR5K_EELOCKED;
+               AR5K_PRINT("unable to init EEPROM\n");
+               goto failed;
+       }
+
+       /* Get misc capabilities */
+       if (hal->ah_get_capabilities(hal) != TRUE) {
+               *status = AR5K_EEREAD;
+               AR5K_PRINTF("unable to get device capabilities: 0x%04x\n",
+                   device);
+               goto failed;
+       }
+
+       /* Get MAC address */
+       if ((*status = ath5k_eeprom_read_mac(hal, mac)) != 0) {
+               *status = AR5K_EEBADMAC;
+               AR5K_PRINTF("unable to read address from EEPROM: 0x%04x\n",
+                   device);
+               goto failed;
+       }
+
+       hal->ah_set_lladdr(hal, mac);
+
+       /* Get rate tables */
+       if (hal->ah_capabilities.cap_mode & AR5K_MODE_11A)
+               ath5k_hw_rtcopy(&hal->ah_rt_11a, &ath5k_rt_11a);
+       if (hal->ah_capabilities.cap_mode & AR5K_MODE_11B)
+               ath5k_hw_rtcopy(&hal->ah_rt_11b, &ath5k_rt_11b);
+       if (hal->ah_capabilities.cap_mode & AR5K_MODE_11G)
+               ath5k_hw_rtcopy(&hal->ah_rt_11g, &ath5k_rt_11g);
+       if (hal->ah_capabilities.cap_mode & AR5K_MODE_TURBO)
+               ath5k_hw_rtcopy(&hal->ah_rt_turbo, &ath5k_rt_turbo);
+       if (hal->ah_capabilities.cap_mode & AR5K_MODE_XR)
+               ath5k_hw_rtcopy(&hal->ah_rt_xr, &ath5k_rt_xr);
+
+       /* Initialize the gain optimization values */
+       /*For RF5111*/
+       if (hal->ah_radio == AR5K_AR5111) {
+               hal->ah_gain.g_step_idx = ar5111_gain_opt.go_default;
+               hal->ah_gain.g_step =
+                   &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
+               hal->ah_gain.g_low = 20;
+               hal->ah_gain.g_high = 35;
+               hal->ah_gain.g_active = 1;
+       /*For RF5112*/
+       } else if (hal->ah_radio == AR5K_AR5112) {
+               hal->ah_gain.g_step_idx = ar5112_gain_opt.go_default;
+               hal->ah_gain.g_step =
+                   &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
+               hal->ah_gain.g_low = 20;
+               hal->ah_gain.g_high = 85;
+               hal->ah_gain.g_active = 1;
+       }
+
+       *status = AR5K_OK;
+
+       return (hal);
+
+ failed:
+       free(hal, M_DEVBUF);
+       return (NULL);
+}
+
+/*
+ * Bring up MAC + PHY Chips
+ */
+AR5K_BOOL
+ath5k_hw_nic_wakeup(struct ath_hal *hal, u_int16_t flags)
+{
+       u_int32_t turbo, mode, clock;
+
+       turbo = 0;
+       mode = 0;
+       clock = 0;
+
+       AR5K_TRACE;
+
+       /*
+        * Get channel mode flags
+        */
+ 
+       if (hal->ah_radio >= AR5K_AR5112) {
+               mode = AR5K_PHY_MODE_RAD_AR5112;
+               clock = AR5K_PHY_PLL_AR5112;
+       } else {
+               mode = AR5K_PHY_MODE_RAD_AR5111;        /*Zero -backwards 
combatible*/
+               clock = AR5K_PHY_PLL_AR5111;            /*Zero -backwards 
combatible*/
+       }
+
+       if (flags & CHANNEL_2GHZ) {
+               mode |= AR5K_PHY_MODE_FREQ_2GHZ;
+               clock |= AR5K_PHY_PLL_44MHZ;
+       } else if (flags & CHANNEL_5GHZ) {
+               mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+               clock |= AR5K_PHY_PLL_40MHZ;
+       } else {
+               AR5K_PRINT("invalid radio frequency mode\n");
+               return (FALSE);
+       }
+
+       if (flags & CHANNEL_CCK) {
+               mode |= AR5K_PHY_MODE_MOD_CCK;
+       } else if (flags & CHANNEL_OFDM) {
+               mode |= AR5K_PHY_MODE_MOD_OFDM;
+       } else if (flags & CHANNEL_DYN) {
+               /* Dynamic OFDM/CCK is not supported by the AR5211 */
+               if (hal->ah_version == AR5K_AR5211){
+                       mode |= AR5K_PHY_MODE_MOD_CCK;
+               }else{
+                       mode |= AR5K_PHY_MODE_MOD_DYN;
+               }
+       } else {
+               AR5K_PRINT("invalid radio frequency mode\n");
+               return (FALSE);
+       }
+
+       if (flags & CHANNEL_TURBO) {
+               turbo = AR5K_PHY_TURBO_MODE |
+                   AR5K_PHY_TURBO_SHORT;
+       }
+
+       /*
+        * Reset and wakeup the device
+        */
+
+       /* ...reset chipset and PCI device */
+       if (hal->ah_single_chip == FALSE &&
+       ath5k_hw_nic_reset(hal,AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI) == 
FALSE) {
+               AR5K_PRINT("failed to reset the MAC + PCI Chipset\n");
+               return (FALSE);
+       }
+
+       /* ...wakeup */
+       if (ath5k_hw_set_power(hal,
+               AR5K_PM_AWAKE, TRUE, 0) == FALSE) {
+               AR5K_PRINT("failed to resume the MAC Chip (again)\n");
+               return (FALSE);
+       }
+
+       /* ...final warm reset */
+       if (ath5k_hw_nic_reset(hal, 0) == FALSE) {
+               AR5K_PRINT("failed to warm reset the MAC Chip\n");
+               return (FALSE);
+       }
+
+       /* ...set the PHY operating mode */
+       AR5K_REG_WRITE(AR5K_PHY_PLL, clock);
+       AR5K_DELAY(300);
+
+       AR5K_REG_WRITE(AR5K_PHY_MODE, mode);
+       AR5K_REG_WRITE(AR5K_PHY_TURBO, turbo);
+
+       return (TRUE);
+}
+
+/*
+ * Get the PHY Chip revision
+ */
+u_int16_t
+ath5k_hw_radio_revision(struct ath_hal *hal, AR5K_CHIP chip)
+{
+       int i;
+       u_int32_t srev;
+       u_int16_t ret;
+
+       AR5K_TRACE;
+
+       /*
+        * Set the radio chip access register
+        */
+       switch (chip) {
+       case AR5K_CHIP_2GHZ:
+               AR5K_REG_WRITE(AR5K_PHY(0), AR5K_PHY_SHIFT_2GHZ);
+               break;
+       case AR5K_CHIP_5GHZ:
+               AR5K_REG_WRITE(AR5K_PHY(0), AR5K_PHY_SHIFT_5GHZ);
+               break;
+       default:
+               return (0);
+       }
+
+       AR5K_DELAY(2000);
+
+       /* ...wait until PHY is ready and read the selected radio revision */
+       AR5K_REG_WRITE(AR5K_PHY(0x34), 0x00001c16);
+
+       for (i = 0; i < 8; i++)
+               AR5K_REG_WRITE(AR5K_PHY(0x20), 0x00010000);
+       srev = (AR5K_REG_READ(AR5K_PHY(0x100)) >> 24) & 0xff;
+
+       ret = ath5k_hw_bitswap(((srev & 0xf0) >> 4) | ((srev & 0x0f) << 4), 8);
+
+       /* Reset to the 5GHz mode */
+       AR5K_REG_WRITE(AR5K_PHY(0), AR5K_PHY_SHIFT_5GHZ);
+
+       return (ret);
+}
+
+/*
+ * Get the rate table for a specific operation mode
+ */
+const AR5K_RATE_TABLE *
+ath5k_hw_get_rate_table(struct ath_hal *hal, u_int mode)
+{
+
+       AR5K_TRACE;
+
+       switch (mode) {
+       case AR5K_MODE_11A:
+               return (&hal->ah_rt_11a);
+       case AR5K_MODE_TURBO:
+               return (&hal->ah_rt_turbo);
+       case AR5K_MODE_11B:
+               return (&hal->ah_rt_11b);
+       case AR5K_MODE_11G:
+               return (&hal->ah_rt_11g);
+       case AR5K_MODE_XR:
+               return (&hal->ah_rt_xr);
+       default:
+               return (NULL);
+       }
+
+       return (NULL);
+}
+
+/*
+ * Free the hal struct
+ */
+void
+ath5k_hw_detach(struct ath_hal *hal)
+{
+       AR5K_TRACE;
+
+       if (hal->ah_rf_banks != NULL)
+               free(hal->ah_rf_banks, M_DEVBUF);
+
+       /*
+        * Free HAL structure, assume interrupts are down
+        */
+       free(hal, M_DEVBUF);
+}
+
+
+
+
+/*******************************\
+       Reset Functions
+\*******************************/
+
+/*
+ * Main reset function
+ */
+AR5K_BOOL
+ath5k_hw_reset(struct ath_hal *hal, AR5K_OPMODE op_mode, AR5K_CHANNEL *channel,
+    AR5K_BOOL change_channel, AR5K_STATUS *status)
+{
+       struct ath5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+       u_int8_t mac[IEEE80211_ADDR_LEN];
+       u_int32_t data, s_seq, s_ant, s_led[3];
+       u_int i, phy, mode, freq, off, ee_mode, ant[2];
+       const AR5K_RATE_TABLE *rt;
+
+       AR5K_TRACE;
+
+       *status = AR5K_OK;
+
+       /*
+        * Save some registers before a reset
+        */
+       if (change_channel == TRUE) {
+               /*Sequence number for queue 0 -do this for all queues ?*/
+               s_seq = AR5K_REG_READ(AR5K_QUEUE_DFS_SEQNUM(0));
+               /*Default antenna*/
+               s_ant = AR5K_REG_READ(AR5K_DEFAULT_ANTENNA);
+       } else {
+               s_seq = 0;
+               s_ant = 1;
+       }
+
+       /*GPIOs*/
+       s_led[0] = AR5K_REG_READ(AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE;
+       s_led[1] = AR5K_REG_READ(AR5K_GPIOCR);
+       s_led[2] = AR5K_REG_READ(AR5K_GPIODO);
+
+       if (change_channel == TRUE && hal->ah_rf_banks != NULL)
+               ath5k_hw_get_rf_gain(hal);
+
+       if (ath5k_hw_nic_wakeup(hal, channel->channel_flags) == FALSE) {
+               *status = AR5K_EIO;
+               return (FALSE);
+       }
+
+       /*
+        * Initialize operating mode
+        */
+       hal->ah_op_mode = op_mode;
+
+       if (hal->ah_radio == AR5K_AR5111) {
+               phy = AR5K_INI_PHY_5111;
+       } else if (hal->ah_radio == AR5K_AR5112) {
+               phy = AR5K_INI_PHY_5112;
+       } else {
+               AR5K_PRINTF("invalid phy radio: %u\n", hal->ah_radio);
+               *status = AR5K_EINVAL;
+               return (FALSE);
+       }
+
+       switch (channel->channel_flags & CHANNEL_MODES) {
+       case CHANNEL_A:
+               mode = AR5K_INI_VAL_11A;
+               freq = AR5K_INI_RFGAIN_5GHZ;
+               ee_mode = AR5K_EEPROM_MODE_11A;
+               break;
+       case CHANNEL_B:
+               mode = AR5K_INI_VAL_11B;
+               freq = AR5K_INI_RFGAIN_2GHZ;
+               ee_mode = AR5K_EEPROM_MODE_11B;
+               break;
+       case CHANNEL_G:
+               mode = AR5K_INI_VAL_11G;
+               freq = AR5K_INI_RFGAIN_2GHZ;
+               ee_mode = AR5K_EEPROM_MODE_11G;
+               break;
+       case CHANNEL_T:
+               mode = AR5K_INI_VAL_11A_TURBO;
+               freq = AR5K_INI_RFGAIN_5GHZ;
+               ee_mode = AR5K_EEPROM_MODE_11A;
+               break;
+       /*Is this ok on 5211 too ?*/
+       case CHANNEL_TG:
+               mode = AR5K_INI_VAL_11G_TURBO;
+               freq = AR5K_INI_RFGAIN_2GHZ;
+               ee_mode = AR5K_EEPROM_MODE_11G;
+               break;
+       case CHANNEL_XR:
+               if(hal->ah_version == AR5K_AR5211){
+                       AR5K_PRINTF("XR mode not available on 5211");
+                       return (FALSE);
+               }
+               mode = AR5K_INI_VAL_XR;
+               freq = AR5K_INI_RFGAIN_5GHZ;
+               ee_mode = AR5K_EEPROM_MODE_11A;
+               break;
+       default:
+               AR5K_PRINTF("invalid channel: %d\n", channel->freq);
+               *status = AR5K_EINVAL;
+               return (FALSE);
+       }
+
+       /* PHY access enable */
+       AR5K_REG_WRITE(AR5K_PHY(0), AR5K_PHY_SHIFT_5GHZ);
+
+       /*
+        * Write initial RF registers on 5211
+        * do we need that ? Is ath5k_rfregs going to work for 5211 (5111) ?
+        */
+       if(hal->ah_version == AR5K_AR5211){
+               ath5k_ar5211_rfregs(hal, channel, freq, ee_mode);
+       }
+
+       /*
+        * Write initial mode settings
+        * TODO:Clean/merge arrays
+        */
+       /*For 5212*/
+       if(hal->ah_version == AR5K_AR5212){
+               for (i = 0; i < AR5K_ELEMENTS(ar5212_mode); i++) {
+                       if (ar5212_mode[i].mode_flags == AR5K_INI_FLAG_511X)
+                               off = AR5K_INI_PHY_511X;
+                       else if (ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5111 
&&
+                           hal->ah_radio == AR5K_AR5111)
+                               off = AR5K_INI_PHY_5111;
+                       else if (ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5112 
&&
+                           hal->ah_radio == AR5K_AR5112)
+                               off = AR5K_INI_PHY_5112;
+                       else
+                               continue;
+
+                       AR5K_REG_WAIT(i);
+                       AR5K_REG_WRITE((u_int32_t)ar5212_mode[i].mode_register,
+                           ar5212_mode[i].mode_value[off][mode]);
+               }
+       }
+       /*For 5211*/
+       if(hal->ah_version == AR5K_AR5211){
+               for (i = 0; i < AR5K_ELEMENTS(ar5211_mode); i++) {
+                       AR5K_REG_WAIT(i);
+                       AR5K_REG_WRITE((u_int32_t)ar5211_mode[i].mode_register,
+                           ar5211_mode[i].mode_value[mode]);
+               }
+       }
+
+       /*
+        * Write initial register settings
+        * TODO:Clean/merge arrays
+        */
+       /*For 5212*/
+       if(hal->ah_version == AR5K_AR5212){
+               for (i = 0; i < AR5K_ELEMENTS(ar5212_ini); i++) {
+                       if (change_channel == TRUE &&
+                           ar5212_ini[i].ini_register >= AR5K_PCU_MIN &&
+                           ar5212_ini[i].ini_register <= AR5K_PCU_MAX)
+                               continue;
+
+                       if ((hal->ah_radio == AR5K_AR5111 &&
+                           ar5212_ini[i].ini_flags & AR5K_INI_FLAG_5111) ||
+                           (hal->ah_radio == AR5K_AR5112 &&
+                           ar5212_ini[i].ini_flags & AR5K_INI_FLAG_5112)) {
+                               AR5K_REG_WAIT(i);
+                               
AR5K_REG_WRITE((u_int32_t)ar5212_ini[i].ini_register,
+                                   ar5212_ini[i].ini_value);
+                       }
+               }
+       }
+       /*For 5211*/
+       if(hal->ah_version == AR5K_AR5211){
+               for (i = 0; i < AR5K_ELEMENTS(ar5211_ini); i++) {
+                       if (change_channel == TRUE &&
+                           ar5211_ini[i].ini_register >= AR5K_PCU_MIN &&
+                           ar5211_ini[i].ini_register <= AR5K_PCU_MAX)
+                               continue;
+
+                       AR5K_REG_WAIT(i);
+                       AR5K_REG_WRITE((u_int32_t)ar5211_ini[i].ini_register,
+                           ar5211_ini[i].ini_value);
+               }
+       }
+
+       /*
+        * Write initial RF gain settings
+        * This should work for all chipsets
+        */
+       if (ath5k_rfgain(hal, phy, freq) == FALSE) {
+               *status = AR5K_EIO;
+               return (FALSE);
+       }
+
+       AR5K_DELAY(1000);
+
+       /*
+        * Set rate duration table on 5212
+        */
+       if(hal->ah_version == AR5K_AR5212){
+
+               /*For 802.11b*/
+               if (!(channel->channel_flags & CHANNEL_B)) {
+
+                       /*Get rate table for this operation mode*/
+                       rt = ath5k_hw_get_rate_table(hal, AR5K_MODE_11B);
+
+                       /*Write rate duration table*/
+                       for (i = 0; i < rt->rate_count; i++) {
+                               data = AR5K_RATE_DUR(rt->rates[i].rate_code);
+                               AR5K_REG_WRITE(data,
+                                   ath_hal_computetxtime(hal, rt, 14,
+                                   rt->rates[i].control_rate, FALSE));
+                               if (HAS_SHPREAMBLE(i)) {
+                                       AR5K_REG_WRITE(data +
+                                           (AR5K_SET_SHORT_PREAMBLE << 2),
+                                           ath_hal_computetxtime(hal, rt, 14,
+                                           rt->rates[i].control_rate, FALSE));
+                               }
+                       }
+
+               } else {
+               /*For 802.11a/g Turbo/XR mode (AR5K_MODE_XR here is O.K. for 
both a/g - OFDM)*/
+
+                       /*Get rate table for this operation mode*/
+                       rt = ath5k_hw_get_rate_table(hal,
+                           channel->channel_flags & CHANNEL_TURBO ?
+                           AR5K_MODE_TURBO : AR5K_MODE_XR);
+
+                       /*Write rate duration table*/
+                       for (i = 0; i < rt->rate_count; i++) {
+                               
AR5K_REG_WRITE(AR5K_RATE_DUR(rt->rates[i].rate_code),
+                                   ath_hal_computetxtime(hal, rt, 14,
+                                   rt->rates[i].control_rate, FALSE));
+                       }
+
+               }
+       }
+
+       /* Fix for first revision of the AR5112 RF chipset */
+       if (hal->ah_radio >= AR5K_AR5112 &&
+               hal->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
+                       AR5K_REG_WRITE(AR5K_PHY_CCKTXCTL,
+                       AR5K_PHY_CCKTXCTL_WORLD);
+               if (channel->channel_flags & CHANNEL_OFDM)
+                       data = 0xffb81020;
+               else
+                       data = 0xffb80d20;
+               AR5K_REG_WRITE(AR5K_PHY_FRAME_CTL, data);
+       }
+
+       /*
+        * Set TX power (XXX use txpower from net80211)
+        */
+       if (ath5k_hw_txpower(hal, channel,
+               AR5K_TUNE_DEFAULT_TXPOWER) == FALSE) {
+               *status = AR5K_EIO;
+               return (FALSE);
+       }
+
+       /*
+        * Write RF registers
+        * TODO:Does this work on 5211 (5111) ?
+        */
+       if (ath5k_rfregs(hal, channel, mode) == FALSE) {
+               *status = AR5K_EINPROGRESS;
+               return (FALSE);
+       }
+
+       /*
+        * Configure additional registers
+        */
+
+       /* Write OFDM timings on 5212*/
+       if(hal->ah_version == AR5K_AR5212){
+               if (channel->channel_flags & CHANNEL_OFDM) {
+                       u_int32_t coef_scaled, coef_exp, coef_man, ds_coef_exp,
+                           ds_coef_man, clock;
+
+                       clock = channel->channel_flags & CHANNEL_T ? 80 : 40;
+                       coef_scaled = ((5 * (clock << 24)) / 2) / channel->freq;
+
+                       for (coef_exp = 31; coef_exp > 0; coef_exp--)
+                               if ((coef_scaled >> coef_exp) & 0x1)
+                                       break;
+
+                       if (!coef_exp) {
+                               *status = AR5K_EINVAL;
+                               return (FALSE);
+                       }
+
+                       coef_exp = 14 - (coef_exp - 24);
+                       coef_man = coef_scaled + (1 << (24 - coef_exp - 1));
+                       ds_coef_man = coef_man >> (24 - coef_exp);
+                       ds_coef_exp = coef_exp - 16;
+
+                       AR5K_REG_WRITE_BITS(AR5K_PHY_TIMING_3,
+                           AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
+                       AR5K_REG_WRITE_BITS(AR5K_PHY_TIMING_3,
+                           AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+               }
+       }
+
+       /*Enable/disable 802.11b mode on 5111
+       (enable 2111 frequency converter + CCK)*/
+       if (hal->ah_radio == AR5K_AR5111) {
+               if (channel->channel_flags & CHANNEL_B)
+                       AR5K_REG_ENABLE_BITS(AR5K_TXCFG,
+                           AR5K_TXCFG_B_MODE);
+               else
+                       AR5K_REG_DISABLE_BITS(AR5K_TXCFG,
+                           AR5K_TXCFG_B_MODE);
+       }
+
+       /* Set antenna mode */
+       AR5K_REG_MASKED_BITS(AR5K_PHY(0x44),
+           hal->ah_antenna[ee_mode][0], 0xfffffc06);
+
+               if (freq == AR5K_INI_RFGAIN_2GHZ)
+                       ant[0] = ant[1] = AR5K_ANT_FIXED_B;
+               else
+                       ant[0] = ant[1] = AR5K_ANT_FIXED_A;
+
+
+       AR5K_REG_WRITE(AR5K_PHY_ANT_SWITCH_TABLE_0,
+           hal->ah_antenna[ee_mode][ant[0]]);
+       AR5K_REG_WRITE(AR5K_PHY_ANT_SWITCH_TABLE_1,
+           hal->ah_antenna[ee_mode][ant[1]]);
+
+       /* Commit values from EEPROM */
+       if (hal->ah_radio == AR5K_AR5111)
+               AR5K_REG_WRITE_BITS(AR5K_PHY_FRAME_CTL,
+                   AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip);
+
+       AR5K_REG_WRITE(AR5K_PHY(0x5a),
+           AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]));
+
+       AR5K_REG_MASKED_BITS(AR5K_PHY(0x11),
+           (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, 0xffffc07f);
+       AR5K_REG_MASKED_BITS(AR5K_PHY(0x12),
+           (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, 0xfffc0fff);
+       AR5K_REG_MASKED_BITS(AR5K_PHY(0x14),
+           (ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
+           ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), 0xffff0000);
+
+       AR5K_REG_WRITE(AR5K_PHY(0x0d),
+           (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
+           (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
+           (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
+           (ee->ee_tx_frm2xpa_enable[ee_mode]));
+
+       AR5K_REG_MASKED_BITS(AR5K_PHY(0x0a),
+           ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
+       AR5K_REG_MASKED_BITS(AR5K_PHY(0x19),
+           (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
+       AR5K_REG_MASKED_BITS(AR5K_PHY(0x49), 4, 0xffffff01);
+
+       AR5K_REG_ENABLE_BITS(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]);
+
+       if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
+               AR5K_REG_WRITE_BITS(AR5K_PHY_GAIN_2GHZ,
+                   AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+                   ee->ee_margin_tx_rx[ee_mode]);
+       }
+
+       /*
+        * Restore saved values
+        */
+       AR5K_REG_WRITE(AR5K_QUEUE_DFS_SEQNUM(0), s_seq);
+       AR5K_REG_WRITE(AR5K_DEFAULT_ANTENNA, s_ant);
+       AR5K_REG_ENABLE_BITS(AR5K_PCICFG, s_led[0]);
+       AR5K_REG_WRITE(AR5K_GPIOCR, s_led[1]);
+       AR5K_REG_WRITE(AR5K_GPIODO, s_led[2]);
+
+       /*
+        * Misc
+        */
+       bcopy(etherbroadcastaddr, mac, IEEE80211_ADDR_LEN);
+       ath5k_hw_set_associd(hal, mac, 0);
+       ath5k_hw_set_opmode(hal);
+       AR5K_REG_WRITE(AR5K_PISR, 0xffffffff);
+       AR5K_REG_WRITE(AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES);
+
+       /*
+        * Set Rx/Tx DMA Configuration
+        */
+       AR5K_REG_WRITE_BITS(AR5K_TXCFG, AR5K_TXCFG_SDMAMR,
+           AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE);
+       AR5K_REG_WRITE_BITS(AR5K_RXCFG, AR5K_RXCFG_SDMAMW,
+           AR5K_DMASIZE_512B);
+
+       /*
+        * Set channel and calibrate the PHY
+        */
+       if (ath5k_channel(hal, channel) == FALSE) {
+               *status = AR5K_EIO;
+               return (FALSE);
+       }
+
+       /*
+        * Enable the PHY and wait until completion
+        */
+       AR5K_REG_WRITE(AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE);
+
+       data = AR5K_REG_READ(AR5K_PHY_RX_DELAY) & AR5K_PHY_RX_DELAY_M;
+       data = (channel->channel_flags & CHANNEL_CCK) ?
+           ((data << 2) / 22) : (data / 10);
+
+       AR5K_DELAY(100 + data);
+
+       /*
+        * Start calibration
+        */
+       AR5K_REG_ENABLE_BITS(AR5K_PHY_AGCCTL,
+           AR5K_PHY_AGCCTL_NF |
+           AR5K_PHY_AGCCTL_CAL);
+
+
+       hal->ah_calibration = FALSE;
+
+       if (!(channel->channel_flags & CHANNEL_B)) {
+               hal->ah_calibration = TRUE;
+               AR5K_REG_WRITE_BITS(AR5K_PHY_IQ,
+                   AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+               AR5K_REG_ENABLE_BITS(AR5K_PHY_IQ,
+                   AR5K_PHY_IQ_RUN);
+       }
+
+       /*
+        * Reset queues and start beacon timers at the end of the reset routine
+        */
+       for (i = 0; i < hal->ah_capabilities.cap_queues.q_tx_num; i++) {
+               AR5K_REG_WRITE_Q(AR5K_QUEUE_QCUMASK(i), i);
+               if (ath5k_hw_reset_tx_queue(hal, i) == FALSE) {
+                       AR5K_PRINTF("failed to reset TX queue #%d\n", i);
+                       *status = AR5K_EINVAL;
+                       return (FALSE);
+               }
+       }
+
+       /* Pre-enable interrupts */
+       ath5k_hw_set_intr(hal, AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_FATAL);
+
+       /*
+        * Set RF kill flags if supported by the device (read from the EEPROM)
+        * Disable gpio_intr for now since it results system hang.
+        * TODO:Handle this in ath_intr
+        */
+/*     if (AR5K_EEPROM_HDR_RFKILL(hal->ah_capabilities.cap_eeprom.ee_header)) {
+               ath5k_hw_set_gpio_input(hal, 0);
+               if ((hal->ah_gpio[0] = ath5k_hw_get_gpio(hal, 0)) == 0)
+                       ath5k_hw_set_gpio_intr(hal, 0, 1);
+               else
+                       ath5k_hw_set_gpio_intr(hal, 0, 0);
+       }
+*/
+
+       /*
+        * Set the 32MHz reference clock on 5212 phy clock sleep register
+        */
+       if(hal->ah_version == AR5K_AR5212){
+               AR5K_REG_WRITE(AR5K_PHY_SCR, AR5K_PHY_SCR_32MHZ);
+               AR5K_REG_WRITE(AR5K_PHY_SLMT, AR5K_PHY_SLMT_32MHZ);
+               AR5K_REG_WRITE(AR5K_PHY_SCAL, AR5K_PHY_SCAL_32MHZ);
+               AR5K_REG_WRITE(AR5K_PHY_SCLOCK, AR5K_PHY_SCLOCK_32MHZ);
+               AR5K_REG_WRITE(AR5K_PHY_SDELAY, AR5K_PHY_SDELAY_32MHZ);
+               AR5K_REG_WRITE(AR5K_PHY_SPENDING, hal->ah_radio == AR5K_AR5111 ?
+                               AR5K_PHY_SPENDING_AR5111 : 
AR5K_PHY_SPENDING_AR5112);
+       }
+
+       /* 
+        * Disable beacons and reset the register
+        */
+       AR5K_REG_DISABLE_BITS(AR5K_BEACON,
+           AR5K_BEACON_ENABLE | AR5K_BEACON_RESET_TSF);
+
+       return (TRUE);
+}
+
+/*
+ * Reset chipset
+ */
+AR5K_BOOL
+ath5k_hw_nic_reset(struct ath_hal *hal, u_int32_t val)
+{
+       AR5K_BOOL ret = FALSE;
+       u_int32_t mask = val ? val : ~0;
+
+       AR5K_TRACE;
+
+       /* Read-and-clear RX Descriptor Pointer*/
+       AR5K_REG_READ(AR5K_RXDP);
+
+       /*
+        * Reset the device and wait until success
+        */
+       AR5K_REG_WRITE(AR5K_RESET_CTL, val);
+
+       /* Wait at least 128 PCI clocks */
+       AR5K_DELAY(15);
+
+       val &=
+           AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+
+       mask &=
+           AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+
+       ret = ath5k_hw_register_timeout(hal, AR5K_RESET_CTL, mask, val, FALSE);
+
+       /*
+        * Reset configuration register (for hw bitswap)
+        */
+       if ((val & AR5K_RESET_CTL_PCU) == 0)
+               AR5K_REG_WRITE(AR5K_CFG, AR5K_INIT_CFG);
+
+       return (ret);
+}
+
+/*
+ * Power management functions
+ */
+
+/*
+ * Sleep control
+ */
+AR5K_BOOL
+ath5k_hw_set_power(struct ath_hal *hal, AR5K_POWER_MODE mode,
+    AR5K_BOOL set_chip, u_int16_t sleep_duration)
+{
+       u_int32_t staid;
+       int i;
+
+       AR5K_TRACE;
+       staid = AR5K_REG_READ(AR5K_STA_ID1);
+
+       switch (mode) {
+       case AR5K_PM_AUTO:
+               staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
+               /* fallthrough */
+       case AR5K_PM_NETWORK_SLEEP:
+               if (set_chip == TRUE) {
+                       AR5K_REG_WRITE(AR5K_SLEEP_CTL,
+                           AR5K_SLEEP_CTL_SLE | sleep_duration);
+               }
+               staid |= AR5K_STA_ID1_PWR_SV;
+               break;
+
+       case AR5K_PM_FULL_SLEEP:
+               if (set_chip == TRUE) {
+                       AR5K_REG_WRITE(AR5K_SLEEP_CTL,
+                           AR5K_SLEEP_CTL_SLE_SLP);
+               }
+               staid |= AR5K_STA_ID1_PWR_SV;
+               break;
+
+       case AR5K_PM_AWAKE:
+               if (set_chip == FALSE)
+                       goto commit;
+
+               AR5K_REG_WRITE(AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLE_WAKE);
+
+               for (i = 5000; i > 0; i--) {
+                       /* Check if the chip did wake up */
+                       if ((AR5K_REG_READ(AR5K_PCICFG) &
+                           AR5K_PCICFG_SPWR_DN) == 0)
+                               break;
+
+                       /* Wait a bit and retry */
+                       AR5K_DELAY(200);
+                       AR5K_REG_WRITE(AR5K_SLEEP_CTL,
+                           AR5K_SLEEP_CTL_SLE_WAKE);
+               }
+
+               /* Fail if the chip didn't wake up */
+               if (i <= 0)
+                       return (FALSE);
+
+               staid &= ~AR5K_STA_ID1_PWR_SV;
+               break;
+
+       default:
+               return (FALSE);
+       }
+
+ commit:
+       hal->ah_power_mode = mode;
+
+       AR5K_REG_WRITE(AR5K_STA_ID1, staid);
+
+       return (TRUE);
+}
+
+/*
+ * Get power mode (sleep state)
+ * TODO:Remove ?
+ */
+AR5K_POWER_MODE
+ath5k_hw_get_power_mode(struct ath_hal *hal)
+{
+       AR5K_TRACE;
+       return (hal->ah_power_mode);
+}
+
+
+
+
+/***********************\
+  DMA Related Functions
+\***********************/
+
+/*
+ * Receive functions
+ */
+
+/*
+ * Start DMA receive
+ */
+void
+ath5k_hw_start_rx(struct ath_hal *hal)
+{
+       AR5K_TRACE;
+       AR5K_REG_WRITE(AR5K_CR, AR5K_CR_RXE);
+}
+
+/*
+ * Stop DMA receive
+ */
+AR5K_BOOL
+ath5k_hw_stop_rx_dma(struct ath_hal *hal)
+{
+       int i;
+
+       AR5K_TRACE;
+       AR5K_REG_WRITE(AR5K_CR, AR5K_CR_RXD);
+
+       /*
+        * It may take some time to disable the DMA receive unit
+        */
+       for (i = 2000;
+            i > 0 && (AR5K_REG_READ(AR5K_CR) & AR5K_CR_RXE) != 0;
+            i--)
+               AR5K_DELAY(10);
+
+       return (i > 0 ? TRUE : FALSE);
+}
+
+/*
+ * Get the address of the RX Descriptor
+ */
+u_int32_t
+ath5k_hw_get_rx_buf(struct ath_hal *hal)
+{
+       return (AR5K_REG_READ(AR5K_RXDP));
+}
+
+/*
+ * Set the address of the RX Descriptor
+ */
+void
+ath5k_hw_put_rx_buf(struct ath_hal *hal, u_int32_t phys_addr)
+{
+       AR5K_TRACE;
+
+       /*TODO:Shouldn't we check if RX is enabled first ?*/
+       AR5K_REG_WRITE(AR5K_RXDP, phys_addr);
+}
+
+/*
+ * Transmit functions
+ */
+
+/*
+ * Start DMA transmit for a specific queue
+ * (see also QCU/DCU functions)
+ */
+AR5K_BOOL
+ath5k_hw_tx_start(struct ath_hal *hal, u_int queue)
+{
+       AR5K_TRACE;
+       AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
+
+       /* Return if queue is disabled */
+       if (AR5K_REG_READ_Q(AR5K_QCU_TXD, queue))
+               return (FALSE);
+
+       /* Start queue */
+       AR5K_REG_WRITE_Q(AR5K_QCU_TXE, queue);
+
+       return (TRUE);
+}
+
+/*
+ * Stop DMA transmit for a specific queue
+ * (see also QCU/DCU functions)
+ */
+AR5K_BOOL
+ath5k_hw_stop_tx_dma(struct ath_hal *hal, u_int queue)
+{
+       int i = 100, pending;
+       
+       AR5K_TRACE;
+       AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
+
+       /*
+        * Schedule TX disable and wait until queue is empty
+        */
+       AR5K_REG_WRITE_Q(AR5K_QCU_TXD, queue);
+
+       /*Check for pending frames*/
+       do {
+               pending = AR5K_REG_READ(AR5K_QUEUE_STATUS(queue)) &
+                    AR5K_QCU_STS_FRMPENDCNT;
+               AR5K_DELAY(100);
+       } while (--i && pending);
+
+       /* Clear register */
+       AR5K_REG_WRITE(AR5K_QCU_TXD, 0);
+
+       /*TODO: Check for success else return false*/
+       return (TRUE);
+}
+
+/*
+ * Get the address of the TX Descriptor for a specific queue
+ * (see also QCU/DCU functions)
+ */ 
+u_int32_t
+ath5k_hw_get_tx_buf(struct ath_hal *hal, u_int queue)
+{
+       AR5K_TRACE;
+       AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
+
+       /*
+        * Get the transmit queue descriptor pointer from the selected queue
+        */
+       return (AR5K_REG_READ(AR5K_QUEUE_TXDP(queue)));
+}
+
+/*
+ * Set the address of the TX Descriptor for a specific queue
+ * (see also QCU/DCU functions)
+ */
+AR5K_BOOL
+ath5k_hw_put_tx_buf(struct ath_hal *hal, u_int queue, u_int32_t phys_addr)
+{
+       AR5K_TRACE;
+       AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
+
+       /*
+        * Set the transmit queue descriptor pointer for the selected queue
+        * (this won't work if the queue is still active)
+        */
+       if (AR5K_REG_READ_Q(AR5K_QCU_TXE, queue))
+               return (FALSE);
+
+       AR5K_REG_WRITE(AR5K_QUEUE_TXDP(queue), phys_addr);
+
+       return (TRUE);
+}
+
+/*
+ * Update tx trigger level
+ */
+AR5K_BOOL
+ath5k_hw_update_tx_triglevel(struct ath_hal *hal, AR5K_BOOL increase)
+{
+       u_int32_t trigger_level, imr;
+       AR5K_BOOL status = FALSE;
+       AR5K_TRACE;
+
+       /*
+        * Disable interrupts by setting the mask
+        */
+       imr = ath5k_hw_set_intr(hal, hal->ah_imr & ~AR5K_INT_GLOBAL);
+
+       /*TODO: Boundary check on trigger_level*/
+       trigger_level = AR5K_REG_MS(AR5K_REG_READ(AR5K_TXCFG),
+           AR5K_TXCFG_TXFULL);
+
+       if (increase == FALSE) {
+               if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
+                       goto done;
+       } else
+               trigger_level +=
+                   ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
+
+       /*
+        * Update trigger level on success
+        */
+       AR5K_REG_WRITE_BITS(AR5K_TXCFG,
+           AR5K_TXCFG_TXFULL, trigger_level);
+       status = TRUE;
+
+ done:
+       /*
+        * Restore interrupt mask
+        */
+       ath5k_hw_set_intr(hal, imr);
+
+       return (status);
+}
+
+/*
+ * Interrupt handling
+ */
+
+/*
+ * Check if we have pending interrupts
+ */
+AR5K_BOOL
+ath5k_hw_is_intr_pending(struct ath_hal *hal)
+{
+       AR5K_TRACE;
+       return (AR5K_REG_READ(AR5K_INTPEND) == TRUE ? TRUE : FALSE);
+}
+
+/*
+ * Get interrupt mask (ISR)
+ */
+AR5K_BOOL
+ath5k_hw_get_isr(struct ath_hal *hal, u_int32_t *interrupt_mask)
+{
+       u_int32_t data;
+
+       AR5K_TRACE;
+       /*
+        * Read interrupt status from the Read-And-Clear shadow register
+        */
+       data = AR5K_REG_READ(AR5K_RAC_PISR);
+
+       /*
+        * Get abstract interrupt mask (HAL-compatible)
+        */
+       *interrupt_mask = (data & AR5K_INT_COMMON) & hal->ah_imr;
+
+       if (data == AR5K_INT_NOCARD)
+               return (FALSE);
+
+       if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR))
+               *interrupt_mask |= AR5K_INT_RX;
+
+       if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR))
+               *interrupt_mask |= AR5K_INT_TX;
+
+       /*HIU = Host Interface Unit (PCI etc)*/
+       if (data & (AR5K_ISR_HIUERR))
+               *interrupt_mask |= AR5K_INT_FATAL;
+
+       /*Beacon Not Ready*/
+       if (data & (AR5K_ISR_BNR))
+               *interrupt_mask |= AR5K_INT_BNR;
+
+       /*
+        * Special interrupt handling (not caught by the driver)
+        */
+       if (((*interrupt_mask) & AR5K_ISR_RXPHY) &&
+           hal->ah_radar.r_enabled == TRUE)
+               ath5k_radar_alert(hal);
+
+       if (*interrupt_mask == 0)
+               AR5K_PRINTF("0x%08x\n", data);
+
+       return (TRUE);
+}
+
+/*
+ * Return the interrupt mask stored previously
+ * TODO: Remove ?
+ */
+u_int32_t
+ath5k_hw_get_intr(struct ath_hal *hal)
+{
+       AR5K_TRACE;
+       return (hal->ah_imr);
+}
+
+/*
+ * Set interrupt mask
+ */
+AR5K_INT
+ath5k_hw_set_intr(struct ath_hal *hal, AR5K_INT new_mask)
+{
+       AR5K_INT old_mask, int_mask;
+
+       /*
+        * Disable card interrupts to prevent any race conditions
+        * (they will be re-enabled afterwards).
+        */
+       AR5K_REG_WRITE(AR5K_IER, AR5K_IER_DISABLE);
+
+       old_mask = hal->ah_imr;
+
+       /*
+        * Add additional, chipset-dependent interrupt mask flags
+        * and write them to the IMR (interrupt mask register).
+        */
+       int_mask = new_mask & AR5K_INT_COMMON;
+
+       if (new_mask & AR5K_INT_RX)
+               int_mask |=
+                   AR5K_IMR_RXOK |
+                   AR5K_IMR_RXERR |
+                   AR5K_IMR_RXORN |
+                   AR5K_IMR_RXDESC;
+
+       if (new_mask & AR5K_INT_TX)
+               int_mask |=
+                   AR5K_IMR_TXOK |
+                   AR5K_IMR_TXERR |
+                   AR5K_IMR_TXDESC |
+                   AR5K_IMR_TXURN;
+
+       if (new_mask & AR5K_INT_FATAL) {
+               int_mask |= AR5K_IMR_HIUERR;
+               AR5K_REG_ENABLE_BITS(AR5K_SIMR2,
+                   AR5K_SIMR2_MCABT |
+                   AR5K_SIMR2_SSERR |
+                   AR5K_SIMR2_DPERR);
+       }
+
+       AR5K_REG_WRITE(AR5K_PIMR, int_mask);
+
+       /* Store new interrupt mask */
+       hal->ah_imr = new_mask;
+
+       /* ..re-enable interrupts */
+       AR5K_REG_WRITE(AR5K_IER, AR5K_IER_ENABLE);
+
+       return (old_mask);
+}
+
+/*
+ * Enalbe HW radar detection
+ */
+void
+ath5k_hw_radar_alert(struct ath_hal *hal, AR5K_BOOL enable)
+{
+
+       AR5K_TRACE;
+       /*
+        * Enable radar detection
+        */
+
+       /*Disable interupts*/
+       AR5K_REG_WRITE(AR5K_IER, AR5K_IER_DISABLE);
+
+       /*Set AR5K_PHY_RADAR register*/
+       if (enable == TRUE) {
+               AR5K_REG_WRITE(AR5K_PHY_RADAR,
+                   AR5K_PHY_RADAR_ENABLE);
+               AR5K_REG_ENABLE_BITS(AR5K_PIMR,
+                   AR5K_IMR_RXPHY);
+       } else {
+               AR5K_REG_WRITE(AR5K_PHY_RADAR,
+                   AR5K_PHY_RADAR_DISABLE);
+               AR5K_REG_DISABLE_BITS(AR5K_PIMR,
+                   AR5K_IMR_RXPHY);
+       }
+
+       /*Re-enable interrupts*/
+       AR5K_REG_WRITE(AR5K_IER, AR5K_IER_ENABLE);
+}
+
+
+
+
+/*************************\
+  EEPROM access functions
+\*************************/
+
+/*
+ * Check if eeprom is busy
+ */
+AR5K_BOOL
+ath5k_hw_eeprom_is_busy(struct ath_hal *hal)
+{
+       AR5K_TRACE;
+       return (AR5K_REG_READ(AR5K_CFG) & AR5K_CFG_EEBS ?
+           TRUE : FALSE);
+}
+
+/*
+ * Read from eeprom
+ */
+int
+ath5k_hw_eeprom_read(struct ath_hal *hal, u_int32_t offset, u_int16_t *data)
+{
+       u_int32_t status, i;
+
+       AR5K_TRACE;
+       /*
+        * Initialize EEPROM access
+        */
+       AR5K_REG_WRITE(AR5K_EEPROM_BASE, (u_int8_t)offset);
+       AR5K_REG_ENABLE_BITS(AR5K_EEPROM_CMD,
+           AR5K_EEPROM_CMD_READ);
+
+       for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+               status = AR5K_REG_READ(AR5K_EEPROM_STATUS);
+               if (status & AR5K_EEPROM_STAT_RDDONE) {
+                       if (status & AR5K_EEPROM_STAT_RDERR)
+                               return (EIO);
+                       *data = (u_int16_t)
+                           (AR5K_REG_READ(AR5K_EEPROM_DATA) & 0xffff);
+                       return (0);
+               }
+               AR5K_DELAY(15);
+       }
+
+       return (ETIMEDOUT);
+}
+
+/*
+ * Write to eeprom - currently disabled, use at your own risk
+ */
+int
+ath5k_hw_eeprom_write(struct ath_hal *hal, u_int32_t offset, u_int16_t data)
+{
+       u_int32_t status, timeout;
+
+       AR5K_TRACE;
+       /* Enable eeprom access */
+       AR5K_REG_ENABLE_BITS(AR5K_EEPROM_CMD,
+           AR5K_EEPROM_CMD_RESET);
+
+       /*
+        * Write data to data register
+        * Disable this, it's not needed for
+        * normal operation, uncomment it if you
+        * need it.
+        */
+       /*
+       AR5K_REG_WRITE(AR5K_EEPROM_DATA, data);
+       */
+       AR5K_PRINTF("EEPROM Write is disabled!");
+
+       /* Write offset to base register */
+       AR5K_REG_WRITE(AR5K_EEPROM_BASE, (u_int8_t)offset - 1);
+
+       /* Issue write command */
+       AR5K_REG_ENABLE_BITS(AR5K_EEPROM_CMD,
+           AR5K_EEPROM_CMD_WRITE);
+
+       /*
+        * Check status
+        */
+
+       for (timeout = 10000; timeout > 0; timeout--) {
+               AR5K_DELAY(1);
+               status = AR5K_REG_READ(AR5K_EEPROM_STATUS);
+               if (status & AR5K_EEPROM_STAT_WRDONE) {
+                       if (status & AR5K_EEPROM_STAT_WRERR)
+                               return (EIO);
+                       return (0);
+               }
+       }
+
+       return (ETIMEDOUT);
+}
+
+u_int16_t
+ath5k_eeprom_bin2freq(struct ath_hal *hal, u_int16_t bin, u_int mode)
+{
+       u_int16_t val;
+
+       if (bin == AR5K_EEPROM_CHANNEL_DIS)
+               return (bin);
+
+       if (mode == AR5K_EEPROM_MODE_11A) {
+               if (hal->ah_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 (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+                       val = bin + 2300;
+               else
+                       val = bin + 2400;
+       }
+
+       return (val);
+}
+
+/*
+ * Read antenna infos from eeprom
+ */
+int
+ath5k_eeprom_read_ants(struct ath_hal *hal, u_int32_t *offset, u_int mode)
+{
+       struct ath5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+       u_int32_t o = *offset;
+       u_int16_t val;
+       int ret, i = 0;
+
+       AR5K_EEPROM_READ(o++, val);
+       ee->ee_switch_settling[mode]    = (val >> 8) & 0x7f;
+       ee->ee_ant_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 */
+       hal->ah_antenna[mode][0] =
+           (ee->ee_ant_control[mode][0] << 4) | 0x1;
+       hal->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);
+       hal->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 from eeprom
+ */
+int
+ath5k_eeprom_read_modes(struct ath_hal *hal, u_int32_t *offset, u_int mode)
+{
+       struct ath5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+       u_int32_t o = *offset;
+       u_int16_t val;
+       int ret;
+
+       AR5K_EEPROM_READ(o++, val);
+       ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
+       ee->ee_thr_62[mode]             = val & 0xff;
+
+       if (hal->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 (hal->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 (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
+               ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
+
+       if (hal->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 (hal->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 (hal->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 (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
+           mode == AR5K_EEPROM_MODE_11G)
+               ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+
+       /* return new offset */
+       *offset = o;
+
+       return (0);
+}
+
+/*
+ * Initialize eeprom & capabilities structs
+ */
+int
+ath5k_eeprom_init(struct ath_hal *hal)
+{
+       struct ath5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+       u_int32_t offset;
+       u_int16_t val;
+       int ret, i;
+       u_int mode;
+
+       /* Initial TX thermal adjustment values */
+       ee->ee_tx_clip = 4;
+       ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
+       ee->ee_gain_select = 1;
+
+       /*
+        * 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 (hal->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) {
+               AR5K_PRINTF("Invalid EEPROM checksum 0x%04x\n", cksum);
+               return (AR5K_EEBADSUM);
+       }
+#endif
+
+       AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(hal->ah_ee_version),
+           ee_ant_gain);
+
+       if (hal->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);
+       }
+
+       if (hal->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