25/5/09

Should work on all ports that have a kernel which currently includes
an "ath* at pci*" line

Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.924.4.1
diff -u -r1.924.4.1 files
--- sys/conf/files      15 Mar 2009 19:43:48 -0000      1.924.4.1
+++ sys/conf/files      15 May 2009 13:10:30 -0000
@@ -582,15 +582,16 @@
device wi: arp, wlan, ifnet
file   dev/ic/wi.c                     wi

+# Atheros HAL
+#
+include "external/isc/atheros_hal/conf/files.ath_hal"
+
# Atheros 5210/5211/5212 multi-mode 802.11
#
-defflag        opt_athhal.h    ATHHAL_ASSERT ATHHAL_DEBUG ATHHAL_DEBUG_ALQ
device ath: arp, wlan, ifnet
file   dev/ic/ath.c                                    ath
file   dev/ic/ath_netbsd.c                             ath
file   dev/ic/athrate-sample.c                         ath
-file   contrib/dev/ath/netbsd/ah_osdep.c               ath
-object /athhal.o                                       ath

# ADMtek ADM8211 802.11
#
Index: sys/arch/i386/conf/std.i386
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/std.i386,v
retrieving revision 1.28
diff -u -r1.28 std.i386
--- sys/arch/i386/conf/std.i386 30 Apr 2008 15:29:12 -0000      1.28
+++ sys/arch/i386/conf/std.i386 15 May 2009 13:10:48 -0000
@@ -19,3 +19,6 @@
mainbus0 at root
cpu* at mainbus?
ioapic* at mainbus?
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/macppc/conf/std.macppc
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/conf/std.macppc,v
retrieving revision 1.22
diff -u -r1.22 std.macppc
--- sys/arch/macppc/conf/std.macppc     17 Oct 2007 19:55:17 -0000      1.22
+++ sys/arch/macppc/conf/std.macppc     15 May 2009 13:10:48 -0000
@@ -16,3 +16,6 @@
options        EXEC_SCRIPT     # shell script support

options        INTSTK=0x2000
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/macppc/conf/std.macppc.g5
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/conf/std.macppc.g5,v
retrieving revision 1.2
diff -u -r1.2 std.macppc.g5
--- sys/arch/macppc/conf/std.macppc.g5  26 Aug 2008 16:18:49 -0000      1.2
+++ sys/arch/macppc/conf/std.macppc.g5  25 May 2009 19:39:27 -0000
@@ -15,3 +15,6 @@
options        EXEC_SCRIPT     # shell script support

options        INTSTK=0x2000
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/xen/conf/std.xen
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/conf/std.xen,v
retrieving revision 1.5
diff -u -r1.5 std.xen
--- sys/arch/xen/conf/std.xen   25 Jan 2008 21:12:14 -0000      1.5
+++ sys/arch/xen/conf/std.xen   15 May 2009 13:10:48 -0000
@@ -15,3 +15,6 @@
#options       CRYPTO_MD_DES_CBC       # machine-dependant DES CBC code
#options       CRYPTO_MD_BF_ENC        # machine-dependant code for BF_encrypt
#options       CRYPTO_MD_BF_CBC        # careful: uses bswapl, requires 486
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/amd64/conf/std.amd64
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/conf/std.amd64,v
retrieving revision 1.6
diff -u -r1.6 std.amd64
--- sys/arch/amd64/conf/std.amd64       30 Apr 2008 22:08:18 -0000      1.6
+++ sys/arch/amd64/conf/std.amd64       15 May 2009 13:10:48 -0000
@@ -15,3 +15,5 @@
cpu* at mainbus?
ioapic* at mainbus? apid ?

+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/amd64/conf/std.xen
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/conf/std.xen,v
retrieving revision 1.3
diff -u -r1.3 std.xen
--- sys/arch/amd64/conf/std.xen 25 Jan 2008 21:12:11 -0000      1.3
+++ sys/arch/amd64/conf/std.xen 15 May 2009 13:10:48 -0000
@@ -13,3 +13,6 @@
options        EXEC_ELF64      # exec ELF binaries
options        EXEC_SCRIPT     # exec #! scripts
options        MTRR
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/evbmips/conf/std.adm5120
===================================================================
RCS file: /cvsroot/src/sys/arch/evbmips/conf/std.adm5120,v
retrieving revision 1.1
diff -u -r1.1 std.adm5120
--- sys/arch/evbmips/conf/std.adm5120   20 Mar 2007 08:52:01 -0000      1.1
+++ sys/arch/evbmips/conf/std.adm5120   25 May 2009 19:39:27 -0000
@@ -16,3 +16,6 @@

include        "arch/evbmips/conf/files.adm5120"
include        "arch/mips/conf/files.adm5120"
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/evbmips/conf/std.alchemy
===================================================================
RCS file: /cvsroot/src/sys/arch/evbmips/conf/std.alchemy,v
retrieving revision 1.3
diff -u -r1.3 std.alchemy
--- sys/arch/evbmips/conf/std.alchemy   28 Mar 2006 03:43:57 -0000      1.3
+++ sys/arch/evbmips/conf/std.alchemy   25 May 2009 19:39:27 -0000
@@ -15,3 +15,6 @@

include        "arch/evbmips/conf/files.alchemy"
include        "arch/mips/conf/files.alchemy"
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/evbmips/conf/std.atheros
===================================================================
RCS file: /cvsroot/src/sys/arch/evbmips/conf/std.atheros,v
retrieving revision 1.3
diff -u -r1.3 std.atheros
--- sys/arch/evbmips/conf/std.atheros   26 Sep 2006 06:37:32 -0000      1.3
+++ sys/arch/evbmips/conf/std.atheros   25 May 2009 19:39:27 -0000
@@ -13,3 +13,6 @@

include        "arch/evbmips/conf/files.atheros"
include        "arch/mips/conf/files.atheros"
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/evbmips/conf/std.malta
===================================================================
RCS file: /cvsroot/src/sys/arch/evbmips/conf/std.malta,v
retrieving revision 1.5
diff -u -r1.5 std.malta
--- sys/arch/evbmips/conf/std.malta     11 Dec 2005 12:17:11 -0000      1.5
+++ sys/arch/evbmips/conf/std.malta     25 May 2009 19:39:27 -0000
@@ -15,3 +15,6 @@
makeoptions    BOARDTYPE="malta"

include "arch/evbmips/conf/files.malta"
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/evbmips/conf/std.meraki
===================================================================
RCS file: /cvsroot/src/sys/arch/evbmips/conf/std.meraki,v
retrieving revision 1.1
diff -u -r1.1 std.meraki
--- sys/arch/evbmips/conf/std.meraki    26 Sep 2006 06:37:32 -0000      1.1
+++ sys/arch/evbmips/conf/std.meraki    25 May 2009 19:39:27 -0000
@@ -13,3 +13,6 @@

include        "arch/evbmips/conf/files.atheros"
include        "arch/mips/conf/files.atheros"
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/sparc64/conf/std.sparc64
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/conf/std.sparc64,v
retrieving revision 1.17
diff -u -r1.17 std.sparc64
--- sys/arch/sparc64/conf/std.sparc64   3 Feb 2008 13:27:12 -0000       1.17
+++ sys/arch/sparc64/conf/std.sparc64   25 May 2009 19:39:27 -0000
@@ -15,3 +15,6 @@
options        EXEC_ELF64      # 64-bit NetBSD and SunOS 5 bins

options                CPU_IN_CKSUM    # use optimized checksum method
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/arch/sparc64/conf/std.sparc64-32
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/conf/std.sparc64-32,v
retrieving revision 1.1
diff -u -r1.1 std.sparc64-32
--- sys/arch/sparc64/conf/std.sparc64-32        30 Jun 2006 10:27:48 -0000      1.1
+++ sys/arch/sparc64/conf/std.sparc64-32        25 May 2009 19:39:27 -0000
@@ -10,3 +10,6 @@
makeoptions    LP64="no"

no options     EXEC_ELF64
+
+# Atheros HAL options
+include "external/isc/atheros_hal/conf/std.ath_hal"
Index: sys/dev/ic/ath.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/ath.c,v
retrieving revision 1.102
diff -u -r1.102 ath.c
--- sys/dev/ic/ath.c    9 Jul 2008 19:47:24 -0000       1.102
+++ sys/dev/ic/ath.c    15 May 2009 13:10:50 -0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ath.c,v 1.102 2008/07/09 19:47:24 joerg Exp $  */
+/*     $NetBSD: ath.c,v 1.105 2008/12/11 06:04:01 alc Exp $    */

/*-
 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
@@ -41,7 +41,7 @@
__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.104 2005/09/16 10:09:23 ru Exp $");
#endif
#ifdef __NetBSD__
-__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.102 2008/07/09 19:47:24 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.105 2008/12/11 06:04:01 alc Exp $");
#endif

/*
@@ -96,9 +96,9 @@

#define        AR_DEBUG
#include <dev/ic/athvar.h>
-#include <contrib/dev/ath/ah_desc.h>
-#include <contrib/dev/ath/ah_devid.h>  /* XXX for softled */
-#include "athhal_options.h"
+#include "ah_desc.h"
+#include "ah_devid.h"  /* XXX for softled */
+#include "opt_ah.h"

#ifdef ATH_TX99_DIAG
#include <dev/ath/ath_tx99/ath_tx99.h>
@@ -253,10 +253,10 @@
static void ath_printrxbuf(struct ath_buf *bf, int);
static void ath_printtxbuf(struct ath_buf *bf, int);
#else
-#define        IFF_DUMPPKTS(sc, m) \
+#define        IFF_DUMPPKTS(sc, m) \
       ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
-#define        DPRINTF(m, fmt, ...)
-#define        KEYPRINTF(sc, k, ix, mac)
+#define        DPRINTF(m, fmt, ...)
+#define        KEYPRINTF(sc, k, ix, mac)
#endif

MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers");
@@ -371,7 +371,9 @@
       }
       ATH_CALLOUT_INIT(&sc->sc_scan_ch, debug_mpsafenet ? CALLOUT_MPSAFE : 0);
       ATH_CALLOUT_INIT(&sc->sc_cal_ch, CALLOUT_MPSAFE);
+#if 0
       ATH_CALLOUT_INIT(&sc->sc_dfs_ch, CALLOUT_MPSAFE);
+#endif

       ATH_TXBUF_LOCK_INIT(sc);

@@ -518,13 +520,28 @@
                * separate key cache entries are required to
                * handle both tx+rx MIC keys.
                */
-               if (ath_hal_ciphersupported(ah, HAL_CIPHER_MIC))
+               if (ath_hal_ciphersupported(ah, HAL_CIPHER_MIC)) {
                       ic->ic_caps |= IEEE80211_C_TKIPMIC;
-               if (ath_hal_tkipsplit(ah))
+                       /*
+                        * Check if h/w does MIC correctly when
+                        * WMM is turned on.
+                        */
+                       if (ath_hal_wmetkipmic(ah))
+                               ic->ic_caps |= IEEE80211_C_WME_TKIPMIC;
+               }
+
+               /*
+                * If the h/w supports storing tx+rx MIC keys
+                * in one cache slot automatically enable use.
+                */
+               if (ath_hal_tkipsplit(ah) ||
+                   !ath_hal_settkipsplit(ah, AH_FALSE))
                       sc->sc_splitmic = 1;
       }
       sc->sc_hasclrkey = ath_hal_ciphersupported(ah, HAL_CIPHER_CLR);
+#if 0
       sc->sc_mcastkey = ath_hal_getmcastkeysearch(ah);
+#endif
       /*
        * TPC support can be done either with a global cap or
        * per-packet support.  The latter is not available on
@@ -661,6 +678,7 @@
void
ath_suspend(struct ath_softc *sc)
{
+#if notyet
       /*
        * Set the chip in full sleep mode.  Note that we are
        * careful to do this only when bringing the interface
@@ -671,15 +689,22 @@
        * issue with newer parts that go to sleep more quickly.
        */
       ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
+#endif
}

bool
ath_resume(struct ath_softc *sc)
{
-       int i;
       struct ath_hal *ah = sc->sc_ah;
+       struct ieee80211com *ic = &sc->sc_ic;
+       HAL_STATUS status;
+       int i;

+#if notyet
       ath_hal_setpower(ah, HAL_PM_AWAKE);
+#else
+       ath_hal_reset(ah, ic->ic_opmode, &sc->sc_curchan, AH_FALSE, &status);
+#endif

       /*
        * Reset the key cache since some parts do not
@@ -877,6 +902,7 @@
static void
ath_radar_proc(void *arg, int pending)
{
+#if 0
       struct ath_softc *sc = arg;
       struct ifnet *ifp = &sc->sc_if;
       struct ath_hal *ah = sc->sc_ah;
@@ -890,6 +916,7 @@
                */
               /* XXX not yet */
       }
+#endif
}

static u_int
@@ -946,6 +973,17 @@
        */
       ath_stop_locked(ifp, 0);

+       int dummy;      /* XXX: gcc */
+       /* Whether we should enable h/w TKIP MIC */
+       if ((ic->ic_caps & IEEE80211_C_WME) &&
+           ((ic->ic_caps & IEEE80211_C_WME_TKIPMIC) ||
+           !(ic->ic_flags & IEEE80211_F_WME))) {
+               dummy = ath_hal_settkipmic(ah, AH_TRUE);
+       } else {
+               dummy = ath_hal_settkipmic(ah, AH_FALSE);
+       }
+
+
       /*
        * The basic interface to setting the hardware in a good
        * state is ``reset''.  On return the hardware is known to
@@ -1326,7 +1364,7 @@
                        * buffers to send all the fragments so all
                        * go out or none...
                        */
-                       if ((m->m_flags & M_FRAG) &&
+                       if ((m->m_flags & M_FRAG) &&
                           !ath_txfrag_setup(sc, &frags, m, ni)) {
                               DPRINTF(sc, ATH_DEBUG_ANY,
                                   "%s: out of txfrag buffers\n", __func__);
@@ -1450,21 +1488,36 @@

       KASSERT(k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP,
               ("got a non-TKIP key, cipher %u", k->wk_cipher->ic_cipher));
-       KASSERT(sc->sc_splitmic, ("key cache !split"));
       if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) {
-               /*
-                * TX key goes at first index, RX key at the rx index.
-                * The hal handles the MIC keys at index+64.
-                */
-               memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_mic));
-               KEYPRINTF(sc, k->wk_keyix, hk, zerobssid);
-               if (!ath_hal_keyset(ah, k->wk_keyix, hk, zerobssid))
-                       return 0;
-
-               memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic));
-               KEYPRINTF(sc, k->wk_keyix+32, hk, mac);
-               /* XXX delete tx key on failure? */
-               return ath_hal_keyset(ah, k->wk_keyix+32, hk, mac);
+               if (sc->sc_splitmic) {
+                       /*
+                        * TX key goes at first index, RX key at the rx index.
+                        * The hal handles the MIC keys at index+64.
+                        */
+                       memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_mic));
+                       KEYPRINTF(sc, k->wk_keyix, hk, zerobssid);
+                       if (!ath_hal_keyset(ah, ATH_KEY(k->wk_keyix), hk,
+                                               zerobssid))
+                               return 0;
+
+                       memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic));
+                       KEYPRINTF(sc, k->wk_keyix+32, hk, mac);
+                       /* XXX delete tx key on failure? */
+                       return ath_hal_keyset(ah, ATH_KEY(k->wk_keyix+32),
+                                       hk, mac);
+               } else {
+                       /*
+                        * Room for both TX+RX MIC keys in one key cache
+                        * slot, just set key at the first index; the HAL
+                        * will handle the reset.
+                        */
+                       memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic));
+#if HAL_ABI_VERSION > 0x06052200
+                       memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic));
+#endif
+                       KEYPRINTF(sc, k->wk_keyix, hk, mac);
+                       return ath_hal_keyset(ah, ATH_KEY(k->wk_keyix), hk, mac);
+               }
       } else if (k->wk_flags & IEEE80211_KEY_XR) {
               /*
                * TX/RX key goes at first index.
@@ -1473,7 +1526,7 @@
               memcpy(hk->kv_mic, k->wk_flags & IEEE80211_KEY_XMIT ?
                       k->wk_txmic : k->wk_rxmic, sizeof(hk->kv_mic));
               KEYPRINTF(sc, k->wk_keyix, hk, mac);
-               return ath_hal_keyset(ah, k->wk_keyix, hk, mac);
+               return ath_hal_keyset(ah, ATH_KEY(k->wk_keyix), hk, mac);
       }
       return 0;
#undef IEEE80211_KEY_XR
@@ -1532,13 +1585,12 @@
       } else
               mac = mac0;

-       if (hk.kv_type == HAL_CIPHER_TKIP &&
-           (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 &&
-           sc->sc_splitmic) {
+       if ((hk.kv_type == HAL_CIPHER_TKIP &&
+           (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) && sc->sc_splitmic) {
               return ath_keyset_tkip(sc, k, &hk, mac);
       } else {
               KEYPRINTF(sc, k->wk_keyix, &hk, mac);
-               return ath_hal_keyset(ah, k->wk_keyix, &hk, mac);
+               return ath_hal_keyset(ah, ATH_KEY(k->wk_keyix), &hk, mac);
       }
#undef N
}
@@ -1590,11 +1642,11 @@
                               keyix+32, keyix+32+64);
                       *txkeyix = keyix;
                       *rxkeyix = keyix+32;
-                       return 1;
+                       return keyix;
               }
       }
       DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__);
-       return 0;
+       return IEEE80211_KEYIX_NONE;
#undef N
}

@@ -1813,6 +1865,8 @@
       if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
           (ifp->if_flags & IFF_PROMISC))
               rfilt |= HAL_RX_FILTER_PROM;
+       if (ifp->if_flags & IFF_PROMISC)
+               rfilt |= HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_PROBEREQ;
       if (ic->ic_opmode == IEEE80211_M_STA ||
           ic->ic_opmode == IEEE80211_M_IBSS ||
           state == IEEE80211_S_SCAN)
@@ -2103,8 +2157,8 @@
               , ds                            /* first descriptor */
       );

-       /* NB: The desc swap function becomes void,
-        * if descriptor swapping is not enabled
+       /* NB: The desc swap function becomes void, if descriptor swapping
+        * is not enabled
        */
       ath_desc_swap(ds);

@@ -2750,7 +2804,7 @@
       ds = bf->bf_desc;
       ds->ds_link = HTOAH32(bf->bf_daddr);    /* link to self */
       ds->ds_data = bf->bf_segs[0].ds_addr;
-       ds->ds_vdata = mtod(m, void *); /* for radar */
+       /* ds->ds_vdata = mtod(m, void *);      for radar */
       ath_hal_setuprxdesc(ah, ds
               , m->m_len              /* buffer size */
               , 0
@@ -2848,6 +2902,21 @@
}

static void
+ath_handle_micerror(struct ieee80211com *ic,
+       struct ieee80211_frame *wh, int keyix)
+{
+       struct ieee80211_node *ni;
+
+       /* XXX recheck MIC to deal w/ chips that lie */
+       /* XXX discard MIC errors on !data frames */
+       ni = ieee80211_find_rxnode_withkey(ic, (const struct ieee80211_frame_min *) wh, keyix);
+       if (ni != NULL) {
+               ieee80211_notify_michael_failure(ic, wh, keyix);
+               ieee80211_free_node(ni);
+       }
+}
+
+static void
ath_rx_proc(void *arg, int npending)
{
#define        PA2DESC(_sc, _pa) \
@@ -2862,14 +2931,23 @@
       struct mbuf *m;
       struct ieee80211_node *ni;
       struct ath_node *an;
-       int len, type, ngood;
+       int len, ngood, type;
       u_int phyerr;
       HAL_STATUS status;
       int16_t nf;
       u_int64_t tsf;
+       uint8_t rxerr_tap, rxerr_mon;

       NET_LOCK_GIANT();               /* XXX */

+       rxerr_tap =
+           (ifp->if_flags & IFF_PROMISC) ? HAL_RXERR_CRC|HAL_RXERR_PHY : 0;
+
+       if (sc->sc_ic.ic_opmode == IEEE80211_M_MONITOR)
+               rxerr_mon = HAL_RXERR_DECRYPT|HAL_RXERR_MIC;
+       else if (ifp->if_flags & IFF_PROMISC)
+               rxerr_tap |= HAL_RXERR_DECRYPT|HAL_RXERR_MIC;
+
       DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
       ngood = 0;
       nf = ath_hal_getchannoise(ah, &sc->sc_curchan);
@@ -2903,7 +2981,8 @@
                * a self-linked list to avoid rx overruns.
                */
               status = ath_hal_rxprocdesc(ah, ds,
-                               bf->bf_daddr, PA2DESC(sc, ds->ds_link));
+                               bf->bf_daddr, PA2DESC(sc, ds->ds_link),
+                               tsf, &ds->ds_rxstat);
#ifdef AR_DEBUG
               if (sc->sc_debug & ATH_DEBUG_RECV_DESC)
                       ath_printrxbuf(bf, status == HAL_OK);
@@ -2962,12 +3041,10 @@
                                           bf->bf_dmamap,
                                           0, bf->bf_dmamap->dm_mapsize,
                                           BUS_DMASYNC_POSTREAD);
-                                       ieee80211_notify_michael_failure(ic,
+                                       ath_handle_micerror(ic,
                                           mtod(m, struct ieee80211_frame *),
                                           sc->sc_splitmic ?
-                                               ds->ds_rxstat.rs_keyix-32 :
-                                               ds->ds_rxstat.rs_keyix
-                                       );
+                                               ds->ds_rxstat.rs_keyix-32 : ds->ds_rxstat.rs_keyix);
                               }
                       }
                       ifp->if_ierrors++;
@@ -2976,9 +3053,8 @@
                        * to see them in monitor mode (in monitor mode
                        * allow through packets that have crypto problems).
                        */
-                       if ((ds->ds_rxstat.rs_status &~
-                               (HAL_RXERR_DECRYPT|HAL_RXERR_MIC)) ||
-                           sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
+
+                       if (ds->ds_rxstat.rs_status &~ (rxerr_tap|rxerr_mon))
                               goto rx_next;
               }
rx_accept:
@@ -3020,6 +3096,11 @@
                       sc->sc_rx_th.wr_tsf = htole64(
                               ath_extend_tsf(ds->ds_rxstat.rs_tstamp, tsf));
                       sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags;
+                       if (ds->ds_rxstat.rs_status &
+                           (HAL_RXERR_CRC|HAL_RXERR_PHY)) {
+                               sc->sc_rx_th.wr_flags |=
+                                   IEEE80211_RADIOTAP_F_BADFCS;
+                       }
                       sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate;
                       sc->sc_rx_th.wr_antsignal = ds->ds_rxstat.rs_rssi + nf;
                       sc->sc_rx_th.wr_antnoise = nf;
@@ -3030,6 +3111,10 @@
               }
#endif

+               if (ds->ds_rxstat.rs_status & rxerr_tap) {
+                       m_freem(m);
+                       goto rx_next;
+               }
               /*
                * From this point on we assume the frame is at least
                * as large as ieee80211_frame_min; verify that.
@@ -3111,8 +3196,10 @@

       /* rx signal state monitoring */
       ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
+#if 0
       if (ath_hal_radar_event(ah))
               TASK_RUN_OR_ENQUEUE(&sc->sc_radartask);
+#endif
       if (ngood)
               sc->sc_lastrx = tsf;

@@ -3715,7 +3802,7 @@
                        */
                       dur += ath_hal_computetxtime(ah, rt,
                           deduct_pad_bytes(m0->m_nextpkt->m_pkthdr.len,
-                               hdrlen) -
+                               hdrlen) -
                           deduct_pad_bytes(m0->m_pkthdr.len, hdrlen) + pktlen,
                           rix, shortPreamble);
               }
@@ -3866,7 +3953,7 @@
                       , ds0                   /* first descriptor */
               );

-               /* NB: The desc swap function becomes void,
+               /* NB: The desc swap function becomes void,
                * if descriptor swapping is not enabled
                */
               ath_desc_swap(ds);
@@ -3938,11 +4025,9 @@
               }
               ds0 = &bf->bf_desc[0];
               ds = &bf->bf_desc[bf->bf_nseg - 1];
-               status = ath_hal_txprocdesc(ah, ds);
-#ifdef AR_DEBUG
+               status = ath_hal_txprocdesc(ah, ds, &ds->ds_txstat);
               if (sc->sc_debug & ATH_DEBUG_XMIT_DESC)
                       ath_printtxbuf(bf, status == HAL_OK);
-#endif
               if (status == HAL_EINPROGRESS) {
                       ATH_TXQ_UNLOCK(txq);
                       break;
@@ -4114,6 +4199,7 @@
       struct ath_hal *ah = sc->sc_ah;
       struct ieee80211_node *ni;
       struct ath_buf *bf;
+       struct ath_desc *ds;

       /*
        * NB: this assumes output has been stopped and
@@ -4129,11 +4215,11 @@
               }
               ATH_TXQ_REMOVE_HEAD(txq, bf_list);
               ATH_TXQ_UNLOCK(txq);
-#ifdef AR_DEBUG
+               ds = &bf->bf_desc[bf->bf_nseg - 1];
               if (sc->sc_debug & ATH_DEBUG_RESET)
                       ath_printtxbuf(bf,
-                               ath_hal_txprocdesc(ah, bf->bf_desc) == HAL_OK);
-#endif /* AR_DEBUG */
+                               ath_hal_txprocdesc(ah, bf->bf_desc,
+                                       &ds->ds_txstat) == HAL_OK);
               bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
               m_freem(bf->bf_m);
               bf->bf_m = NULL;
@@ -4199,12 +4285,12 @@
       ((struct ath_desc *)((char *)(_sc)->sc_rxdma.dd_desc + \
               ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
       struct ath_hal *ah = sc->sc_ah;
+       u_int64_t tsf;

       ath_hal_stoppcurecv(ah);        /* disable PCU */
       ath_hal_setrxfilter(ah, 0);     /* clear recv filter */
       ath_hal_stopdmarecv(ah);        /* disable DMA engine */
       DELAY(3000);                    /* 3ms is long enough for 1 frame */
-#ifdef AR_DEBUG
       if (sc->sc_debug & (ATH_DEBUG_RESET | ATH_DEBUG_FATAL)) {
               struct ath_buf *bf;

@@ -4212,13 +4298,14 @@
                       (void *)(uintptr_t) ath_hal_getrxbuf(ah), sc->sc_rxlink);
               STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
                       struct ath_desc *ds = bf->bf_desc;
+                       tsf = ath_hal_gettsf64(sc->sc_ah);
                       HAL_STATUS status = ath_hal_rxprocdesc(ah, ds,
-                               bf->bf_daddr, PA2DESC(sc, ds->ds_link));
+                               bf->bf_daddr, PA2DESC(sc, ds->ds_link),
+                               tsf, &ds->ds_rxstat);
                       if (status == HAL_OK || (sc->sc_debug & ATH_DEBUG_FATAL))
                               ath_printrxbuf(bf, status == HAL_OK);
               }
       }
-#endif
       sc->sc_rxlink = NULL;           /* just in case */
#undef PA2DESC
}
@@ -4288,6 +4375,7 @@
               htole16(flags);
}

+#if 0
/*
 * Poll for a channel clear indication; this is required
 * for channels requiring DFS and not previously visited
@@ -4320,6 +4408,7 @@
       } else
               callout_reset(&sc->sc_dfs_ch, 2 * hz, ath_dfswait, sc);
}
+#endif

/*
 * Set/change channels.  If the channel is really being changed,
@@ -4392,6 +4481,7 @@
               ic->ic_ibss_chan = chan;
               ath_chan_change(sc, chan);

+#if 0
               /*
                * Handle DFS required waiting period to determine
                * if channel is clear of radar traffic.
@@ -4410,6 +4500,7 @@
                               callout_stop(&sc->sc_dfs_ch);
#undef DFS_NOT_CLEAR
               }
+#endif

               /*
                * Re-enable interrupts.
@@ -4520,7 +4611,9 @@

       callout_stop(&sc->sc_scan_ch);
       callout_stop(&sc->sc_cal_ch);
+#if 0
       callout_stop(&sc->sc_dfs_ch);
+#endif
       ath_hal_setledstate(ah, leds[nstate]);  /* set LED */

       if (nstate == IEEE80211_S_INIT) {
@@ -5036,7 +5129,7 @@
                   !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
       }
}
-#endif /* AR_DEBUG */
+#endif /* AR_DEBUG */

static void
ath_watchdog(struct ifnet *ifp)
@@ -5148,6 +5241,8 @@
       ATH_LOCK(sc);
       switch (cmd) {
       case SIOCSIFFLAGS:
+               if ((error = ifioctl_common(ifp, cmd, data)) != 0)
+                       break;
               if (IS_RUNNING(ifp)) {
                       /*
                        * To avoid rescanning another access point,
Index: sys/dev/ic/athrate-amrr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/athrate-amrr.c,v
retrieving revision 1.10
diff -u -r1.10 athrate-amrr.c
--- sys/dev/ic/athrate-amrr.c   4 Jan 2008 21:17:56 -0000       1.10
+++ sys/dev/ic/athrate-amrr.c   15 May 2009 13:10:51 -0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: athrate-amrr.c,v 1.10 2008/01/04 21:17:56 ad Exp $ */
+/*     $NetBSD: athrate-amrr.c,v 1.11 2008/12/11 05:45:29 alc Exp $ */

/*-
 * Copyright (c) 2004 INRIA
@@ -43,7 +43,7 @@
__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/amrr/amrr.c,v 1.10 2005/08/09 10:19:43 rwatson Exp $");
#endif
#ifdef __NetBSD__
-__KERNEL_RCSID(0, "$NetBSD: athrate-amrr.c,v 1.10 2008/01/04 21:17:56 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: athrate-amrr.c,v 1.11 2008/12/11 05:45:29 alc Exp $");
#endif

/*
@@ -77,7 +77,8 @@

#include <dev/ic/athvar.h>
#include <dev/ic/athrate-amrr.h>
-#include <contrib/dev/ath/ah_desc.h>
+
+#include <external/isc/atheros_hal/dist/ah.h>

#define        AMRR_DEBUG
#ifdef AMRR_DEBUG
Index: sys/dev/ic/athrate-onoe.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/athrate-onoe.c,v
retrieving revision 1.12
diff -u -r1.12 athrate-onoe.c
--- sys/dev/ic/athrate-onoe.c   4 Jan 2008 21:17:57 -0000       1.12
+++ sys/dev/ic/athrate-onoe.c   15 May 2009 13:10:51 -0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: athrate-onoe.c,v 1.12 2008/01/04 21:17:57 ad Exp $ */
+/*     $NetBSD: athrate-onoe.c,v 1.13 2008/12/11 05:45:29 alc Exp $ */

/*-
 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
@@ -41,7 +41,7 @@
__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.c,v 1.10 2005/08/09 10:19:43 rwatson Exp $");
#endif
#ifdef __NetBSD__
-__KERNEL_RCSID(0, "$NetBSD: athrate-onoe.c,v 1.12 2008/01/04 21:17:57 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: athrate-onoe.c,v 1.13 2008/12/11 05:45:29 alc Exp $");
#endif

/*
@@ -74,7 +74,8 @@
#include <dev/ic/ath_netbsd.h>
#include <dev/ic/athvar.h>
#include <dev/ic/athrate-onoe.h>
-#include <contrib/dev/ath/ah_desc.h>
+
+#include <external/isc/atheros_hal/dist/ah.h>

#define        ONOE_DEBUG
#ifdef ONOE_DEBUG
Index: sys/dev/ic/athrate-sample.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/athrate-sample.c,v
retrieving revision 1.16
diff -u -r1.16 athrate-sample.c
--- sys/dev/ic/athrate-sample.c 9 Jul 2008 19:47:24 -0000       1.16
+++ sys/dev/ic/athrate-sample.c 15 May 2009 13:10:51 -0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: athrate-sample.c,v 1.16 2008/07/09 19:47:24 joerg Exp $ */
+/*     $NetBSD: athrate-sample.c,v 1.17 2008/12/11 05:45:29 alc Exp $ */

/*-
 * Copyright (c) 2005 John Bicket
@@ -41,7 +41,7 @@
__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.c,v 1.9 2005/07/22 16:50:17 sam Exp $");
#endif
#ifdef __NetBSD__
-__KERNEL_RCSID(0, "$NetBSD: athrate-sample.c,v 1.16 2008/07/09 19:47:24 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: athrate-sample.c,v 1.17 2008/12/11 05:45:29 alc Exp $");
#endif


@@ -74,9 +74,9 @@
#include <netinet/in.h>
#endif

+#include "ah_desc.h"
#include <dev/ic/athvar.h>
#include <dev/ic/athrate-sample.h>
-#include <contrib/dev/ath/ah_desc.h>

#define        SAMPLE_DEBUG
#ifdef SAMPLE_DEBUG
Index: sys/dev/ic/athvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/athvar.h,v
retrieving revision 1.25
diff -u -r1.25 athvar.h
--- sys/dev/ic/athvar.h 9 Jul 2008 19:47:24 -0000       1.25
+++ sys/dev/ic/athvar.h 15 May 2009 13:10:51 -0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: athvar.h,v 1.25 2008/07/09 19:47:24 joerg Exp $        */
+/*     $NetBSD: athvar.h,v 1.26 2008/12/11 05:45:29 alc Exp $  */

/*-
 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
@@ -44,9 +44,11 @@
#ifndef _DEV_ATH_ATHVAR_H
#define _DEV_ATH_ATHVAR_H

-#include <dev/ic/ath_netbsd.h>
-#include <contrib/dev/ath/ah.h>
#include <net80211/ieee80211_radiotap.h>
+
+#include <external/isc/atheros_hal/dist/ah.h>
+
+#include <dev/ic/ath_netbsd.h>
#include <dev/ic/athioctl.h>
#include <dev/ic/athrate.h>

@@ -77,6 +79,12 @@
 */
#define        ATH_KEYMAX      128             /* max key cache size we handle */
#define        ATH_KEYBYTES    (ATH_KEYMAX/NBBY)       /* storage space in bytes */
+/*
+ * Convert from net80211 layer values to Ath layer values. Hopefully this will
+ * be optimised away when the two constants are the same.
+ */
+typedef unsigned int ath_keyix_t;
+#define ATH_KEY(_keyix) ((_keyix == IEEE80211_KEYIX_NONE) ? HAL_TXKEYIX_INVALID : _keyix)

/* driver-specific node state */
struct ath_node {
@@ -454,6 +462,12 @@
       (*(_pcc) = (_ah)->ah_countryCode)
#define        ath_hal_tkipsplit(_ah) \
       (ath_hal_getcapability(_ah, HAL_CAP_TKIP_SPLIT, 0, NULL) == HAL_OK)
+#define ath_hal_settkipmic(_ah, _v) \
+       (ath_hal_setcapability(_ah, HAL_CAP_TKIP_MIC, 1, _v, NULL) == HAL_OK)
+#define ath_hal_settkipsplit(_ah, _v) \
+       (ath_hal_setcapability(_ah, HAL_CAP_TKIP_SPLIT, 1, _v, NULL) == HAL_OK)
+#define ath_hal_wmetkipmic(_ah) \
+       (ath_hal_getcapability(_ah, HAL_CAP_WME_TKIPMIC, 0, NULL) == HAL_OK)
#define        ath_hal_hwphycounters(_ah) \
       (ath_hal_getcapability(_ah, HAL_CAP_PHYCOUNTERS, 0, NULL) == HAL_OK)
#define        ath_hal_hasdiversity(_ah) \
@@ -528,8 +542,8 @@

#define        ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \
       ((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq)))
-#define        ath_hal_rxprocdesc(_ah, _ds, _dspa, _dsnext) \
-       ((*(_ah)->ah_procRxDesc)((_ah), (_ds), (_dspa), (_dsnext), 0))
+#define        ath_hal_rxprocdesc(_ah, _ds, _dspa, _dsnext, tsf, a5) \
+       ((*(_ah)->ah_procRxDesc)((_ah), (_ds), (_dspa), (_dsnext), (tsf), (a5)))
#define        ath_hal_setuptxdesc(_ah, _ds, _plen, _hlen, _atype, _txpow, \
               _txr0, _txtr0, _keyix, _ant, _flags, \
               _rtsrate, _rtsdura) \
@@ -542,8 +556,8 @@
               (_txr1), (_txtr1), (_txr2), (_txtr2), (_txr3), (_txtr3)))
#define        ath_hal_filltxdesc(_ah, _ds, _l, _first, _last, _ds0) \
       ((*(_ah)->ah_fillTxDesc)((_ah), (_ds), (_l), (_first), (_last), (_ds0)))
-#define        ath_hal_txprocdesc(_ah, _ds) \
-       ((*(_ah)->ah_procTxDesc)((_ah), (_ds)))
+#define        ath_hal_txprocdesc(_ah, _ds, _a2) \
+       ((*(_ah)->ah_procTxDesc)((_ah), (_ds), (_a2)))
#define        ath_hal_gettxintrtxqs(_ah, _txqs) \
       ((*(_ah)->ah_getTxIntrQueue)((_ah), (_txqs)))

@@ -558,7 +572,5 @@
       ((*(_ah)->ah_processDfs)((_ah), (_chan)))
#define ath_hal_checknol(_ah, _chan, _nchans) \
       ((*(_ah)->ah_dfsNolCheck)((_ah), (_chan), (_nchans)))
-#define ath_hal_radar_wait(_ah, _chan) \
-       ((*(_ah)->ah_radarWait)((_ah), (_chan)))

#endif /* _DEV_ATH_ATHVAR_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/conf/files.ath_hal     2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,138 @@
+#      $NetBSD: files.ath_hal,v 1.1 2008/12/11 14:11:43 alc Exp $
+
+defflag opt_athhal.h   ATHHAL_ASSERT ATHHAL_DEBUG ATHHAL_DEBUG_ALQ
+defflag opt_athhal.h   ATHHAL_WRITE_EEPROM ATHHAL_WRITE_REGDOMAIN
+
+define athhal_eeprom_v1
+define athhal_eeprom_v3
+define athhal_eeprom_v14
+
+file   external/isc/atheros_hal/dist/ah.c              ath
+file   external/isc/atheros_hal/dist/ah_eeprom_v1.c    ath & athhal_eeprom_v1
+file   external/isc/atheros_hal/dist/ah_eeprom_v3.c    ath & athhal_eeprom_v3
+file   external/isc/atheros_hal/dist/ah_eeprom_v14.c   ath & athhal_eeprom_v14
+file   external/isc/atheros_hal/dist/ah_regdomain.c    ath
+
+# Atheros HAL's OS dependant code
+#
+file   external/isc/atheros_hal/ic/ah_osdep.c  ath
+
+
+# Atheros AR5210 family
+#
+defflag opt_athhal.h   ATHHAL_AR5210: athhal_eeprom_v1
+
+file   external/isc/atheros_hal/dist/ar5210/ar5210_attach.c    ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_beacon.c    ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_interrupts.c        ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_keycache.c  ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_misc.c      ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_phy.c       ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_power.c     ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_recv.c      ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_reset.c     ath & athhal_ar5210
+file   external/isc/atheros_hal/dist/ar5210/ar5210_xmit.c      ath & athhal_ar5210
+
+# Atheros AR5211 family
+#
+defflag opt_athhal.h   ATHHAL_AR5211: athhal_eeprom_v3
+
+file   external/isc/atheros_hal/dist/ar5211/ar5211_attach.c    ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_beacon.c    ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_interrupts.c        ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_keycache.c  ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_misc.c      ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_phy.c       ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_power.c     ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_recv.c      ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_reset.c     ath & athhal_ar5211
+file   external/isc/atheros_hal/dist/ar5211/ar5211_xmit.c      ath & athhal_ar5211
+
+# Atheros AR5212/AR5312 RF support
+#
+defflag opt_athhal.h   ATHHAL_RF2316
+defflag opt_athhal.h   ATHHAL_RF2317
+defflag opt_athhal.h   ATHHAL_RF2413
+defflag opt_athhal.h   ATHHAL_RF2425
+defflag opt_athhal.h   ATHHAL_RF5111
+defflag opt_athhal.h   ATHHAL_RF5112
+defflag opt_athhal.h   ATHHAL_RF5413
+
+file   external/isc/atheros_hal/dist/ar5212/ar2316.c           ath & athhal_rf2316
+file   external/isc/atheros_hal/dist/ar5212/ar2317.c           ath & athhal_rf2317
+file   external/isc/atheros_hal/dist/ar5212/ar2413.c           ath & athhal_rf2413
+file   external/isc/atheros_hal/dist/ar5212/ar2425.c           ath & athhal_rf2425
+file   external/isc/atheros_hal/dist/ar5212/ar5111.c           ath & athhal_rf5111
+file   external/isc/atheros_hal/dist/ar5212/ar5112.c           ath & athhal_rf5112
+file   external/isc/atheros_hal/dist/ar5212/ar5413.c           ath & athhal_rf5413
+
+# Atheros AR5212 family
+#
+define athhal_ar5212_attach
+define athhal_ar5212_subr
+
+defflag opt_athhal.h   ATHHAL_AR5212: athhal_eeprom_v3,
+                       athhal_ar5212_attach, athhal_ar5212_subr
+
+defflag opt_athhal.h   ATHHAL_AR5311: ATHHAL_AR5212
+
+file   external/isc/atheros_hal/dist/ar5212/ar5212_ani.c       ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_attach.c    ath & athhal_ar5212_attach
+file   external/isc/atheros_hal/dist/ar5212/ar5212_beacon.c    ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_eeprom.c    ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_gpio.c      ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_interrupts.c        ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_keycache.c  ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_misc.c      ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_phy.c       ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_power.c     ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_recv.c      ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_reset.c     ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_rfgain.c    ath & athhal_ar5212_subr
+file   external/isc/atheros_hal/dist/ar5212/ar5212_xmit.c      ath & athhal_ar5212_subr
+
+# Atheros AR5312 family
+#
+defflag opt_athhal.h   ATHHAL_AR5312: athhal_eeprom_v3, athhal_ar5212_subr
+
+defflag opt_athhal.h   ATHHAL_AR2316: ATHHAL_AR5312
+defflag opt_athhal.h   ATHHAL_AR2317: ATHHAL_AR5312
+
+file   external/isc/atheros_hal/dist/ar5312/ar5312_attach.c    ath & athhal_ar5312
+file   external/isc/atheros_hal/dist/ar5312/ar5312_eeprom.c    ath & athhal_ar5312
+file   external/isc/atheros_hal/dist/ar5312/ar5312_gpio.c      ath & athhal_ar5312
+file   external/isc/atheros_hal/dist/ar5312/ar5312_interrupts.c        ath & athhal_ar5312
+file   external/isc/atheros_hal/dist/ar5312/ar5312_misc.c      ath & athhal_ar5312
+file   external/isc/atheros_hal/dist/ar5312/ar5312_power.c     ath & athhal_ar5312
+file   external/isc/atheros_hal/dist/ar5312/ar5312_reset.c     ath & athhal_ar5312
+file   external/isc/atheros_hal/dist/ar5312/ar5315_gpio.c      ath & (athhal_ar2316 | athhal_ar2317)
+
+# Atheros AR5416 family
+#
+defflag opt_athhal.h   ATHHAL_AR5416: athhal_eeprom_v14, athhal_ar5212_subr
+defflag opt_athhal.h   ATHHAL_AR9280: ATHHAL_AR5416
+
+file   external/isc/atheros_hal/dist/ar5416/ar2133.c           ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_ani.c       ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_attach.c    ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_beacon.c    ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_cal.c       ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcdc.c ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcgain.c       ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_cal_iq.c    ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_eeprom.c    ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_gpio.c      ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_interrupts.c        ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_keycache.c  ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_misc.c      ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_phy.c       ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_power.c     ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_recv.c      ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_reset.c     ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar5416_xmit.c      ath & athhal_ar5416
+file   external/isc/atheros_hal/dist/ar5416/ar9160_attach.c    ath & athhal_ar5416
+
+#
+#
+makeoptions ath                CPPFLAGS+="-I${S}/external/isc/atheros_hal/dist"
+makeoptions ath                CPPFLAGS+="-I${S}/external/isc/atheros_hal/ic"
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/conf/std.ath_hal       2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,25 @@
+#options ATHHAL_ASSERT
+#options ATHHAL_DEBUG
+#options ATHHAL_DEBUG_ALQ
+
+# Atheros HAL Chipset Support
+#
+options ATHHAL_AR5210
+options ATHHAL_AR5211
+options ATHHAL_AR5212
+options ATHHAL_AR5311
+#options ATHHAL_AR5312
+#options ATHHAL_AR2316
+#options ATHHAL_AR2317
+options ATHHAL_AR5416
+#options ATHHAL_AR9280
+
+# Atheros AR5212/AR5312 RF Support
+#
+options ATHHAL_RF2316
+options ATHHAL_RF2317
+options ATHHAL_RF2413
+options ATHHAL_RF2425
+options ATHHAL_RF5111
+options ATHHAL_RF5112
+options ATHHAL_RF5413
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211.h   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AR5211_H_
+#define _ATH_AR5211_H_
+
+#include "ah_eeprom.h"
+
+#define        AR5211_MAGIC    0x19570405
+
+/* Classes for WME streams */
+#define        AC_BK   0
+#define        AC_BE   1
+#define        AC_VI   2
+#define        AC_VO   3
+
+/* DCU Transmit Filter macros */
+#define CALC_MMR(dcu, idx) \
+       ( (4 * dcu) + (idx < 32 ? 0 : (idx < 64 ? 1 : (idx < 96 ? 2 : 3))) )
+#define TXBLK_FROM_MMR(mmr) \
+       (AR_D_TXBLK_BASE + ((mmr & 0x1f) << 6) + ((mmr & 0x20) >> 3))
+#define CALC_TXBLK_ADDR(dcu, idx)      (TXBLK_FROM_MMR(CALC_MMR(dcu, idx)))
+#define CALC_TXBLK_VALUE(idx)          (1 << (idx & 0x1f))
+
+/* MAC register values */
+
+#define INIT_INTERRUPT_MASK \
+       ( AR_IMR_TXERR  | AR_IMR_TXOK | AR_IMR_RXORN | \
+         AR_IMR_RXERR  | AR_IMR_RXOK | AR_IMR_TXURN | \
+         AR_IMR_HIUERR )
+#define INIT_BEACON_CONTROL \
+       ( (INIT_RESET_TSF << 24)  | (INIT_BEACON_EN << 23) | \
+         (INIT_TIM_OFFSET << 16) | INIT_BEACON_PERIOD )
+
+#define INIT_CONFIG_STATUS     0x00000000
+#define INIT_RSSI_THR          0x00000700      /* Missed beacon counter initialized to 0x7 (max is 0xff) */
+#define INIT_IQCAL_LOG_COUNT_MAX       0xF
+#define INIT_BCON_CNTRL_REG    0x00000000
+
+#define INIT_BEACON_PERIOD     0xffff
+#define INIT_TIM_OFFSET                0
+#define INIT_BEACON_EN         0               /* this should be set by AP only when it's ready */
+#define INIT_RESET_TSF         0
+
+/*
+ * Various fifo fill before Tx start, in 64-byte units
+ * i.e. put the frame in the air while still DMAing
+ */
+#define MIN_TX_FIFO_THRESHOLD     0x1
+#define MAX_TX_FIFO_THRESHOLD     ((IEEE80211_MAX_LEN / 64) + 1)
+#define INIT_TX_FIFO_THRESHOLD   MIN_TX_FIFO_THRESHOLD
+
+/*
+ * Gain support.
+ */
+typedef struct _gainOptStep {
+       int16_t paramVal[4];
+       int32_t stepGain;
+       int8_t  stepName[16];
+} GAIN_OPTIMIZATION_STEP;
+
+typedef struct {
+       uint32_t        numStepsInLadder;
+       uint32_t        defaultStepNum;
+       GAIN_OPTIMIZATION_STEP optStep[10];
+} GAIN_OPTIMIZATION_LADDER;
+
+typedef struct {
+       uint32_t        currStepNum;
+       uint32_t        currGain;
+       uint32_t        targetGain;
+       uint32_t        loTrig;
+       uint32_t        hiTrig;
+       uint32_t        active;
+       const GAIN_OPTIMIZATION_STEP *currStep;
+} GAIN_VALUES;
+
+enum {
+       RFGAIN_INACTIVE,
+       RFGAIN_READ_REQUESTED,
+       RFGAIN_NEED_CHANGE
+};
+
+/*
+ * Header Info - general parameters and
+ * values set for each chipset board solution
+ * that are programmed every reset
+ */
+struct ath_hal_5211 {
+       struct ath_hal_private  ah_priv;        /* base class */
+
+       GAIN_VALUES     ah_gainValues;
+
+       uint8_t         ah_macaddr[IEEE80211_ADDR_LEN];
+       uint8_t         ah_bssid[IEEE80211_ADDR_LEN];
+
+       /*
+        * Runtime state.
+        */
+       uint32_t        ah_maskReg;             /* copy of AR_IMR */
+       uint32_t        ah_txOkInterruptMask;
+       uint32_t        ah_txErrInterruptMask;
+       uint32_t        ah_txDescInterruptMask;
+       uint32_t        ah_txEolInterruptMask;
+       uint32_t        ah_txUrnInterruptMask;
+       HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES];
+       HAL_POWER_MODE  ah_powerMode;
+       HAL_ANT_SETTING ah_diversityControl;    /* antenna setting */
+       uint32_t        ah_calibrationTime;
+       HAL_BOOL        ah_bIQCalibration;
+       HAL_CHANNEL     ah_curchan;             /* XXX */
+       int             ah_rfgainState;
+       uint32_t        ah_tx6PowerInHalfDbm;   /* power output for 6Mb tx */
+       uint32_t        ah_staId1Defaults;      /* STA_ID1 default settings */
+       uint32_t        ah_beaconInterval;
+       uint32_t        ah_rssiThr;             /* RSSI_THR settings */
+
+       u_int           ah_sifstime;            /* user-specified sifs time */
+       u_int           ah_slottime;            /* user-specified slot time */
+       u_int           ah_acktimeout;          /* user-specified ack timeout */
+       u_int           ah_ctstimeout;          /* user-specified cts timeout */
+       /*
+        * RF Silent handling.
+        */
+       uint32_t        ah_gpioSelect;          /* GPIO pin to use */
+       uint32_t        ah_polarity;            /* polarity to disable RF */
+       uint32_t        ah_gpioBit;             /* after init, prev value */
+};
+#define        AH5211(ah)      ((struct ath_hal_5211 *)(ah))
+
+struct ath_hal;
+
+extern struct ath_hal *ar5211Attach(uint16_t, HAL_SOFTC,
+       HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS *);
+extern void ar5211Detach(struct ath_hal *);
+
+extern HAL_BOOL ar5211Reset(struct ath_hal *, HAL_OPMODE,
+               HAL_CHANNEL *, HAL_BOOL bChannelChange, HAL_STATUS *);
+extern HAL_BOOL ar5211PhyDisable(struct ath_hal *);
+extern HAL_BOOL ar5211Disable(struct ath_hal *);
+extern HAL_BOOL ar5211ChipReset(struct ath_hal *, uint16_t);
+extern HAL_BOOL ar5211PerCalibration(struct ath_hal *, HAL_CHANNEL *, HAL_BOOL *);
+extern HAL_BOOL ar5211PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan,
+               u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone);
+extern HAL_BOOL ar5211ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan);
+extern HAL_BOOL ar5211SetTxPowerLimit(struct ath_hal *, uint32_t limit);
+extern HAL_BOOL ar5211SetTransmitPower(struct ath_hal *, HAL_CHANNEL *);
+extern HAL_BOOL ar5211CalNoiseFloor(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+extern HAL_BOOL ar5211SetAntennaSwitchInternal(struct ath_hal *,
+               HAL_ANT_SETTING, const HAL_CHANNEL *);
+extern int16_t ar5211GetNfAdjust(struct ath_hal *,
+               const HAL_CHANNEL_INTERNAL *);
+extern HAL_BOOL ar5211ResetDma(struct ath_hal *, HAL_OPMODE);
+extern void ar5211InitializeGainValues(struct ath_hal *);
+extern HAL_RFGAIN ar5211GetRfgain(struct ath_hal *);
+extern void ar5211SetPCUConfig(struct ath_hal *);
+
+extern  HAL_BOOL ar5211SetTxQueueProps(struct ath_hal *ah, int q,
+               const HAL_TXQ_INFO *qInfo);
+extern HAL_BOOL ar5211GetTxQueueProps(struct ath_hal *ah, int q,
+               HAL_TXQ_INFO *qInfo);
+extern int ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
+               const HAL_TXQ_INFO *qInfo);
+extern HAL_BOOL ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q);
+extern HAL_BOOL ar5211ResetTxQueue(struct ath_hal *ah, u_int q);
+extern uint32_t ar5211GetTxDP(struct ath_hal *, u_int);
+extern HAL_BOOL ar5211SetTxDP(struct ath_hal *, u_int, uint32_t txdp);
+extern HAL_BOOL ar5211UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL);
+extern HAL_BOOL ar5211StartTxDma(struct ath_hal *, u_int);
+extern HAL_BOOL ar5211StopTxDma(struct ath_hal *, u_int);
+extern uint32_t ar5211NumTxPending(struct ath_hal *, u_int qnum);
+extern HAL_BOOL ar5211IsTxQueueStopped(struct ath_hal *, u_int);
+extern HAL_BOOL ar5211GetTransmitFilterIndex(struct ath_hal *, uint32_t);
+extern HAL_BOOL ar5211SetupTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower,
+               u_int txRate0, u_int txTries0,
+               u_int keyIx, u_int antMode, u_int flags,
+               u_int rtsctsRate, u_int rtsctsDuration,
+                u_int compicvLen, u_int compivLen, u_int comp);
+extern HAL_BOOL ar5211SetupXTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int txRate1, u_int txRetries1,
+               u_int txRate2, u_int txRetries2,
+               u_int txRate3, u_int txRetries3);
+extern HAL_BOOL ar5211FillTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+               const struct ath_desc *ds0);
+extern HAL_STATUS ar5211ProcTxDesc(struct ath_hal *,
+               struct ath_desc *, struct ath_tx_status *);
+extern  void ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *);
+extern  void ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *);
+
+extern uint32_t ar5211GetRxDP(struct ath_hal *);
+extern void ar5211SetRxDP(struct ath_hal *, uint32_t rxdp);
+extern void ar5211EnableReceive(struct ath_hal *);
+extern HAL_BOOL ar5211StopDmaReceive(struct ath_hal *);
+extern void ar5211StartPcuReceive(struct ath_hal *);
+extern void ar5211StopPcuReceive(struct ath_hal *);
+extern void ar5211SetMulticastFilter(struct ath_hal *,
+               uint32_t filter0, uint32_t filter1);
+extern HAL_BOOL ar5211ClrMulticastFilterIndex(struct ath_hal *, uint32_t);
+extern HAL_BOOL ar5211SetMulticastFilterIndex(struct ath_hal *, uint32_t);
+extern uint32_t ar5211GetRxFilter(struct ath_hal *);
+extern void ar5211SetRxFilter(struct ath_hal *, uint32_t);
+extern HAL_BOOL ar5211SetupRxDesc(struct ath_hal *, struct ath_desc *,
+               uint32_t, u_int flags);
+extern HAL_STATUS ar5211ProcRxDesc(struct ath_hal *, struct ath_desc *,
+               uint32_t, struct ath_desc *, uint64_t,
+               struct ath_rx_status *);
+
+extern void ar5211GetMacAddress(struct ath_hal *, uint8_t *);
+extern HAL_BOOL ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *);
+extern void ar5211GetBssIdMask(struct ath_hal *, uint8_t *);
+extern HAL_BOOL ar5211SetBssIdMask(struct ath_hal *, const uint8_t *);
+extern HAL_BOOL ar5211EepromRead(struct ath_hal *, u_int off, uint16_t *data);
+extern HAL_BOOL ar5211EepromWrite(struct ath_hal *, u_int off, uint16_t data);
+extern HAL_BOOL ar5211SetRegulatoryDomain(struct ath_hal *,
+               uint16_t, HAL_STATUS *);
+extern u_int ar5211GetWirelessModes(struct ath_hal *);
+extern void ar5211EnableRfKill(struct ath_hal *);
+extern uint32_t ar5211GpioGet(struct ath_hal *, uint32_t gpio);
+extern void ar5211GpioSetIntr(struct ath_hal *, u_int, uint32_t ilevel);
+extern HAL_BOOL ar5211GpioCfgOutput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5211GpioCfgInput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5211GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val);
+extern void ar5211SetLedState(struct ath_hal *, HAL_LED_STATE);
+extern u_int ar5211AntennaGet(struct ath_hal *);
+extern void ar5211WriteAssocid(struct ath_hal *,
+               const uint8_t *bssid, uint16_t assocId);
+extern uint64_t ar5211GetTsf64(struct ath_hal *);
+extern uint32_t ar5211GetTsf32(struct ath_hal *);
+extern void ar5211ResetTsf(struct ath_hal *);
+extern uint32_t ar5211GetMaxTurboRate(struct ath_hal *);
+extern uint32_t ar5211GetRandomSeed(struct ath_hal *);
+extern HAL_BOOL ar5211DetectCardPresent(struct ath_hal *);
+extern void ar5211UpdateMibCounters(struct ath_hal *, HAL_MIB_STATS *);
+extern void ar5211EnableHwEncryption(struct ath_hal *);
+extern void ar5211DisableHwEncryption(struct ath_hal *);
+extern HAL_BOOL ar5211SetSlotTime(struct ath_hal *, u_int);
+extern u_int ar5211GetSlotTime(struct ath_hal *);
+extern HAL_BOOL ar5211SetAckTimeout(struct ath_hal *, u_int);
+extern u_int ar5211GetAckTimeout(struct ath_hal *);
+extern HAL_BOOL ar5211SetAckCTSRate(struct ath_hal *, u_int);
+extern u_int ar5211GetAckCTSRate(struct ath_hal *);
+extern HAL_BOOL ar5211SetCTSTimeout(struct ath_hal *, u_int);
+extern u_int ar5211GetCTSTimeout(struct ath_hal *);
+extern HAL_BOOL ar5211SetSifsTime(struct ath_hal *, u_int);
+extern u_int ar5211GetSifsTime(struct ath_hal *);
+extern  HAL_BOOL ar5211SetDecompMask(struct ath_hal *, uint16_t, int);
+extern void ar5211SetCoverageClass(struct ath_hal *, uint8_t, int);
+extern uint32_t ar5211GetCurRssi(struct ath_hal *);
+extern u_int ar5211GetDefAntenna(struct ath_hal *);
+extern void ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna);
+extern HAL_ANT_SETTING ar5211GetAntennaSwitch(struct ath_hal *);
+extern HAL_BOOL ar5211SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
+extern HAL_STATUS ar5211GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE,
+               uint32_t, uint32_t *);
+extern HAL_BOOL ar5211SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE,
+               uint32_t, uint32_t, HAL_STATUS *);
+extern HAL_BOOL ar5211GetDiagState(struct ath_hal *ah, int request,
+               const void *args, uint32_t argsize,
+               void **result, uint32_t *resultsize);
+
+extern u_int ar5211GetKeyCacheSize(struct ath_hal *);
+extern HAL_BOOL ar5211IsKeyCacheEntryValid(struct ath_hal *, uint16_t);
+extern HAL_BOOL ar5211ResetKeyCacheEntry(struct ath_hal *, uint16_t entry);
+extern HAL_BOOL ar5211SetKeyCacheEntry(struct ath_hal *, uint16_t entry,
+                       const HAL_KEYVAL *, const uint8_t *mac,
+                       int xorKey);
+extern HAL_BOOL ar5211SetKeyCacheEntryMac(struct ath_hal *,
+                       uint16_t, const uint8_t *);
+
+extern HAL_BOOL ar5211SetPowerMode(struct ath_hal *, uint32_t powerRequest,
+               int setChip);
+extern HAL_POWER_MODE ar5211GetPowerMode(struct ath_hal *);
+
+extern void ar5211SetBeaconTimers(struct ath_hal *,
+               const HAL_BEACON_TIMERS *);
+extern void ar5211BeaconInit(struct ath_hal *, uint32_t, uint32_t);
+extern void ar5211SetStaBeaconTimers(struct ath_hal *,
+               const HAL_BEACON_STATE *);
+extern void ar5211ResetStaBeaconTimers(struct ath_hal *);
+
+extern HAL_BOOL ar5211IsInterruptPending(struct ath_hal *);
+extern HAL_BOOL ar5211GetPendingInterrupts(struct ath_hal *, HAL_INT *);
+extern HAL_INT ar5211GetInterrupts(struct ath_hal *);
+extern HAL_INT ar5211SetInterrupts(struct ath_hal *, HAL_INT ints);
+
+extern const HAL_RATE_TABLE *ar5211GetRateTable(struct ath_hal *, u_int mode);
+
+extern HAL_BOOL ar5211AniControl(struct ath_hal *, HAL_ANI_CMD, int );
+extern void ar5211AniPoll(struct ath_hal *, const HAL_NODE_STATS *, HAL_CHANNEL *);
+extern void ar5211MibEvent(struct ath_hal *, const HAL_NODE_STATS *);
+#endif /* _ATH_AR5211_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_attach.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_attach.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+#include "ar5211/ar5211phy.h"
+
+#include "ah_eeprom_v3.h"
+
+static HAL_BOOL ar5211GetChannelEdges(struct ath_hal *ah,
+               uint16_t flags, uint16_t *low, uint16_t *high);
+static HAL_BOOL ar5211GetChipPowerLimits(struct ath_hal *ah,
+               HAL_CHANNEL *chans, uint32_t nchans);
+
+static const struct ath_hal_private ar5211hal = {{
+       .ah_magic                       = AR5211_MAGIC,
+       .ah_abi                         = HAL_ABI_VERSION,
+       .ah_countryCode                 = CTRY_DEFAULT,
+
+       .ah_getRateTable                = ar5211GetRateTable,
+       .ah_detach                      = ar5211Detach,
+
+       /* Reset Functions */
+       .ah_reset                       = ar5211Reset,
+       .ah_phyDisable                  = ar5211PhyDisable,
+       .ah_disable                     = ar5211Disable,
+       .ah_setPCUConfig                = ar5211SetPCUConfig,
+       .ah_perCalibration              = ar5211PerCalibration,
+       .ah_perCalibrationN             = ar5211PerCalibrationN,
+       .ah_resetCalValid               = ar5211ResetCalValid,
+       .ah_setTxPowerLimit             = ar5211SetTxPowerLimit,
+       .ah_getChanNoise                = ath_hal_getChanNoise,
+
+       /* Transmit functions */
+       .ah_updateTxTrigLevel           = ar5211UpdateTxTrigLevel,
+       .ah_setupTxQueue                = ar5211SetupTxQueue,
+       .ah_setTxQueueProps             = ar5211SetTxQueueProps,
+       .ah_getTxQueueProps             = ar5211GetTxQueueProps,
+       .ah_releaseTxQueue              = ar5211ReleaseTxQueue,
+       .ah_resetTxQueue                = ar5211ResetTxQueue,
+       .ah_getTxDP                     = ar5211GetTxDP,
+       .ah_setTxDP                     = ar5211SetTxDP,
+       .ah_numTxPending                = ar5211NumTxPending,
+       .ah_startTxDma                  = ar5211StartTxDma,
+       .ah_stopTxDma                   = ar5211StopTxDma,
+       .ah_setupTxDesc                 = ar5211SetupTxDesc,
+       .ah_setupXTxDesc                = ar5211SetupXTxDesc,
+       .ah_fillTxDesc                  = ar5211FillTxDesc,
+       .ah_procTxDesc                  = ar5211ProcTxDesc,
+       .ah_getTxIntrQueue              = ar5211GetTxIntrQueue,
+       .ah_reqTxIntrDesc               = ar5211IntrReqTxDesc,
+
+       /* RX Functions */
+       .ah_getRxDP                     = ar5211GetRxDP,
+       .ah_setRxDP                     = ar5211SetRxDP,
+       .ah_enableReceive               = ar5211EnableReceive,
+       .ah_stopDmaReceive              = ar5211StopDmaReceive,
+       .ah_startPcuReceive             = ar5211StartPcuReceive,
+       .ah_stopPcuReceive              = ar5211StopPcuReceive,
+       .ah_setMulticastFilter          = ar5211SetMulticastFilter,
+       .ah_setMulticastFilterIndex     = ar5211SetMulticastFilterIndex,
+       .ah_clrMulticastFilterIndex     = ar5211ClrMulticastFilterIndex,
+       .ah_getRxFilter                 = ar5211GetRxFilter,
+       .ah_setRxFilter                 = ar5211SetRxFilter,
+       .ah_setupRxDesc                 = ar5211SetupRxDesc,
+       .ah_procRxDesc                  = ar5211ProcRxDesc,
+       .ah_rxMonitor                   = ar5211AniPoll,
+       .ah_procMibEvent                = ar5211MibEvent,
+
+       /* Misc Functions */
+       .ah_getCapability               = ar5211GetCapability,
+       .ah_setCapability               = ar5211SetCapability,
+       .ah_getDiagState                = ar5211GetDiagState,
+       .ah_getMacAddress               = ar5211GetMacAddress,
+       .ah_setMacAddress               = ar5211SetMacAddress,
+       .ah_getBssIdMask                = ar5211GetBssIdMask,
+       .ah_setBssIdMask                = ar5211SetBssIdMask,
+       .ah_setRegulatoryDomain         = ar5211SetRegulatoryDomain,
+       .ah_setLedState                 = ar5211SetLedState,
+       .ah_writeAssocid                = ar5211WriteAssocid,
+       .ah_gpioCfgInput                = ar5211GpioCfgInput,
+       .ah_gpioCfgOutput               = ar5211GpioCfgOutput,
+       .ah_gpioGet                     = ar5211GpioGet,
+       .ah_gpioSet                     = ar5211GpioSet,
+       .ah_gpioSetIntr                 = ar5211GpioSetIntr,
+       .ah_getTsf32                    = ar5211GetTsf32,
+       .ah_getTsf64                    = ar5211GetTsf64,
+       .ah_resetTsf                    = ar5211ResetTsf,
+       .ah_detectCardPresent           = ar5211DetectCardPresent,
+       .ah_updateMibCounters           = ar5211UpdateMibCounters,
+       .ah_getRfGain                   = ar5211GetRfgain,
+       .ah_getDefAntenna               = ar5211GetDefAntenna,
+       .ah_setDefAntenna               = ar5211SetDefAntenna,
+       .ah_getAntennaSwitch            = ar5211GetAntennaSwitch,
+       .ah_setAntennaSwitch            = ar5211SetAntennaSwitch,
+       .ah_setSifsTime                 = ar5211SetSifsTime,
+       .ah_getSifsTime                 = ar5211GetSifsTime,
+       .ah_setSlotTime                 = ar5211SetSlotTime,
+       .ah_getSlotTime                 = ar5211GetSlotTime,
+       .ah_setAckTimeout               = ar5211SetAckTimeout,
+       .ah_getAckTimeout               = ar5211GetAckTimeout,
+       .ah_setAckCTSRate               = ar5211SetAckCTSRate,
+       .ah_getAckCTSRate               = ar5211GetAckCTSRate,
+       .ah_setCTSTimeout               = ar5211SetCTSTimeout,
+       .ah_getCTSTimeout               = ar5211GetCTSTimeout,
+       .ah_setDecompMask               = ar5211SetDecompMask,
+       .ah_setCoverageClass            = ar5211SetCoverageClass,
+
+       /* Key Cache Functions */
+       .ah_getKeyCacheSize             = ar5211GetKeyCacheSize,
+       .ah_resetKeyCacheEntry          = ar5211ResetKeyCacheEntry,
+       .ah_isKeyCacheEntryValid        = ar5211IsKeyCacheEntryValid,
+       .ah_setKeyCacheEntry            = ar5211SetKeyCacheEntry,
+       .ah_setKeyCacheEntryMac         = ar5211SetKeyCacheEntryMac,
+
+       /* Power Management Functions */
+       .ah_setPowerMode                = ar5211SetPowerMode,
+       .ah_getPowerMode                = ar5211GetPowerMode,
+
+       /* Beacon Functions */
+       .ah_setBeaconTimers             = ar5211SetBeaconTimers,
+       .ah_beaconInit                  = ar5211BeaconInit,
+       .ah_setStationBeaconTimers      = ar5211SetStaBeaconTimers,
+       .ah_resetStationBeaconTimers    = ar5211ResetStaBeaconTimers,
+
+       /* Interrupt Functions */
+       .ah_isInterruptPending          = ar5211IsInterruptPending,
+       .ah_getPendingInterrupts        = ar5211GetPendingInterrupts,
+       .ah_getInterrupts               = ar5211GetInterrupts,
+       .ah_setInterrupts               = ar5211SetInterrupts },
+
+       .ah_getChannelEdges             = ar5211GetChannelEdges,
+       .ah_getWirelessModes            = ar5211GetWirelessModes,
+       .ah_eepromRead                  = ar5211EepromRead,
+#ifdef AH_SUPPORT_WRITE_EEPROM
+       .ah_eepromWrite                 = ar5211EepromWrite,
+#endif
+       .ah_gpioCfgInput                = ar5211GpioCfgInput,
+       .ah_gpioCfgOutput               = ar5211GpioCfgOutput,
+       .ah_gpioGet                     = ar5211GpioGet,
+       .ah_gpioSet                     = ar5211GpioSet,
+       .ah_gpioSetIntr                 = ar5211GpioSetIntr,
+       .ah_getChipPowerLimits          = ar5211GetChipPowerLimits,
+};
+
+static HAL_BOOL ar5211ChipTest(struct ath_hal *);
+static HAL_BOOL ar5211FillCapabilityInfo(struct ath_hal *ah);
+
+/*
+ * Return the revsion id for the radio chip.  This
+ * fetched via the PHY.
+ */
+static uint32_t
+ar5211GetRadioRev(struct ath_hal *ah)
+{
+       uint32_t val;
+       int i;
+
+       OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16);
+       for (i = 0; i < 8; i++)
+               OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000);
+       val = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 24) & 0xff;
+       val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
+       return ath_hal_reverseBits(val, 8);
+}
+
+/*
+ * Attach for an AR5211 part.
+ */
+struct ath_hal *
+ar5211Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+       struct ath_hal_5211 *ahp;
+       struct ath_hal *ah;
+       uint32_t val;
+       uint16_t eeval;
+       HAL_STATUS ecode;
+
+       HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
+           __func__, sc, (void*) st, (void*) sh);
+
+       /* NB: memory is returned zero'd */
+       ahp = ath_hal_malloc(sizeof (struct ath_hal_5211));
+       if (ahp == AH_NULL) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                   "%s: cannot allocate memory for state block\n", __func__);
+               ecode = HAL_ENOMEM;
+               goto bad;
+       }
+       ah = &ahp->ah_priv.h;
+       /* set initial values */
+       OS_MEMCPY(&ahp->ah_priv, &ar5211hal, sizeof(struct ath_hal_private));
+       ah->ah_sc = sc;
+       ah->ah_st = st;
+       ah->ah_sh = sh;
+
+       ah->ah_devid = devid;                   /* NB: for AH_DEBUG_ALQ */
+       AH_PRIVATE(ah)->ah_devid = devid;
+       AH_PRIVATE(ah)->ah_subvendorid = 0;     /* XXX */
+
+       AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER;
+       AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX;  /* no scaling */
+
+       ahp->ah_diversityControl = HAL_ANT_VARIABLE;
+       ahp->ah_staId1Defaults = 0;
+       ahp->ah_rssiThr = INIT_RSSI_THR;
+       ahp->ah_sifstime = (u_int) -1;
+       ahp->ah_slottime = (u_int) -1;
+       ahp->ah_acktimeout = (u_int) -1;
+       ahp->ah_ctstimeout = (u_int) -1;
+
+       if (!ar5211ChipReset(ah, AH_FALSE)) {   /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+       if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B) {
+               /* set it back to OFDM mode to be able to read analog rev id */
+               OS_REG_WRITE(ah, AR5211_PHY_MODE, AR5211_PHY_MODE_OFDM);
+               OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44);
+               OS_DELAY(1000);
+       }
+
+       /* Read Revisions from Chips */
+       val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M;
+       AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;
+       AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION_M;
+
+       if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_MAUI_2 ||
+           AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_OAHU) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: Mac Chip Rev 0x%x is not supported by this driver\n",
+                   __func__, AH_PRIVATE(ah)->ah_macVersion);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+       }
+
+       AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
+
+       if (!ar5211ChipTest(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
+                   __func__);
+               ecode = HAL_ESELFTEST;
+               goto bad;
+       }
+
+       /* Set correct Baseband to analog shift setting to access analog chips. */
+       if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
+               OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007);
+       } else {
+               OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047);
+       }
+       OS_DELAY(2000);
+
+       /* Read Radio Chip Rev Extract */
+       AH_PRIVATE(ah)->ah_analog5GhzRev = ar5211GetRadioRev(ah);
+       if ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xf0) != RAD5_SREV_MAJOR) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: 5G Radio Chip Rev 0x%02X is not supported by this "
+                   "driver\n", __func__, AH_PRIVATE(ah)->ah_analog5GhzRev);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+       }
+
+       val = (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_EEPROM_SIZE_M) >>
+               AR_PCICFG_EEPROM_SIZE_S;
+       if (val != AR_PCICFG_EEPROM_SIZE_16K) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size "
+                   "%u (0x%x) found\n", __func__, val, val);
+               ecode = HAL_EESIZE;
+               goto bad;
+       }
+       ecode = ath_hal_legacyEepromAttach(ah);
+       if (ecode != HAL_OK) {
+               goto bad;
+       }
+
+        /* If Bmode and AR5211, verify 2.4 analog exists */
+       if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU &&
+           ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) {
+               /* Set correct Baseband to analog shift setting to access analog chips. */
+               OS_REG_WRITE(ah, AR_PHY_BASE, 0x00004007);
+               OS_DELAY(2000);
+               AH_PRIVATE(ah)->ah_analog2GhzRev = ar5211GetRadioRev(ah);
+
+               /* Set baseband for 5GHz chip */
+               OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007);
+               OS_DELAY(2000);
+               if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != RAD2_SREV_MAJOR) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: 2G Radio Chip Rev 0x%x is not supported by "
+                           "this driver\n", __func__,
+                           AH_PRIVATE(ah)->ah_analog2GhzRev);
+                       ecode = HAL_ENOTSUPP;
+                       goto bad;
+               }
+       } else {
+               ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_FALSE);
+        }
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot read regulatory domain from EEPROM\n",
+                   __func__);
+               goto bad;
+        }
+       AH_PRIVATE(ah)->ah_currentRD = eeval;
+       AH_PRIVATE(ah)->ah_getNfAdjust = ar5211GetNfAdjust;
+
+       /*
+        * Got everything we need now to setup the capabilities.
+        */
+       (void) ar5211FillCapabilityInfo(ah);
+
+       /* Initialize gain ladder thermal calibration structure */
+       ar5211InitializeGainValues(ah);
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error getting mac address from EEPROM\n", __func__);
+               goto bad;
+        }
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
+
+       return ah;
+bad:
+       if (ahp)
+               ar5211Detach((struct ath_hal *) ahp);
+       if (status)
+               *status = ecode;
+       return AH_NULL;
+#undef N
+}
+
+void
+ar5211Detach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
+
+       HALASSERT(ah != AH_NULL);
+       HALASSERT(ah->ah_magic == AR5211_MAGIC);
+
+       ath_hal_eepromDetach(ah);
+       ath_hal_free(ah);
+}
+
+static HAL_BOOL
+ar5211ChipTest(struct ath_hal *ah)
+{
+       uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) };
+       uint32_t regHold[2];
+       uint32_t patternData[4] =
+           { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };
+       int i, j;
+
+       /* Test PHY & MAC registers */
+       for (i = 0; i < 2; i++) {
+               uint32_t addr = regAddr[i];
+               uint32_t wrData, rdData;
+
+               regHold[i] = OS_REG_READ(ah, addr);
+               for (j = 0; j < 0x100; j++) {
+                       wrData = (j << 16) | j;
+                       OS_REG_WRITE(ah, addr, wrData);
+                       rdData = OS_REG_READ(ah, addr);
+                       if (rdData != wrData) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+                               __func__, addr, wrData, rdData);
+                               return AH_FALSE;
+                       }
+               }
+               for (j = 0; j < 4; j++) {
+                       wrData = patternData[j];
+                       OS_REG_WRITE(ah, addr, wrData);
+                       rdData = OS_REG_READ(ah, addr);
+                       if (wrData != rdData) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+                                       __func__, addr, wrData, rdData);
+                               return AH_FALSE;
+                       }
+               }
+               OS_REG_WRITE(ah, regAddr[i], regHold[i]);
+       }
+       OS_DELAY(100);
+       return AH_TRUE;
+}
+
+/*
+ * Store the channel edges for the requested operational mode
+ */
+static HAL_BOOL
+ar5211GetChannelEdges(struct ath_hal *ah,
+       uint16_t flags, uint16_t *low, uint16_t *high)
+{
+       if (flags & CHANNEL_5GHZ) {
+               *low = 4920;
+               *high = 6100;
+               return AH_TRUE;
+       }
+       if (flags & CHANNEL_2GHZ && ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) {
+               *low = 2312;
+               *high = 2732;
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+static HAL_BOOL
+ar5211GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans)
+{
+       HAL_CHANNEL *chan;
+       int i;
+
+       /* XXX fill in, this is just a placeholder */
+       for (i = 0; i < nchans; i++) {
+               chan = &chans[i];
+               HALDEBUG(ah, HAL_DEBUG_ATTACH,
+                   "%s: no min/max power for %u/0x%x\n",
+                   __func__, chan->channel, chan->channelFlags);
+               chan->maxTxPower = MAX_RATE_POWER;
+               chan->minTxPower = 0;
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Fill all software cached or static hardware state information.
+ */
+static HAL_BOOL
+ar5211FillCapabilityInfo(struct ath_hal *ah)
+{
+       struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
+       HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
+
+       /* Construct wireless mode from EEPROM */
+       pCap->halWirelessModes = 0;
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
+               pCap->halWirelessModes |= HAL_MODE_11A;
+               if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
+                       pCap->halWirelessModes |= HAL_MODE_TURBO;
+       }
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
+               pCap->halWirelessModes |= HAL_MODE_11B;
+
+       pCap->halLow2GhzChan = 2312;
+       pCap->halHigh2GhzChan = 2732;
+       pCap->halLow5GhzChan = 4920;
+       pCap->halHigh5GhzChan = 6100;
+
+       pCap->halChanSpreadSupport = AH_TRUE;
+       pCap->halSleepAfterBeaconBroken = AH_TRUE;
+       pCap->halPSPollBroken = AH_TRUE;
+       pCap->halVEOLSupport = AH_TRUE;
+
+       pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
+       pCap->halKeyCacheSize = 128;
+
+       /* XXX not needed */
+       pCap->halChanHalfRate = AH_FALSE;
+       pCap->halChanQuarterRate = AH_FALSE;
+
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
+           ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
+               /* NB: enabled by default */
+               ahpriv->ah_rfkillEnabled = AH_TRUE;
+               pCap->halRfSilentSupport = AH_TRUE;
+       }
+
+       pCap->halTstampPrecision = 13;
+
+       /* XXX might be ok w/ some chip revs */
+       ahpriv->ah_rxornIsFatal = AH_TRUE;
+       return AH_TRUE;
+}
+
+static const char*
+ar5211Probe(uint16_t vendorid, uint16_t devid)
+{
+       if (vendorid == ATHEROS_VENDOR_ID) {
+               if (devid == AR5211_DEVID || devid == AR5311_DEVID ||
+                   devid == AR5211_DEFAULT)
+                       return "Atheros 5211";
+               if (devid == AR5211_FPGA11B)
+                       return "Atheros 5211 (FPGA)";
+       }
+       return AH_NULL;
+}
+AH_CHIP(AR5211, ar5211Probe, ar5211Attach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_beacon.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_beacon.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+#include "ar5211/ar5211desc.h"
+
+/*
+ * Routines used to initialize and generated beacons for the AR5211/AR5311.
+ */
+
+/*
+ * Initialize all of the hardware registers used to send beacons.
+ */
+void
+ar5211SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
+{
+
+       OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt);
+       OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba);
+       OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba);
+       OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim);
+       /*
+        * Set the Beacon register after setting all timers.
+        */
+       OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval);
+}
+
+/*
+ * Legacy api to initialize all of the beacon registers.
+ */
+void
+ar5211BeaconInit(struct ath_hal *ah,
+       uint32_t next_beacon, uint32_t beacon_period)
+{
+       HAL_BEACON_TIMERS bt;
+
+       bt.bt_nextdba = 0;
+       bt.bt_nextswba = 0;
+       bt.bt_nexttbtt = next_beacon;
+       /*
+        * TIMER1: in AP/adhoc mode this controls the DMA beacon
+        * alert timer; otherwise it controls the next wakeup time.
+        * TIMER2: in AP mode, it controls the SBA beacon alert
+        * interrupt; otherwise it sets the start of the next CFP.
+        */
+       switch (AH_PRIVATE(ah)->ah_opmode) {
+       case HAL_M_STA:
+       case HAL_M_MONITOR:
+               bt.bt_nextdba = 0xffff;
+               bt.bt_nextswba = 0x7ffff;
+               break;
+       case HAL_M_IBSS:
+       case HAL_M_HOSTAP:
+               bt.bt_nextdba = (next_beacon -
+                       ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */
+               bt.bt_nextswba = (next_beacon -
+                       ath_hal_sw_beacon_response_time) << 3;  /* 1/8 TU */
+               break;
+       }
+       /*
+        * Set the ATIM window
+        * Our hardware does not support an ATIM window of 0
+        * (beacons will not work).  If the ATIM windows is 0,
+        * force it to 1.
+        */
+       bt.bt_nextatim = next_beacon + 1;
+       bt.bt_intval = beacon_period &
+               (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
+       ar5211SetBeaconTimers(ah, &bt);
+}
+
+void
+ar5211ResetStaBeaconTimers(struct ath_hal *ah)
+{
+       uint32_t val;
+
+       OS_REG_WRITE(ah, AR_TIMER0, 0);         /* no beacons */
+       val = OS_REG_READ(ah, AR_STA_ID1);
+       val |= AR_STA_ID1_PWR_SAV;              /* XXX */
+       /* tell the h/w that the associated AP is not PCF capable */
+       OS_REG_WRITE(ah, AR_STA_ID1,
+               val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF));
+       OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD);
+}
+
+/*
+ * Set all the beacon related bits on the h/w for stations
+ * i.e. initializes the corresponding h/w timers;
+ * also tells the h/w whether to anticipate PCF beacons
+ */
+void
+ar5211SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__);
+
+       HALASSERT(bs->bs_intval != 0);
+       /* if the AP will do PCF */
+       if (bs->bs_cfpmaxduration != 0) {
+               /* tell the h/w that the associated AP is PCF capable */
+               OS_REG_WRITE(ah, AR_STA_ID1,
+                       OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF);
+
+               /* set CFP_PERIOD(1.024ms) register */
+               OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod);
+
+               /* set CFP_DUR(1.024ms) register to max cfp duration */
+               OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration);
+
+               /* set TIMER2(128us) to anticipated time of next CFP */
+               OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3);
+       } else {
+               /* tell the h/w that the associated AP is not PCF capable */
+               OS_REG_WRITE(ah, AR_STA_ID1,
+                       OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF);
+       }
+
+       /*
+        * Set TIMER0(1.024ms) to the anticipated time of the next beacon.
+        */
+       OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt);
+
+       /*
+        * Start the beacon timers by setting the BEACON register
+        * to the beacon interval; also write the tim offset which
+        * we should know by now.  The code, in ar5211WriteAssocid,
+        * also sets the tim offset once the AID is known which can
+        * be left as such for now.
+        */
+       OS_REG_WRITE(ah, AR_BEACON,
+               (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM))
+               | SM(bs->bs_intval, AR_BEACON_PERIOD)
+               | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM)
+       );
+
+       /*
+        * Configure the BMISS interrupt.  Note that we
+        * assume the caller blocks interrupts while enabling
+        * the threshold.
+        */
+       HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR));
+       ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR)
+                       | SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR);
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+
+       /*
+        * Set the sleep duration in 1/8 TU's.
+        */
+#define        SLEEP_SLOP      3
+       OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLDUR,
+               (bs->bs_sleepduration - SLEEP_SLOP) << 3);
+#undef SLEEP_SLOP
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_interrupts.c        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_interrupts.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+
+/*
+ * Checks to see if an interrupt is pending on our NIC
+ *
+ * Returns: TRUE    if an interrupt is pending
+ *          FALSE   if not
+ */
+HAL_BOOL
+ar5211IsInterruptPending(struct ath_hal *ah)
+{
+       return OS_REG_READ(ah, AR_INTPEND) != 0;
+}
+
+/*
+ * Reads the Interrupt Status Register value from the NIC, thus deasserting
+ * the interrupt line, and returns both the masked and unmasked mapped ISR
+ * values.  The value returned is mapped to abstract the hw-specific bit
+ * locations in the Interrupt Status Register.
+ *
+ * Returns: A hardware-abstracted bitmap of all non-masked-out
+ *          interrupts pending, as well as an unmasked value
+ */
+HAL_BOOL
+ar5211GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)
+{
+       uint32_t isr;
+
+       isr = OS_REG_READ(ah, AR_ISR_RAC);
+       if (isr == 0xffffffff) {
+               *masked = 0;
+               return AH_FALSE;
+       }
+
+       *masked = isr & HAL_INT_COMMON;
+
+       if (isr & AR_ISR_HIUERR)
+               *masked |= HAL_INT_FATAL;
+       if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+               *masked |= HAL_INT_RX;
+       if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL))
+               *masked |= HAL_INT_TX;
+       /*
+        * Receive overrun is usually non-fatal on Oahu/Spirit.
+        * BUT on some parts rx could fail and the chip must be reset.
+        * So we force a hardware reset in all cases.
+        */
+       if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: receive FIFO overrun interrupt\n", __func__);
+               *masked |= HAL_INT_FATAL;
+       }
+
+       /*
+        * On fatal errors collect ISR state for debugging.
+        */
+       if (*masked & HAL_INT_FATAL) {
+               AH_PRIVATE(ah)->ah_fatalState[0] = isr;
+               AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S);
+               AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S);
+               AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S);
+               AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S);
+               AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S);
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n",
+                   __func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]);
+       }
+       return AH_TRUE;
+}
+
+HAL_INT
+ar5211GetInterrupts(struct ath_hal *ah)
+{
+       return AH5211(ah)->ah_maskReg;
+}
+
+/*
+ * Atomically enables NIC interrupts.  Interrupts are passed in
+ * via the enumerated bitmask in ints.
+ */
+HAL_INT
+ar5211SetInterrupts(struct ath_hal *ah, HAL_INT ints)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       uint32_t omask = ahp->ah_maskReg;
+       uint32_t mask;
+
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",
+           __func__, omask, ints);
+
+       /*
+        * Disable interrupts here before reading & modifying
+        * the mask so that the ISR does not modify the mask
+        * out from under us.
+        */
+       if (omask & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+               /* XXX??? */
+               (void) OS_REG_READ(ah, AR_IER); /* flush write to HW */
+       }
+
+       mask = ints & HAL_INT_COMMON;
+       if (ints & HAL_INT_TX) {
+               if (ahp->ah_txOkInterruptMask)
+                       mask |= AR_IMR_TXOK;
+               if (ahp->ah_txErrInterruptMask)
+                       mask |= AR_IMR_TXERR;
+               if (ahp->ah_txDescInterruptMask)
+                       mask |= AR_IMR_TXDESC;
+               if (ahp->ah_txEolInterruptMask)
+                       mask |= AR_IMR_TXEOL;
+       }
+       if (ints & HAL_INT_RX)
+               mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC;
+       if (ints & HAL_INT_FATAL) {
+               /*
+                * NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2
+                *     so enabling HIUERR enables delivery.
+                */
+               mask |= AR_IMR_HIUERR;
+       }
+
+       /* Write the new IMR and store off our SW copy. */
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
+       OS_REG_WRITE(ah, AR_IMR, mask);
+       ahp->ah_maskReg = ints;
+
+       /* Re-enable interrupts as appropriate. */
+       if (ints & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+       }
+
+       return omask;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_keycache.c  2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_keycache.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+
+/*
+ *  Chips-specific key cache routines.
+ */
+
+#define        AR_KEYTABLE_SIZE        128
+#define        KEY_XOR                 0xaa
+
+/*
+ * Return the size of the hardware key cache.
+ */
+uint32_t
+ar5211GetKeyCacheSize(struct ath_hal *ah)
+{
+       return AR_KEYTABLE_SIZE;
+}
+
+/*
+ * Return true if the specific key cache entry is valid.
+ */
+HAL_BOOL
+ar5211IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry)
+{
+       if (entry < AR_KEYTABLE_SIZE) {
+               uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
+               if (val & AR_KEYTABLE_VALID)
+                       return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Clear the specified key cache entry
+ */
+HAL_BOOL
+ar5211ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
+{
+       if (entry < AR_KEYTABLE_SIZE) {
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Sets the mac part of the specified key cache entry and mark it valid.
+ */
+HAL_BOOL
+ar5211SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac)
+{
+       uint32_t macHi, macLo;
+
+       if (entry >= AR_KEYTABLE_SIZE) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n",
+                   __func__, entry);
+               return AH_FALSE;
+       }
+
+       /*
+        * Set MAC address -- shifted right by 1.  MacLo is
+        * the 4 MSBs, and MacHi is the 2 LSBs.
+        */
+       if (mac != AH_NULL) {
+               macHi = (mac[5] << 8) | mac[4];
+               macLo = (mac[3] << 24)| (mac[2] << 16)
+                     | (mac[1] << 8) | mac[0];
+               macLo >>= 1;
+               macLo |= (macHi & 1) << 31;     /* carry */
+               macHi >>= 1;
+       } else {
+               macLo = macHi = 0;
+       }
+
+       OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+       OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
+       return AH_TRUE;
+}
+
+/*
+ * Sets the contents of the specified key cache entry.
+ */
+HAL_BOOL
+ar5211SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
+                       const HAL_KEYVAL *k, const uint8_t *mac,
+                       int xorKey)
+{
+       uint32_t key0, key1, key2, key3, key4;
+       uint32_t keyType;
+       uint32_t xorMask= xorKey ?
+               (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
+
+       if (entry >= AR_KEYTABLE_SIZE) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n",
+                   __func__, entry);
+               return AH_FALSE;
+       }
+       switch (k->kv_type) {
+       case HAL_CIPHER_AES_OCB:
+               keyType = AR_KEYTABLE_TYPE_AES;
+               break;
+       case HAL_CIPHER_WEP:
+               if (k->kv_len < 40 / NBBY) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: WEP key length %u too small\n",
+                           __func__, k->kv_len);
+                       return AH_FALSE;
+               }
+               if (k->kv_len <= 40 / NBBY)
+                       keyType = AR_KEYTABLE_TYPE_40;
+               else if (k->kv_len <= 104 / NBBY)
+                       keyType = AR_KEYTABLE_TYPE_104;
+               else
+                       keyType = AR_KEYTABLE_TYPE_128;
+               break;
+       case HAL_CIPHER_CLR:
+               keyType = AR_KEYTABLE_TYPE_CLR;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n",
+                       __func__, k->kv_type);
+               return AH_FALSE;
+       }
+
+       key0 = LE_READ_4(k->kv_val+0) ^ xorMask;
+       key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff;
+       key2 = LE_READ_4(k->kv_val+6) ^ xorMask;
+       key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff;
+       key4 = LE_READ_4(k->kv_val+12) ^ xorMask;
+       if (k->kv_len <= 104 / NBBY)
+               key4 &= 0xff;
+
+
+       /*
+        * Note: WEP key cache hardware requires that each double-word
+        * pair be written in even/odd order (since the destination is
+        * a 64-bit register).  Don't reorder these writes w/o
+        * understanding this!
+        */
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+       OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+       return ar5211SetKeyCacheEntryMac(ah, entry, mac);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_misc.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_misc.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+#include "ar5211/ar5211phy.h"
+
+#include "ah_eeprom_v3.h"
+
+#define        AR_NUM_GPIO     6               /* 6 GPIO bits */
+#define        AR_GPIOD_MASK   0x2f            /* 6-bit mask */
+
+void
+ar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
+}
+
+HAL_BOOL
+ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
+       return AH_TRUE;
+}
+
+void
+ar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
+{
+       static const uint8_t ones[IEEE80211_ADDR_LEN] =
+               { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+       OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN);
+}
+
+HAL_BOOL
+ar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
+{
+       return AH_FALSE;
+}
+
+/*
+ * Read 16 bits of data from the specified EEPROM offset.
+ */
+HAL_BOOL
+ar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
+{
+       OS_REG_WRITE(ah, AR_EEPROM_ADDR, off);
+       OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ);
+
+       if (!ath_hal_wait(ah, AR_EEPROM_STS,
+           AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR,
+           AR_EEPROM_STS_READ_COMPLETE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: read failed for entry 0x%x\n", __func__, off);
+               return AH_FALSE;
+       }
+       *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff;
+       return AH_TRUE;
+}
+
+#ifdef AH_SUPPORT_WRITE_EEPROM
+/*
+ * Write 16 bits of data to the specified EEPROM offset.
+ */
+HAL_BOOL
+ar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
+{
+       return AH_FALSE;
+}
+#endif /* AH_SUPPORT_WRITE_EEPROM */
+
+/*
+ * Attempt to change the cards operating regulatory domain to the given value
+ */
+HAL_BOOL
+ar5211SetRegulatoryDomain(struct ath_hal *ah,
+       uint16_t regDomain, HAL_STATUS *status)
+{
+       HAL_STATUS ecode;
+
+       if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
+               ecode = HAL_EINVAL;
+               goto bad;
+       }
+       /*
+        * Check if EEPROM is configured to allow this; must
+        * be a proper version and the protection bits must
+        * permit re-writing that segment of the EEPROM.
+        */
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
+               ecode = HAL_EEWRITE;
+               goto bad;
+       }
+#ifdef AH_SUPPORT_WRITE_REGDOMAIN
+       if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: set regulatory domain to %u (0x%x)\n",
+                   __func__, regDomain, regDomain);
+               AH_PRIVATE(ah)->ah_currentRD = regDomain;
+               return AH_TRUE;
+       }
+#endif
+       ecode = HAL_EIO;
+bad:
+       if (status)
+               *status = ecode;
+       return AH_FALSE;
+}
+
+/*
+ * Return the wireless modes (a,b,g,t) supported by hardware.
+ *
+ * This value is what is actually supported by the hardware
+ * and is unaffected by regulatory/country code settings.
+ *
+ */
+u_int
+ar5211GetWirelessModes(struct ath_hal *ah)
+{
+       u_int mode = 0;
+
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
+               mode = HAL_MODE_11A;
+               if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
+                       mode |= HAL_MODE_TURBO | HAL_MODE_108A;
+       }
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
+               mode |= HAL_MODE_11B;
+       return mode;
+}
+
+#if 0
+HAL_BOOL
+ar5211GetTurboDisable(struct ath_hal *ah)
+{
+       return (AH5211(ah)->ah_turboDisable != 0);
+}
+#endif
+
+/*
+ * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
+ * GPIO values so the ISR and can disable RF on a switch signal
+ */
+void
+ar5211EnableRfKill(struct ath_hal *ah)
+{
+       uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
+       int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
+       int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
+
+       /*
+        * Configure the desired GPIO port for input
+        * and enable baseband rf silence.
+        */
+       ar5211GpioCfgInput(ah, select);
+       OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000);
+       /*
+        * If radio disable switch connection to GPIO bit x is enabled
+        * program GPIO interrupt.
+        * If rfkill bit on eeprom is 1, setupeeprommap routine has already
+        * verified that it is a later version of eeprom, it has a place for
+        * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
+        * connection is present.
+        */
+       ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity));
+}
+
+/*
+ * Configure GPIO Output lines
+ */
+HAL_BOOL
+ar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio)
+{
+       uint32_t reg;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       reg =  OS_REG_READ(ah, AR_GPIOCR);
+       reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT));
+       reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT);
+
+       OS_REG_WRITE(ah, AR_GPIOCR, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Configure GPIO Input lines
+ */
+HAL_BOOL
+ar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
+{
+       uint32_t reg;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       reg =  OS_REG_READ(ah, AR_GPIOCR);
+       reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT));
+       reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT);
+
+       OS_REG_WRITE(ah, AR_GPIOCR, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - set output lines
+ */
+HAL_BOOL
+ar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
+{
+       uint32_t reg;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       reg =  OS_REG_READ(ah, AR_GPIODO);
+       reg &= ~(1 << gpio);
+       reg |= (val&1) << gpio;
+
+       OS_REG_WRITE(ah, AR_GPIODO, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - get input lines
+ */
+uint32_t
+ar5211GpioGet(struct ath_hal *ah, uint32_t gpio)
+{
+       if (gpio < AR_NUM_GPIO) {
+               uint32_t val = OS_REG_READ(ah, AR_GPIODI);
+               val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
+               return val;
+       } else  {
+               return 0xffffffff;
+       }
+}
+
+/*
+ * Set the GPIO 0 Interrupt (gpio is ignored)
+ */
+void
+ar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
+{
+       uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
+
+       /* Clear the bits that we will modify. */
+       val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
+                       AR_GPIOCR_0_CR_A);
+
+       val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA;
+       if (ilevel)
+               val |= AR_GPIOCR_INT_SELH;
+
+       /* Don't need to change anything for low level interrupt. */
+       OS_REG_WRITE(ah, AR_GPIOCR, val);
+
+       /* Change the interrupt mask. */
+       ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO);
+}
+
+/*
+ * Change the LED blinking pattern to correspond to the connectivity
+ */
+void
+ar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
+{
+       static const uint32_t ledbits[8] = {
+               AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */
+               AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */
+               AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */
+               AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/
+               AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */
+               AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
+               AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
+               AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,
+       };
+       OS_REG_WRITE(ah, AR_PCICFG,
+               (OS_REG_READ(ah, AR_PCICFG) &~
+                       (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE))
+               | ledbits[state & 0x7]
+       );
+}
+
+/*
+ * Change association related fields programmed into the hardware.
+ * Writing a valid BSSID to the hardware effectively enables the hardware
+ * to synchronize its TSF to the correct beacons and receive frames coming
+ * from that BSSID. It is called by the SME JOIN operation.
+ */
+void
+ar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       /* XXX save bssid for possible re-use on reset */
+       OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
+                                    ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
+}
+
+/*
+ * Get the current hardware tsf for stamlme.
+ */
+uint64_t
+ar5211GetTsf64(struct ath_hal *ah)
+{
+       uint32_t low1, low2, u32;
+
+       /* sync multi-word read */
+       low1 = OS_REG_READ(ah, AR_TSF_L32);
+       u32 = OS_REG_READ(ah, AR_TSF_U32);
+       low2 = OS_REG_READ(ah, AR_TSF_L32);
+       if (low2 < low1) {      /* roll over */
+               /*
+                * If we are not preempted this will work.  If we are
+                * then we re-reading AR_TSF_U32 does no good as the
+                * low bits will be meaningless.  Likewise reading
+                * L32, U32, U32, then comparing the last two reads
+                * to check for rollover doesn't help if preempted--so
+                * we take this approach as it costs one less PCI
+                * read which can be noticeable when doing things
+                * like timestamping packets in monitor mode.
+                */
+               u32++;
+       }
+       return (((uint64_t) u32) << 32) | ((uint64_t) low2);
+}
+
+/*
+ * Get the current hardware tsf for stamlme.
+ */
+uint32_t
+ar5211GetTsf32(struct ath_hal *ah)
+{
+       return OS_REG_READ(ah, AR_TSF_L32);
+}
+
+/*
+ * Reset the current hardware tsf for stamlme
+ */
+void
+ar5211ResetTsf(struct ath_hal *ah)
+{
+       uint32_t val = OS_REG_READ(ah, AR_BEACON);
+
+       OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
+}
+
+/*
+ * Grab a semi-random value from hardware registers - may not
+ * change often
+ */
+uint32_t
+ar5211GetRandomSeed(struct ath_hal *ah)
+{
+       uint32_t nf;
+
+       nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
+       if (nf & 0x100)
+               nf = 0 - ((nf ^ 0x1ff) + 1);
+       return (OS_REG_READ(ah, AR_TSF_U32) ^
+               OS_REG_READ(ah, AR_TSF_L32) ^ nf);
+}
+
+/*
+ * Detect if our card is present
+ */
+HAL_BOOL
+ar5211DetectCardPresent(struct ath_hal *ah)
+{
+       uint16_t macVersion, macRev;
+       uint32_t v;
+
+       /*
+        * Read the Silicon Revision register and compare that
+        * to what we read at attach time.  If the same, we say
+        * a card/device is present.
+        */
+       v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M;
+       macVersion = v >> AR_SREV_ID_S;
+       macRev = v & AR_SREV_REVISION_M;
+       return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
+               AH_PRIVATE(ah)->ah_macRev == macRev);
+}
+
+/*
+ * Update MIB Counters
+ */
+void
+ar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
+{
+       stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
+       stats->rts_bad    += OS_REG_READ(ah, AR_RTS_FAIL);
+       stats->fcs_bad    += OS_REG_READ(ah, AR_FCS_FAIL);
+       stats->rts_good   += OS_REG_READ(ah, AR_RTS_OK);
+       stats->beacons    += OS_REG_READ(ah, AR_BEACON_CNT);
+}
+
+HAL_BOOL
+ar5211SetSifsTime(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       if (us > ath_hal_mac_usec(ah, 0xffff)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
+                   __func__, us);
+               ahp->ah_sifstime = (u_int) -1;  /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us));
+               ahp->ah_slottime = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5211GetSifsTime(struct ath_hal *ah)
+{
+       u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+HAL_BOOL
+ar5211SetSlotTime(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
+                   __func__, us);
+               ahp->ah_slottime = us;  /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
+               ahp->ah_slottime = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5211GetSlotTime(struct ath_hal *ah)
+{
+       u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+HAL_BOOL
+ar5211SetAckTimeout(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
+                   __func__, us);
+               ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
+                       AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
+               ahp->ah_acktimeout = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5211GetAckTimeout(struct ath_hal *ah)
+{
+       u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+u_int
+ar5211GetAckCTSRate(struct ath_hal *ah)
+{
+       return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
+}
+
+HAL_BOOL
+ar5211SetAckCTSRate(struct ath_hal *ah, u_int high)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       if (high) {
+               OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
+               ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
+       } else {
+               OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
+               ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5211SetCTSTimeout(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
+                   __func__, us);
+               ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
+                       AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
+               ahp->ah_ctstimeout = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5211GetCTSTimeout(struct ath_hal *ah)
+{
+       u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+HAL_BOOL
+ar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
+{
+       /* nothing to do */
+        return AH_TRUE;
+}
+
+void
+ar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
+{
+}
+
+/*
+ * Control Adaptive Noise Immunity Parameters
+ */
+HAL_BOOL
+ar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
+{
+       return AH_FALSE;
+}
+
+void
+ar5211AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, HAL_CHANNEL *chan)
+{
+}
+
+void
+ar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
+{
+}
+
+/*
+ * Get the rssi of frame curently being received.
+ */
+uint32_t
+ar5211GetCurRssi(struct ath_hal *ah)
+{
+       return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
+}
+
+u_int
+ar5211GetDefAntenna(struct ath_hal *ah)
+{
+       return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
+}
+
+void
+ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna)
+{
+       OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
+}
+
+HAL_ANT_SETTING
+ar5211GetAntennaSwitch(struct ath_hal *ah)
+{
+       return AH5211(ah)->ah_diversityControl;
+}
+
+HAL_BOOL
+ar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
+{
+       const HAL_CHANNEL *chan =
+               (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
+
+       if (chan == AH_NULL) {
+               AH5211(ah)->ah_diversityControl = settings;
+               return AH_TRUE;
+       }
+       return ar5211SetAntennaSwitchInternal(ah, settings, chan);
+}
+
+HAL_STATUS
+ar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+       uint32_t capability, uint32_t *result)
+{
+
+       switch (type) {
+       case HAL_CAP_CIPHER:            /* cipher handled in hardware */
+               switch (capability) {
+               case HAL_CIPHER_AES_OCB:
+               case HAL_CIPHER_WEP:
+               case HAL_CIPHER_CLR:
+                       return HAL_OK;
+               default:
+                       return HAL_ENOTSUPP;
+               }
+       default:
+               return ath_hal_getcapability(ah, type, capability, result);
+       }
+}
+
+HAL_BOOL
+ar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+       uint32_t capability, uint32_t setting, HAL_STATUS *status)
+{
+       switch (type) {
+       case HAL_CAP_DIAG:              /* hardware diagnostic support */
+               /*
+                * NB: could split this up into virtual capabilities,
+                *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
+                *     seems worth the additional complexity.
+                */
+#ifdef AH_DEBUG
+               AH_PRIVATE(ah)->ah_diagreg = setting;
+#else
+               AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;     /* ACK+CTS */
+#endif
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+               return AH_TRUE;
+       default:
+               return ath_hal_setcapability(ah, type, capability,
+                       setting, status);
+       }
+}
+
+HAL_BOOL
+ar5211GetDiagState(struct ath_hal *ah, int request,
+       const void *args, uint32_t argsize,
+       void **result, uint32_t *resultsize)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       (void) ahp;
+       if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
+               return AH_TRUE;
+       switch (request) {
+       case HAL_DIAG_EEPROM:
+               return ath_hal_eepromDiag(ah, request,
+                   args, argsize, result, resultsize);
+       case HAL_DIAG_RFGAIN:
+               *result = &ahp->ah_gainValues;
+               *resultsize = sizeof(GAIN_VALUES);
+               return AH_TRUE;
+       case HAL_DIAG_RFGAIN_CURSTEP:
+               *result = __DECONST(void *, ahp->ah_gainValues.currStep);
+               *resultsize = (*result == AH_NULL) ?
+                       0 : sizeof(GAIN_OPTIMIZATION_STEP);
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_phy.c       2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_phy.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5211/ar5211.h"
+
+/* shorthands to compact tables for readability */
+#define        OFDM    IEEE80211_T_OFDM
+#define        CCK     IEEE80211_T_CCK
+#define        TURBO   IEEE80211_T_TURBO
+
+HAL_RATE_TABLE ar5211_11a_table = {
+       8,  /* number of rates */
+       { 0 },
+       {
+/*                                                  short            ctrl  */
+/*                valid                 rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, OFDM,    6000,     0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, OFDM,    9000,     0x0f,    0x00,        18,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,   12000,     0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,   18000,     0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   24000,     0x09,    0x00, (0x80|48),   4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   36000,     0x0d,    0x00,        72,   4, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   48000,     0x08,    0x00,        96,   4, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   54000,     0x0c,    0x00,       108,   4, 0, 0 }
+       },
+};
+
+HAL_RATE_TABLE ar5211_turbo_table = {
+       8,  /* number of rates */
+       { 0 },
+       {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, TURBO,   6000,    0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, TURBO,   9000,    0x0f,    0x00,        18,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, TURBO,  12000,    0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, TURBO,  18000,    0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, TURBO,  24000,    0x09,    0x00, (0x80|48),   4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, TURBO,  36000,    0x0d,    0x00,        72,   4, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, TURBO,  48000,    0x08,    0x00,        96,   4, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, TURBO,  54000,    0x0c,    0x00,       108,   4, 0, 0 }
+       },
+};
+
+HAL_RATE_TABLE ar5211_11b_table = {
+       4,  /* number of rates */
+       { 0 },
+       {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   1 Mb */ {  AH_TRUE,  CCK,    1000,    0x0b,    0x00, (0x80| 2),   0, 0, 0 },
+/*   2 Mb */ {  AH_TRUE,  CCK,    2000,    0x0a,    0x04, (0x80| 4),   1, 0, 0 },
+/* 5.5 Mb */ {  AH_TRUE,  CCK,    5500,    0x09,    0x04, (0x80|11),   1, 0, 0 },
+/*  11 Mb */ {  AH_TRUE,  CCK,   11000,    0x08,    0x04, (0x80|22),   1, 0, 0 }
+       },
+};
+
+#undef OFDM
+#undef CCK
+#undef TURBO
+
+
+const HAL_RATE_TABLE *
+ar5211GetRateTable(struct ath_hal *ah, u_int mode)
+{
+       HAL_RATE_TABLE *rt;
+       switch (mode) {
+       case HAL_MODE_11A:
+               rt = &ar5211_11a_table;
+               break;
+       case HAL_MODE_11B:
+               rt = &ar5211_11b_table;
+               break;
+       case HAL_MODE_TURBO:
+               rt =  &ar5211_turbo_table;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
+                   __func__, mode);
+               return AH_NULL;
+       }
+       ath_hal_setupratetable(ah, rt);
+       return rt;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_power.c     2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_power.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+#include "ar5211/ar5211desc.h"
+
+/*
+ * Notify Power Mgt is enabled in self-generated frames.
+ * If requested, force chip awake.
+ *
+ * Returns A_OK if chip is awake or successfully forced awake.
+ *
+ * WARNING WARNING WARNING
+ * There is a problem with the chip where sometimes it will not wake up.
+ */
+static HAL_BOOL
+ar5211SetPowerModeAwake(struct ath_hal *ah, int setChip)
+{
+#define        POWER_UP_TIME   2000
+       uint32_t val;
+       int i;
+
+       if (setChip) {
+               OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_WAKE);
+               OS_DELAY(10);   /* Give chip the chance to awake */
+
+               for (i = POWER_UP_TIME / 200; i != 0; i--) {
+                       val = OS_REG_READ(ah, AR_PCICFG);
+                       if ((val & AR_PCICFG_SPWR_DN) == 0)
+                               break;
+                       OS_DELAY(200);
+                       OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE,
+                               AR_SCR_SLE_WAKE);
+               }
+               if (i == 0) {
+#ifdef AH_DEBUG
+                       ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n",
+                               __func__, POWER_UP_TIME/20);
+#endif
+                       return AH_FALSE;
+               }
+       }
+
+       OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       return AH_TRUE;
+#undef POWER_UP_TIME
+}
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
+static void
+ar5211SetPowerModeSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       if (setChip)
+               OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP);
+}
+
+/*
+ * Notify Power Management is enabled in self-generating
+ * fames.  If request, set power mode of chip to
+ * auto/normal.  Duration in units of 128us (1/8 TU).
+ */
+static void
+ar5211SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       if (setChip)
+               OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_NORM);
+}
+
+HAL_BOOL
+ar5211SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+#ifdef AH_DEBUG
+       static const char* modes[] = {
+               "AWAKE",
+               "FULL-SLEEP",
+               "NETWORK SLEEP",
+               "UNDEFINED"
+       };
+#endif
+       int status = AH_TRUE;
+
+       HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
+               modes[ahp->ah_powerMode], modes[mode],
+               setChip ? "set chip " : "");
+       switch (mode) {
+       case HAL_PM_AWAKE:
+               status = ar5211SetPowerModeAwake(ah, setChip);
+               break;
+       case HAL_PM_FULL_SLEEP:
+               ar5211SetPowerModeSleep(ah, setChip);
+               break;
+       case HAL_PM_NETWORK_SLEEP:
+               ar5211SetPowerModeNetworkSleep(ah, setChip);
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n",
+                   __func__, mode);
+               return AH_FALSE;
+       }
+       ahp->ah_powerMode = mode;
+       return status;
+}
+
+HAL_POWER_MODE
+ar5211GetPowerMode(struct ath_hal *ah)
+{
+       /* Just so happens the h/w maps directly to the abstracted value */
+       return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_recv.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_recv.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+#include "ar5211/ar5211desc.h"
+
+/*
+ * Get the RXDP.
+ */
+uint32_t
+ar5211GetRxDP(struct ath_hal *ah)
+{
+       return OS_REG_READ(ah, AR_RXDP);
+}
+
+/*
+ * Set the RxDP.
+ */
+void
+ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp)
+{
+       OS_REG_WRITE(ah, AR_RXDP, rxdp);
+       HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp);
+}
+
+
+/*
+ * Set Receive Enable bits.
+ */
+void
+ar5211EnableReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+/*
+ * Stop Receive at the DMA engine
+ */
+HAL_BOOL
+ar5211StopDmaReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);     /* Set receive disable bit */
+       if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s failed to stop in 10ms\n"
+                                  "AR_CR=0x%08X\nAR_DIAG_SW=0x%08X\n"
+                                  , __func__
+                                  , OS_REG_READ(ah, AR_CR)
+                                  , OS_REG_READ(ah, AR_DIAG_SW)
+               );
+#endif
+               return AH_FALSE;
+       } else {
+               return AH_TRUE;
+       }
+}
+
+/*
+ * Start Transmit at the PCU engine (unpause receive)
+ */
+void
+ar5211StartPcuReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_DIAG_SW,
+               OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX));
+}
+
+/*
+ * Stop Transmit at the PCU engine (pause receive)
+ */
+void
+ar5211StopPcuReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_DIAG_SW,
+               OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX);
+}
+
+/*
+ * Set multicast filter 0 (lower 32-bits)
+ *                        filter 1 (upper 32-bits)
+ */
+void
+ar5211SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1)
+{
+       OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+       OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);
+}
+
+/*
+ * Clear multicast filter by index
+ */
+HAL_BOOL
+ar5211ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
+{
+       uint32_t val;
+
+       if (ix >= 64)
+               return AH_FALSE;
+       if (ix >= 32) {
+               val = OS_REG_READ(ah, AR_MCAST_FIL1);
+               OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32))));
+       } else {
+               val = OS_REG_READ(ah, AR_MCAST_FIL0);
+               OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<<ix)));
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Set multicast filter by index
+ */
+HAL_BOOL
+ar5211SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
+{
+       uint32_t val;
+
+       if (ix >= 64)
+               return AH_FALSE;
+       if (ix >= 32) {
+               val = OS_REG_READ(ah, AR_MCAST_FIL1);
+               OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32))));
+       } else {
+               val = OS_REG_READ(ah, AR_MCAST_FIL0);
+               OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<<ix)));
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Get receive filter.
+ */
+uint32_t
+ar5211GetRxFilter(struct ath_hal *ah)
+{
+       return OS_REG_READ(ah, AR_RX_FILTER);
+}
+
+/*
+ * Set receive filter.
+ */
+void
+ar5211SetRxFilter(struct ath_hal *ah, uint32_t bits)
+{
+       OS_REG_WRITE(ah, AR_RX_FILTER, bits);
+}
+
+/*
+ * Initialize RX descriptor, by clearing the status and clearing
+ * the size.  This is not strictly HW dependent, but we want the
+ * control and status words to be opaque above the hal.
+ */
+HAL_BOOL
+ar5211SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       uint32_t size, u_int flags)
+{
+       struct ar5211_desc *ads = AR5211DESC(ds);
+
+       ads->ds_ctl0 = 0;
+       ads->ds_ctl1 = size & AR_BufLen;
+       if (ads->ds_ctl1 != size) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n",
+                   __func__, size);
+               return AH_FALSE;
+       }
+       if (flags & HAL_RXDESC_INTREQ)
+               ads->ds_ctl1 |= AR_RxInterReq;
+       ads->ds_status0 = ads->ds_status1 = 0;
+
+       return AH_TRUE;
+}
+
+/*
+ * Process an RX descriptor, and return the status to the caller.
+ * Copy some hardware specific items into the software portion
+ * of the descriptor.
+ *
+ * NB: the caller is responsible for validating the memory contents
+ *     of the descriptor (e.g. flushing any cached copy).
+ */
+HAL_STATUS
+ar5211ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       uint32_t pa, struct ath_desc *nds, uint64_t tsf,
+       struct ath_rx_status *rs)
+{
+       struct ar5211_desc *ads = AR5211DESC(ds);
+       struct ar5211_desc *ands = AR5211DESC(nds);
+
+       if ((ads->ds_status1 & AR_Done) == 0)
+               return HAL_EINPROGRESS;
+       /*
+        * Given the use of a self-linked tail be very sure that the hw is
+        * done with this descriptor; the hw may have done this descriptor
+        * once and picked it up again...make sure the hw has moved on.
+        */
+       if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa)
+               return HAL_EINPROGRESS;
+
+       rs->rs_datalen = ads->ds_status0 & AR_DataLen;
+       rs->rs_tstamp = MS(ads->ds_status1, AR_RcvTimestamp);
+       rs->rs_status = 0;
+       if ((ads->ds_status1 & AR_FrmRcvOK) == 0) {
+               if (ads->ds_status1 & AR_CRCErr)
+                       rs->rs_status |= HAL_RXERR_CRC;
+               else if (ads->ds_status1 & AR_DecryptCRCErr)
+                       rs->rs_status |= HAL_RXERR_DECRYPT;
+               else {
+                       rs->rs_status |= HAL_RXERR_PHY;
+                       rs->rs_phyerr = MS(ads->ds_status1, AR_PHYErr);
+               }
+       }
+       /* XXX what about KeyCacheMiss? */
+       rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength);
+       if (ads->ds_status1 & AR_KeyIdxValid)
+               rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx);
+       else
+               rs->rs_keyix = HAL_RXKEYIX_INVALID;
+       /* NB: caller expected to do rate table mapping */
+       rs->rs_rate = MS(ads->ds_status0, AR_RcvRate);
+       rs->rs_antenna  = MS(ads->ds_status0, AR_RcvAntenna);
+       rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0;
+
+       return HAL_OK;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_reset.c     2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,2140 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_reset.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+/*
+ * Chips specific device attachment and device info collection
+ * Connects Init Reg Vectors, EEPROM Data, and device Functions.
+ */
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+#include "ar5211/ar5211phy.h"
+
+#include "ah_eeprom_v3.h"
+
+/* Add static register initialization vectors */
+#include "ar5211/boss.ini"
+
+/*
+ * Structure to hold 11b tuning information for Beanie/Sombrero
+ * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12
+ */
+typedef struct {
+       uint32_t        refClkSel;      /* reference clock, 1 for 16 MHz */
+       uint32_t        channelSelect;  /* P[7:4]S[3:0] bits */
+       uint16_t        channel5111;    /* 11a channel for 5111 */
+} CHAN_INFO_2GHZ;
+
+#define CI_2GHZ_INDEX_CORRECTION 19
+static const CHAN_INFO_2GHZ chan2GHzData[] = {
+       { 1, 0x46, 96  },       /* 2312 -19 */
+       { 1, 0x46, 97  },       /* 2317 -18 */
+       { 1, 0x46, 98  },       /* 2322 -17 */
+       { 1, 0x46, 99  },       /* 2327 -16 */
+       { 1, 0x46, 100 },       /* 2332 -15 */
+       { 1, 0x46, 101 },       /* 2337 -14 */
+       { 1, 0x46, 102 },       /* 2342 -13 */
+       { 1, 0x46, 103 },       /* 2347 -12 */
+       { 1, 0x46, 104 },       /* 2352 -11 */
+       { 1, 0x46, 105 },       /* 2357 -10 */
+       { 1, 0x46, 106 },       /* 2362  -9 */
+       { 1, 0x46, 107 },       /* 2367  -8 */
+       { 1, 0x46, 108 },       /* 2372  -7 */
+       /* index -6 to 0 are pad to make this a nolookup table */
+       { 1, 0x46, 116 },       /*       -6 */
+       { 1, 0x46, 116 },       /*       -5 */
+       { 1, 0x46, 116 },       /*       -4 */
+       { 1, 0x46, 116 },       /*       -3 */
+       { 1, 0x46, 116 },       /*       -2 */
+       { 1, 0x46, 116 },       /*       -1 */
+       { 1, 0x46, 116 },       /*        0 */
+       { 1, 0x46, 116 },       /* 2412   1 */
+       { 1, 0x46, 117 },       /* 2417   2 */
+       { 1, 0x46, 118 },       /* 2422   3 */
+       { 1, 0x46, 119 },       /* 2427   4 */
+       { 1, 0x46, 120 },       /* 2432   5 */
+       { 1, 0x46, 121 },       /* 2437   6 */
+       { 1, 0x46, 122 },       /* 2442   7 */
+       { 1, 0x46, 123 },       /* 2447   8 */
+       { 1, 0x46, 124 },       /* 2452   9 */
+       { 1, 0x46, 125 },       /* 2457  10 */
+       { 1, 0x46, 126 },       /* 2462  11 */
+       { 1, 0x46, 127 },       /* 2467  12 */
+       { 1, 0x46, 128 },       /* 2472  13 */
+       { 1, 0x44, 124 },       /* 2484  14 */
+       { 1, 0x46, 136 },       /* 2512  15 */
+       { 1, 0x46, 140 },       /* 2532  16 */
+       { 1, 0x46, 144 },       /* 2552  17 */
+       { 1, 0x46, 148 },       /* 2572  18 */
+       { 1, 0x46, 152 },       /* 2592  19 */
+       { 1, 0x46, 156 },       /* 2612  20 */
+       { 1, 0x46, 160 },       /* 2632  21 */
+       { 1, 0x46, 164 },       /* 2652  22 */
+       { 1, 0x46, 168 },       /* 2672  23 */
+       { 1, 0x46, 172 },       /* 2692  24 */
+       { 1, 0x46, 176 },       /* 2712  25 */
+       { 1, 0x46, 180 }        /* 2732  26 */
+};
+
+/* Power timeouts in usec to wait for chip to wake-up. */
+#define POWER_UP_TIME  2000
+
+#define        DELAY_PLL_SETTLE        300             /* 300 us */
+#define        DELAY_BASE_ACTIVATE     100             /* 100 us */
+
+#define NUM_RATES      8
+
+static HAL_BOOL ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask);
+static HAL_BOOL ar5211SetChannel(struct ath_hal *,  HAL_CHANNEL_INTERNAL *);
+static int16_t ar5211RunNoiseFloor(struct ath_hal *,
+               uint8_t runTime, int16_t startingNF);
+static HAL_BOOL ar5211IsNfGood(struct ath_hal *, HAL_CHANNEL_INTERNAL *chan);
+static HAL_BOOL ar5211SetRf6and7(struct ath_hal *, HAL_CHANNEL *chan);
+static HAL_BOOL ar5211SetBoardValues(struct ath_hal *, HAL_CHANNEL *chan);
+static void ar5211SetPowerTable(struct ath_hal *,
+               PCDACS_EEPROM *pSrcStruct, uint16_t channel);
+static void ar5211SetRateTable(struct ath_hal *,
+               RD_EDGES_POWER *pRdEdgesPower, TRGT_POWER_INFO *pPowerInfo,
+               uint16_t numChannels, HAL_CHANNEL *chan);
+static uint16_t ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue,
+               const PCDACS_EEPROM *pSrcStruct);
+static HAL_BOOL ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue,
+               const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue);
+static uint16_t ar5211GetInterpolatedValue(uint16_t target,
+               uint16_t srcLeft, uint16_t srcRight,
+               uint16_t targetLeft, uint16_t targetRight, HAL_BOOL scaleUp);
+static void ar5211GetLowerUpperValues(uint16_t value,
+               const uint16_t *pList, uint16_t listSize,
+               uint16_t *pLowerValue, uint16_t *pUpperValue);
+static void ar5211GetLowerUpperPcdacs(uint16_t pcdac,
+               uint16_t channel, const PCDACS_EEPROM *pSrcStruct,
+               uint16_t *pLowerPcdac, uint16_t *pUpperPcdac);
+
+static void ar5211SetRfgain(struct ath_hal *, const GAIN_VALUES *);;
+static void ar5211RequestRfgain(struct ath_hal *);
+static HAL_BOOL ar5211InvalidGainReadback(struct ath_hal *, GAIN_VALUES *);
+static HAL_BOOL ar5211IsGainAdjustNeeded(struct ath_hal *, const GAIN_VALUES *);
+static int32_t ar5211AdjustGain(struct ath_hal *, GAIN_VALUES *);
+static void ar5211SetOperatingMode(struct ath_hal *, int opmode);
+
+/*
+ * Places the device in and out of reset and then places sane
+ * values in the registers based on EEPROM config, initialization
+ * vectors (as determined by the mode), and station configuration
+ *
+ * bChannelChange is used to preserve DMA/PCU registers across
+ * a HW Reset during channel change.
+ */
+HAL_BOOL
+ar5211Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+       HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
+{
+uint32_t softLedCfg, softLedState;
+#define        N(a)    (sizeof (a) /sizeof (a[0]))
+#define        FAIL(_code)     do { ecode = _code; goto bad; } while (0)
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       HAL_CHANNEL_INTERNAL *ichan;
+       uint32_t i, ledstate;
+       HAL_STATUS ecode;
+       int q;
+
+       uint32_t                data, synthDelay;
+       uint32_t                macStaId1;
+       uint16_t                modesIndex = 0, freqIndex = 0;
+       uint32_t                saveFrameSeqCount[AR_NUM_DCU];
+       uint32_t                saveTsfLow = 0, saveTsfHigh = 0;
+       uint32_t                saveDefAntenna;
+
+       HALDEBUG(ah, HAL_DEBUG_RESET,
+            "%s: opmode %u channel %u/0x%x %s channel\n",
+            __func__, opmode, chan->channel, chan->channelFlags,
+            bChannelChange ? "change" : "same");
+
+       OS_MARK(ah, AH_MARK_RESET, bChannelChange);
+#define        IS(_c,_f)       (((_c)->channelFlags & _f) || 0)
+       if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan,CHANNEL_5GHZ)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+#undef IS
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       switch (opmode) {
+       case HAL_M_STA:
+       case HAL_M_IBSS:
+       case HAL_M_HOSTAP:
+       case HAL_M_MONITOR:
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid operating mode %u\n", __func__, opmode);
+               FAIL(HAL_EINVAL);
+               break;
+       }
+       HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3);
+
+       /* Preserve certain DMA hardware registers on a channel change */
+       if (bChannelChange) {
+               /*
+                * Need to save/restore the TSF because of an issue
+                * that accelerates the TSF during a chip reset.
+                *
+                * We could use system timer routines to more
+                * accurately restore the TSF, but
+                * 1. Timer routines on certain platforms are
+                *      not accurate enough (e.g. 1 ms resolution).
+                * 2. It would still not be accurate.
+                *
+                * The most important aspect of this workaround,
+                * is that, after reset, the TSF is behind
+                * other STAs TSFs.  This will allow the STA to
+                * properly resynchronize its TSF in adhoc mode.
+                */
+               saveTsfLow  = OS_REG_READ(ah, AR_TSF_L32);
+               saveTsfHigh = OS_REG_READ(ah, AR_TSF_U32);
+
+               /* Read frame sequence count */
+               if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
+                       saveFrameSeqCount[0] = OS_REG_READ(ah, AR_D0_SEQNUM);
+               } else {
+                       for (i = 0; i < AR_NUM_DCU; i++)
+                               saveFrameSeqCount[i] = OS_REG_READ(ah, AR_DSEQNUM(i));
+               }
+               if (!(ichan->privFlags & CHANNEL_DFS))
+                       ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+               chan->channelFlags = ichan->channelFlags;
+               chan->privFlags = ichan->privFlags;
+       }
+
+       /*
+        * Preserve the antenna on a channel change
+        */
+       saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
+       if (saveDefAntenna == 0)
+               saveDefAntenna = 1;
+
+       /* Save hardware flag before chip reset clears the register */
+       macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
+
+       /* Save led state from pci config register */
+       ledstate = OS_REG_READ(ah, AR_PCICFG) &
+               (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
+                AR_PCICFG_LEDSLOW);
+       softLedCfg = OS_REG_READ(ah, AR_GPIOCR);
+       softLedState = OS_REG_READ(ah, AR_GPIODO);
+
+       if (!ar5211ChipReset(ah, chan->channelFlags)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Setup the indices for the next set of register array writes */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+               modesIndex = 1;
+               freqIndex  = 1;
+               break;
+       case CHANNEL_T:
+               modesIndex = 2;
+               freqIndex  = 1;
+               break;
+       case CHANNEL_B:
+               modesIndex = 3;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_PUREG:
+               modesIndex = 4;
+               freqIndex  = 2;
+               break;
+       default:
+               /* Ah, a new wireless mode */
+               HALASSERT(0);
+               break;
+       }
+
+       /* Set correct Baseband to analog shift setting to access analog chips. */
+       if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
+               OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007);
+       } else {
+               OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047);
+       }
+
+       /* Write parameters specific to AR5211 */
+       if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
+               if (IS_CHAN_2GHZ(chan) &&
+                   AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1) {
+                       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+                       uint32_t ob2GHz, db2GHz;
+
+                       if (IS_CHAN_CCK(chan)) {
+                               ob2GHz = ee->ee_ob2GHz[0];
+                               db2GHz = ee->ee_db2GHz[0];
+                       } else {
+                               ob2GHz = ee->ee_ob2GHz[1];
+                               db2GHz = ee->ee_db2GHz[1];
+                       }
+                       ob2GHz = ath_hal_reverseBits(ob2GHz, 3);
+                       db2GHz = ath_hal_reverseBits(db2GHz, 3);
+                       ar5211Mode2_4[25][freqIndex] =
+                               (ar5211Mode2_4[25][freqIndex] & ~0xC0) |
+                                       ((ob2GHz << 6) & 0xC0);
+                       ar5211Mode2_4[26][freqIndex] =
+                               (ar5211Mode2_4[26][freqIndex] & ~0x0F) |
+                                       (((ob2GHz >> 2) & 0x1) |
+                                        ((db2GHz << 1) & 0x0E));
+               }
+               for (i = 0; i < N(ar5211Mode2_4); i++)
+                       OS_REG_WRITE(ah, ar5211Mode2_4[i][0],
+                               ar5211Mode2_4[i][freqIndex]);
+       }
+
+       /* Write the analog registers 6 and 7 before other config */
+       ar5211SetRf6and7(ah, chan);
+
+       /* Write registers that vary across all modes */
+       for (i = 0; i < N(ar5211Modes); i++)
+               OS_REG_WRITE(ah, ar5211Modes[i][0], ar5211Modes[i][modesIndex]);
+
+       /* Write RFGain Parameters that differ between 2.4 and 5 GHz */
+       for (i = 0; i < N(ar5211BB_RfGain); i++)
+               OS_REG_WRITE(ah, ar5211BB_RfGain[i][0], ar5211BB_RfGain[i][freqIndex]);
+
+       /* Write Common Array Parameters */
+       for (i = 0; i < N(ar5211Common); i++) {
+               uint32_t reg = ar5211Common[i][0];
+               /* On channel change, don't reset the PCU registers */
+               if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000)))
+                       OS_REG_WRITE(ah, reg, ar5211Common[i][1]);
+       }
+
+       /* Fix pre-AR5211 register values, this includes AR5311s. */
+       if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
+               /*
+                * The TX and RX latency values have changed locations
+                * within the USEC register in AR5211.  Since they're
+                * set via the .ini, for both AR5211 and AR5311, they
+                * are written properly here for AR5311.
+                */
+               data = OS_REG_READ(ah, AR_USEC);
+               /* Must be 0 for proper write in AR5311 */
+               HALASSERT((data & 0x00700000) == 0);
+               OS_REG_WRITE(ah, AR_USEC,
+                       (data & (AR_USEC_M | AR_USEC_32_M | AR5311_USEC_TX_LAT_M)) |
+                       ((29 << AR5311_USEC_RX_LAT_S) & AR5311_USEC_RX_LAT_M));
+               /* The following registers exist only on AR5311. */
+               OS_REG_WRITE(ah, AR5311_QDCLKGATE, 0);
+
+               /* Set proper ADC & DAC delays for AR5311. */
+               OS_REG_WRITE(ah, 0x00009878, 0x00000008);
+
+               /* Enable the PCU FIFO corruption ECO on AR5311. */
+               OS_REG_WRITE(ah, AR_DIAG_SW,
+                       OS_REG_READ(ah, AR_DIAG_SW) | AR5311_DIAG_SW_USE_ECO);
+       }
+
+       /* Restore certain DMA hardware registers on a channel change */
+       if (bChannelChange) {
+               /* Restore TSF */
+               OS_REG_WRITE(ah, AR_TSF_L32, saveTsfLow);
+               OS_REG_WRITE(ah, AR_TSF_U32, saveTsfHigh);
+
+               if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
+                       OS_REG_WRITE(ah, AR_D0_SEQNUM, saveFrameSeqCount[0]);
+               } else {
+                       for (i = 0; i < AR_NUM_DCU; i++)
+                               OS_REG_WRITE(ah, AR_DSEQNUM(i), saveFrameSeqCount[i]);
+               }
+       }
+
+       OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
+       OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
+               | macStaId1
+       );
+       ar5211SetOperatingMode(ah, opmode);
+
+       /* Restore previous led state */
+       OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate);
+       OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg);
+       OS_REG_WRITE(ah, AR_GPIODO, softLedState);
+
+       /* Restore previous antenna */
+       OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
+
+       /* Restore bmiss rssi & count thresholds */
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+
+       OS_REG_WRITE(ah, AR_ISR, ~0);           /* cleared on write */
+
+       /*
+        * for pre-Production Oahu only.
+        * Disable clock gating in all DMA blocks. Helps when using
+        * 11B and AES but results in higher power consumption.
+        */
+       if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_OAHU &&
+           AH_PRIVATE(ah)->ah_macRev < AR_SREV_OAHU_PROD) {
+               OS_REG_WRITE(ah, AR_CFG,
+                       OS_REG_READ(ah, AR_CFG) | AR_CFG_CLK_GATE_DIS);
+       }
+
+       /* Setup the transmit power values. */
+       if (!ar5211SetTransmitPower(ah, chan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /*
+        * Configurable OFDM spoofing for 11n compatibility; used
+        * only when operating in station mode.
+        */
+       if (opmode != HAL_M_HOSTAP &&
+           (AH_PRIVATE(ah)->ah_11nCompat & HAL_DIAG_11N_SERVICES) != 0) {
+               /* NB: override the .ini setting */
+               OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
+                       AR_PHY_FRAME_CTL_ERR_SERV,
+                       MS(AH_PRIVATE(ah)->ah_11nCompat, HAL_DIAG_11N_SERVICES)&1);
+       }
+
+       /* Setup board specific options for EEPROM version 3 */
+       ar5211SetBoardValues(ah, chan);
+
+       if (!ar5211SetChannel(ah, ichan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n",
+                   __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Activate the PHY */
+       if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B && IS_CHAN_2GHZ(chan))
+               OS_REG_WRITE(ah, 0xd808, 0x502); /* required for FPGA */
+       OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+       /*
+        * Wait for the frequency synth to settle (synth goes on
+        * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
+        * Value is in 100ns increments.
+        */
+       data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_M;
+       if (IS_CHAN_CCK(chan)) {
+               synthDelay = (4 * data) / 22;
+       } else {
+               synthDelay = data / 10;
+       }
+       /*
+        * There is an issue if the AP starts the calibration before
+        * the baseband timeout completes.  This could result in the
+        * rxclear false triggering.  Add an extra delay to ensure this
+        * this does not happen.
+        */
+       OS_DELAY(synthDelay + DELAY_BASE_ACTIVATE);
+
+       /* Calibrate the AGC and wait for completion. */
+       OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
+       (void) ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0);
+
+       /* Perform noise floor and set status */
+       if (!ar5211CalNoiseFloor(ah, ichan)) {
+               if (!IS_CHAN_CCK(chan))
+                       chan->channelFlags |= CHANNEL_CW_INT;
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: noise floor calibration failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
+       if (ahp->ah_calibrationTime != 0) {
+               OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4,
+                       AR_PHY_TIMING_CTRL4_DO_IQCAL | (INIT_IQCAL_LOG_COUNT_MAX << AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S));
+               ahp->ah_bIQCalibration = AH_TRUE;
+       }
+
+       /* set 1:1 QCU to DCU mapping for all queues */
+       for (q = 0; q < AR_NUM_DCU; q++)
+               OS_REG_WRITE(ah, AR_DQCUMASK(q), 1<<q);
+
+       for (q = 0; q < HAL_NUM_TX_QUEUES; q++)
+               ar5211ResetTxQueue(ah, q);
+
+       /* Setup QCU0 transmit interrupt masks (TX_ERR, TX_OK, TX_DESC, TX_URN) */
+       OS_REG_WRITE(ah, AR_IMR_S0,
+                (AR_IMR_S0_QCU_TXOK & AR_QCU_0) |
+                (AR_IMR_S0_QCU_TXDESC & (AR_QCU_0<<AR_IMR_S0_QCU_TXDESC_S)));
+       OS_REG_WRITE(ah, AR_IMR_S1, (AR_IMR_S1_QCU_TXERR & AR_QCU_0));
+       OS_REG_WRITE(ah, AR_IMR_S2, (AR_IMR_S2_QCU_TXURN & AR_QCU_0));
+
+       /*
+        * GBL_EIFS must always be written after writing
+        *              to any QCUMASK register.
+        */
+       OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, OS_REG_READ(ah, AR_D_GBL_IFS_EIFS));
+
+       /* Now set up the Interrupt Mask Register and save it for future use */
+       OS_REG_WRITE(ah, AR_IMR, INIT_INTERRUPT_MASK);
+       ahp->ah_maskReg = INIT_INTERRUPT_MASK;
+
+       /* Enable bus error interrupts */
+       OS_REG_WRITE(ah, AR_IMR_S2, OS_REG_READ(ah, AR_IMR_S2) |
+                AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);
+
+       /* Enable interrupts specific to AP */
+       if (opmode == HAL_M_HOSTAP) {
+               OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_MIB);
+               ahp->ah_maskReg |= AR_IMR_MIB;
+       }
+
+       if (AH_PRIVATE(ah)->ah_rfkillEnabled)
+               ar5211EnableRfKill(ah);
+
+       /*
+        * Writing to AR_BEACON will start timers. Hence it should
+        * be the last register to be written. Do not reset tsf, do
+        * not enable beacons at this point, but preserve other values
+        * like beaconInterval.
+        */
+       OS_REG_WRITE(ah, AR_BEACON,
+               (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));
+
+       /* Restore user-specified slot time and timeouts */
+       if (ahp->ah_sifstime != (u_int) -1)
+               ar5211SetSifsTime(ah, ahp->ah_sifstime);
+       if (ahp->ah_slottime != (u_int) -1)
+               ar5211SetSlotTime(ah, ahp->ah_slottime);
+       if (ahp->ah_acktimeout != (u_int) -1)
+               ar5211SetAckTimeout(ah, ahp->ah_acktimeout);
+       if (ahp->ah_ctstimeout != (u_int) -1)
+               ar5211SetCTSTimeout(ah, ahp->ah_ctstimeout);
+       if (AH_PRIVATE(ah)->ah_diagreg != 0)
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+
+       AH_PRIVATE(ah)->ah_opmode = opmode;     /* record operating mode */
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
+
+       return AH_TRUE;
+bad:
+       if (*status)
+               *status = ecode;
+       return AH_FALSE;
+#undef FAIL
+#undef N
+}
+
+/*
+ * Places the PHY and Radio chips into reset.  A full reset
+ * must be called to leave this state.  The PCI/MAC/PCU are
+ * not placed into reset as we must receive interrupt to
+ * re-enable the hardware.
+ */
+HAL_BOOL
+ar5211PhyDisable(struct ath_hal *ah)
+{
+       return ar5211SetResetReg(ah, AR_RC_BB);
+}
+
+/*
+ * Places all of hardware into reset
+ */
+HAL_BOOL
+ar5211Disable(struct ath_hal *ah)
+{
+       if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+       /*
+        * Reset the HW - PCI must be reset after the rest of the
+        * device has been reset.
+        */
+       if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))
+               return AH_FALSE;
+       OS_DELAY(2100);    /* 8245 @ 96Mhz hangs with 2000us. */
+
+       return AH_TRUE;
+}
+
+/*
+ * Places the hardware into reset and then pulls it out of reset
+ *
+ * Only write the PLL if we're changing to or from CCK mode
+ *
+ * Attach calls with channelFlags = 0, as the coldreset should have
+ * us in the correct mode and we cannot check the hwchannel flags.
+ */
+HAL_BOOL
+ar5211ChipReset(struct ath_hal *ah, uint16_t channelFlags)
+{
+       if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+
+       /* Set CCK and Turbo modes correctly */
+       switch (channelFlags & CHANNEL_ALL) {
+       case CHANNEL_2GHZ|CHANNEL_CCK:
+       case CHANNEL_2GHZ|CHANNEL_CCK|CHANNEL_TURBO:
+               OS_REG_WRITE(ah, AR_PHY_TURBO, 0);
+               OS_REG_WRITE(ah, AR5211_PHY_MODE,
+                       AR5211_PHY_MODE_CCK | AR5211_PHY_MODE_RF2GHZ);
+               OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44);
+               /* Wait for the PLL to settle */
+               OS_DELAY(DELAY_PLL_SETTLE);
+               break;
+       case CHANNEL_2GHZ|CHANNEL_OFDM:
+       case CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO:
+               OS_REG_WRITE(ah, AR_PHY_TURBO, 0);
+               if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) {
+                       OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40);
+                       OS_DELAY(DELAY_PLL_SETTLE);
+                       OS_REG_WRITE(ah, AR5211_PHY_MODE,
+                               AR5211_PHY_MODE_OFDM | AR5211_PHY_MODE_RF2GHZ);
+               }
+               break;
+       case CHANNEL_A:
+       case CHANNEL_T:
+               if (channelFlags & CHANNEL_TURBO) {
+                       OS_REG_WRITE(ah, AR_PHY_TURBO,
+                               AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT);
+               } else {                                /* 5 GHZ OFDM Mode */
+                       OS_REG_WRITE(ah, AR_PHY_TURBO, 0);
+               }
+               if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) {
+                       OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40);
+                       OS_DELAY(DELAY_PLL_SETTLE);
+                       OS_REG_WRITE(ah, AR5211_PHY_MODE,
+                               AR5211_PHY_MODE_OFDM | AR5211_PHY_MODE_RF5GHZ);
+               }
+               break;
+       }
+       /* NB: else no flags set - must be attach calling - do nothing */
+
+       /*
+        * Reset the HW - PCI must be reset after the rest of the
+        * device has been reset
+        */
+       if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))
+               return AH_FALSE;
+       OS_DELAY(2100);    /* 8245 @ 96Mhz hangs with 2000us. */
+
+       /* Bring out of sleep mode (AGAIN) */
+       if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+
+       /* Clear warm reset register */
+       return ar5211SetResetReg(ah, 0);
+}
+
+/*
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+HAL_BOOL
+ar5211PerCalibrationN(struct ath_hal *ah,  HAL_CHANNEL *chan, u_int chainMask,
+       HAL_BOOL longCal, HAL_BOOL *isCalDone)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       HAL_CHANNEL_INTERNAL *ichan;
+       int32_t qCoff, qCoffDenom;
+       uint32_t data;
+       int32_t iqCorrMeas;
+       int32_t iCoff, iCoffDenom;
+       uint32_t powerMeasQ, powerMeasI;
+
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               return AH_FALSE;
+       }
+       /* IQ calibration in progress. Check to see if it has finished. */
+       if (ahp->ah_bIQCalibration &&
+           !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) {
+               /* IQ Calibration has finished. */
+               ahp->ah_bIQCalibration = AH_FALSE;
+
+               /* Read calibration results. */
+               powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I);
+               powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q);
+               iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS);
+
+               /*
+                * Prescale these values to remove 64-bit operation requirement at the loss
+                * of a little precision.
+                */
+               iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
+               qCoffDenom = powerMeasQ / 64;
+
+               /* Protect against divide-by-0. */
+               if (iCoffDenom != 0 && qCoffDenom != 0) {
+                       iCoff = (-iqCorrMeas) / iCoffDenom;
+                       /* IQCORR_Q_I_COFF is a signed 6 bit number */
+                       iCoff = iCoff & 0x3f;
+
+                       qCoff = ((int32_t)powerMeasI / qCoffDenom) - 64;
+                       /* IQCORR_Q_Q_COFF is a signed 5 bit number */
+                       qCoff = qCoff & 0x1f;
+
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasI = 0x%08x\n",
+                           powerMeasI);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasQ = 0x%08x\n",
+                           powerMeasQ);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, "iqCorrMeas = 0x%08x\n",
+                           iqCorrMeas);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, "iCoff     = %d\n",
+                           iCoff);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, "qCoff     = %d\n",
+                           qCoff);
+
+                       /* Write IQ */
+                       data  = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) |
+                               AR_PHY_TIMING_CTRL4_IQCORR_ENABLE |
+                               (((uint32_t)iCoff) << AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S) |
+                               ((uint32_t)qCoff);
+                       OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, data);
+               }
+       }
+       *isCalDone = !ahp->ah_bIQCalibration;
+
+       if (longCal) {
+               /* Perform noise floor and set status */
+               if (!ar5211IsNfGood(ah, ichan)) {
+                       /* report up and clear internal state */
+                       chan->channelFlags |= CHANNEL_CW_INT;
+                       ichan->channelFlags &= ~CHANNEL_CW_INT;
+                       return AH_FALSE;
+               }
+               if (!ar5211CalNoiseFloor(ah, ichan)) {
+                       /*
+                        * Delay 5ms before retrying the noise floor
+                        * just to make sure, as we are in an error
+                        * condition here.
+                        */
+                       OS_DELAY(5000);
+                       if (!ar5211CalNoiseFloor(ah, ichan)) {
+                               if (!IS_CHAN_CCK(chan))
+                                       chan->channelFlags |= CHANNEL_CW_INT;
+                               return AH_FALSE;
+                       }
+               }
+               ar5211RequestRfgain(ah);
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5211PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone)
+{
+       return ar5211PerCalibrationN(ah,  chan, 0x1, AH_TRUE, isIQdone);
+}
+
+HAL_BOOL
+ar5211ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       /* XXX */
+       return AH_TRUE;
+}
+
+/*
+ * Writes the given reset bit mask into the reset register
+ */
+static HAL_BOOL
+ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask)
+{
+       uint32_t mask = resetMask ? resetMask : ~0;
+       HAL_BOOL rt;
+
+       (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */
+       OS_REG_WRITE(ah, AR_RC, resetMask);
+
+       /* need to wait at least 128 clocks when reseting PCI before read */
+       OS_DELAY(15);
+
+       resetMask &= AR_RC_MAC | AR_RC_BB;
+       mask &= AR_RC_MAC | AR_RC_BB;
+       rt = ath_hal_wait(ah, AR_RC, mask, resetMask);
+        if ((resetMask & AR_RC_MAC) == 0) {
+               if (isBigEndian()) {
+                       /*
+                        * Set CFG, little-endian for register
+                        * and descriptor accesses.
+                        */
+                       mask = INIT_CONFIG_STATUS |
+                               AR_CFG_SWTD | AR_CFG_SWRD | AR_CFG_SWRG;
+                       OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));
+               } else
+                       OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
+       }
+       return rt;
+}
+
+/*
+ * Takes the MHz channel value and sets the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus before AGC is active
+ *   or by disabling the AGC.
+ */
+static HAL_BOOL
+ar5211SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t refClk, reg32, data2111;
+       int16_t chan5111, chanIEEE;
+
+       chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags);
+       if (IS_CHAN_2GHZ(chan)) {
+               const CHAN_INFO_2GHZ* ci =
+                       &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION];
+
+               data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff)
+                               << 5)
+                        | (ci->refClkSel << 4);
+               chan5111 = ci->channel5111;
+       } else {
+               data2111 = 0;
+               chan5111 = chanIEEE;
+       }
+
+       /* Rest of the code is common for 5 GHz and 2.4 GHz. */
+       if (chan5111 >= 145 || (chan5111 & 0x1)) {
+               reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xFF;
+               refClk = 1;
+       } else {
+               reg32 = ath_hal_reverseBits(((chan5111 - 24) / 2), 8) & 0xFF;
+               refClk = 0;
+       }
+
+       reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1;
+       OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff));
+       reg32 >>= 8;
+       OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff));
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+}
+
+static int16_t
+ar5211GetNoiseFloor(struct ath_hal *ah)
+{
+       int16_t nf;
+
+       nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
+       if (nf & 0x100)
+               nf = 0 - ((nf ^ 0x1ff) + 1);
+       return nf;
+}
+
+/*
+ * Peform the noisefloor calibration for the length of time set
+ * in runTime (valid values 1 to 7)
+ *
+ * Returns: The NF value at the end of the given time (or 0 for failure)
+ */
+int16_t
+ar5211RunNoiseFloor(struct ath_hal *ah, uint8_t runTime, int16_t startingNF)
+{
+       int i, searchTime;
+
+       HALASSERT(runTime <= 7);
+
+       /* Setup  noise floor run time and starting value */
+       OS_REG_WRITE(ah, AR_PHY(25),
+               (OS_REG_READ(ah, AR_PHY(25)) & ~0xFFF) |
+                        ((runTime << 9) & 0xE00) | (startingNF & 0x1FF));
+       /* Calibrate the noise floor */
+       OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+               OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
+
+       /* Compute the required amount of searchTime needed to finish NF */
+       if (runTime == 0) {
+               /* 8 search windows * 6.4us each */
+               searchTime = 8  * 7;
+       } else {
+               /* 512 * runtime search windows * 6.4us each */
+               searchTime = (runTime * 512)  * 7;
+       }
+
+       /*
+        * Do not read noise floor until it has been updated
+        *
+        * As a guesstimate - we may only get 1/60th the time on
+        * the air to see search windows  in a heavily congested
+        * network (40 us every 2400 us of time)
+        */
+       for (i = 0; i < 60; i++) {
+               if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0)
+                       break;
+               OS_DELAY(searchTime);
+       }
+       if (i >= 60) {
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF with runTime %d failed to end on channel %d\n",
+                   runTime, AH_PRIVATE(ah)->ah_curchan->channel);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "  PHY NF Reg state:         0x%x\n",
+                   OS_REG_READ(ah, AR_PHY_AGC_CONTROL));
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "  PHY Active Reg state: 0x%x\n",
+                   OS_REG_READ(ah, AR_PHY_ACTIVE));
+               return 0;
+       }
+
+       return ar5211GetNoiseFloor(ah);
+}
+
+static HAL_BOOL
+getNoiseFloorThresh(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, int16_t *nft)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:
+               *nft = ee->ee_noiseFloorThresh[0];
+               break;
+       case CHANNEL_CCK|CHANNEL_2GHZ:
+               *nft = ee->ee_noiseFloorThresh[1];
+               break;
+       case CHANNEL_OFDM|CHANNEL_2GHZ:
+               *nft = ee->ee_noiseFloorThresh[2];
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Read the NF and check it against the noise floor threshhold
+ *
+ * Returns: TRUE if the NF is good
+ */
+static HAL_BOOL
+ar5211IsNfGood(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       int16_t nf, nfThresh;
+
+       if (!getNoiseFloorThresh(ah, chan, &nfThresh))
+               return AH_FALSE;
+#ifdef AH_DEBUG
+       if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: NF did not complete in calibration window\n", __func__);
+#endif
+       nf = ar5211GetNoiseFloor(ah);
+       if (nf > nfThresh) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: noise floor failed; detected %u, threshold %u\n",
+                   __func__, nf, nfThresh);
+               /*
+                * NB: Don't discriminate 2.4 vs 5Ghz, if this
+                *     happens it indicates a problem regardless
+                *     of the band.
+                */
+               chan->channelFlags |= CHANNEL_CW_INT;
+       }
+       chan->rawNoiseFloor = nf;
+       return (nf <= nfThresh);
+}
+
+/*
+ * Peform the noisefloor calibration and check for any constant channel
+ * interference.
+ *
+ * NOTE: preAR5211 have a lengthy carrier wave detection process - hence
+ * it is if'ed for MKK regulatory domain only.
+ *
+ * Returns: TRUE for a successful noise floor calibration; else FALSE
+ */
+HAL_BOOL
+ar5211CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+       /* Check for Carrier Wave interference in MKK regulatory zone */
+       if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU &&
+           ath_hal_getnfcheckrequired(ah, (HAL_CHANNEL *) chan)) {
+               static const uint8_t runtime[3] = { 0, 2, 7 };
+               int16_t nf, nfThresh;
+               int i;
+
+               if (!getNoiseFloorThresh(ah, chan, &nfThresh))
+                       return AH_FALSE;
+               /*
+                * Run a quick noise floor that will hopefully
+                * complete (decrease delay time).
+                */
+               for (i = 0; i < N(runtime); i++) {
+                       nf = ar5211RunNoiseFloor(ah, runtime[i], 0);
+                       if (nf > nfThresh) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "%s: run failed with %u > threshold %u "
+                                   "(runtime %u)\n", __func__,
+                                   nf, nfThresh, runtime[i]);
+                               chan->rawNoiseFloor = 0;
+                       } else
+                               chan->rawNoiseFloor = nf;
+               }
+               return (i <= N(runtime));
+       } else {
+               /* Calibrate the noise floor */
+               OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                       OS_REG_READ(ah, AR_PHY_AGC_CONTROL) |
+                                AR_PHY_AGC_CONTROL_NF);
+       }
+       return AH_TRUE;
+#undef N
+}
+
+/*
+ * Adjust NF based on statistical values for 5GHz frequencies.
+ */
+int16_t
+ar5211GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
+{
+       static const struct {
+               uint16_t freqLow;
+               int16_t   adjust;
+       } adjust5111[] = {
+               { 5790, 11 },   /* NB: ordered high -> low */
+               { 5730, 10 },
+               { 5690,  9 },
+               { 5660,  8 },
+               { 5610,  7 },
+               { 5530,  5 },
+               { 5450,  4 },
+               { 5379,  2 },
+               { 5209,  0 },   /* XXX? bogus but doesn't matter */
+               {    0,  1 },
+       };
+       int i;
+
+       for (i = 0; c->channel <= adjust5111[i].freqLow; i++)
+               ;
+       /* NB: placeholder for 5111's less severe requirement */
+       return adjust5111[i].adjust / 3;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * analog registers 6 and 7
+ *
+ * REQUIRES: Access to the analog device
+ */
+static HAL_BOOL
+ar5211SetRf6and7(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       uint16_t rfXpdGain, rfPloSel, rfPwdXpd;
+       uint16_t tempOB, tempDB;
+       uint16_t freqIndex;
+       int i;
+
+       freqIndex = (chan->channelFlags & CHANNEL_2GHZ) ? 2 : 1;
+
+       /*
+        * TODO: This array mode correspondes with the index used
+        *       during the read.
+        * For readability, this should be changed to an enum or #define
+        */
+       switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:
+               if (chan->channel > 4000 && chan->channel < 5260) {
+                       tempOB = ee->ee_ob1;
+                       tempDB = ee->ee_db1;
+               } else if (chan->channel >= 5260 && chan->channel < 5500) {
+                       tempOB = ee->ee_ob2;
+                       tempDB = ee->ee_db2;
+               } else if (chan->channel >= 5500 && chan->channel < 5725) {
+                       tempOB = ee->ee_ob3;
+                       tempDB = ee->ee_db3;
+               } else if (chan->channel >= 5725) {
+                       tempOB = ee->ee_ob4;
+                       tempDB = ee->ee_db4;
+               } else {
+                       /* XXX panic?? */
+                       tempOB = tempDB = 0;
+               }
+
+               rfXpdGain = ee->ee_xgain[0];
+               rfPloSel  = ee->ee_xpd[0];
+               rfPwdXpd  = !ee->ee_xpd[0];
+
+               ar5211Rf6n7[5][freqIndex]  =
+                       (ar5211Rf6n7[5][freqIndex] & ~0x10000000) |
+                               (ee->ee_cornerCal.pd84<< 28);
+               ar5211Rf6n7[6][freqIndex]  =
+                       (ar5211Rf6n7[6][freqIndex] & ~0x04000000) |
+                               (ee->ee_cornerCal.pd90 << 26);
+               ar5211Rf6n7[21][freqIndex] =
+                       (ar5211Rf6n7[21][freqIndex] & ~0x08) |
+                               (ee->ee_cornerCal.gSel << 3);
+               break;
+       case CHANNEL_CCK|CHANNEL_2GHZ:
+               tempOB = ee->ee_obFor24;
+               tempDB = ee->ee_dbFor24;
+               rfXpdGain = ee->ee_xgain[1];
+               rfPloSel  = ee->ee_xpd[1];
+               rfPwdXpd  = !ee->ee_xpd[1];
+               break;
+       case CHANNEL_OFDM|CHANNEL_2GHZ:
+               tempOB = ee->ee_obFor24g;
+               tempDB = ee->ee_dbFor24g;
+               rfXpdGain = ee->ee_xgain[2];
+               rfPloSel  = ee->ee_xpd[2];
+               rfPwdXpd  = !ee->ee_xpd[2];
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       HALASSERT(1 <= tempOB && tempOB <= 5);
+       HALASSERT(1 <= tempDB && tempDB <= 5);
+
+       /* Set rfXpdGain and rfPwdXpd */
+       ar5211Rf6n7[11][freqIndex] =  (ar5211Rf6n7[11][freqIndex] & ~0xC0) |
+               (((ath_hal_reverseBits(rfXpdGain, 4) << 7) | (rfPwdXpd << 6)) & 0xC0);
+       ar5211Rf6n7[12][freqIndex] =  (ar5211Rf6n7[12][freqIndex] & ~0x07) |
+               ((ath_hal_reverseBits(rfXpdGain, 4) >> 1) & 0x07);
+
+       /* Set OB */
+       ar5211Rf6n7[12][freqIndex] =  (ar5211Rf6n7[12][freqIndex] & ~0x80) |
+               ((ath_hal_reverseBits(tempOB, 3) << 7) & 0x80);
+       ar5211Rf6n7[13][freqIndex] =  (ar5211Rf6n7[13][freqIndex] & ~0x03) |
+               ((ath_hal_reverseBits(tempOB, 3) >> 1) & 0x03);
+
+       /* Set DB */
+       ar5211Rf6n7[13][freqIndex] =  (ar5211Rf6n7[13][freqIndex] & ~0x1C) |
+               ((ath_hal_reverseBits(tempDB, 3) << 2) & 0x1C);
+
+       /* Set rfPloSel */
+       ar5211Rf6n7[17][freqIndex] =  (ar5211Rf6n7[17][freqIndex] & ~0x08) |
+               ((rfPloSel << 3) & 0x08);
+
+       /* Write the Rf registers 6 & 7 */
+       for (i = 0; i < N(ar5211Rf6n7); i++)
+               OS_REG_WRITE(ah, ar5211Rf6n7[i][0], ar5211Rf6n7[i][freqIndex]);
+
+       /* Now that we have reprogrammed rfgain value, clear the flag. */
+       ahp->ah_rfgainState = RFGAIN_INACTIVE;
+
+       return AH_TRUE;
+#undef N
+}
+
+HAL_BOOL
+ar5211SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings,
+                       const HAL_CHANNEL *chan)
+{
+#define        ANT_SWITCH_TABLE1       0x9960
+#define        ANT_SWITCH_TABLE2       0x9964
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       uint32_t antSwitchA, antSwitchB;
+       int ix;
+
+       switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:         ix = 0; break;
+       case CHANNEL_B:         ix = 1; break;
+       case CHANNEL_PUREG:     ix = 2; break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       antSwitchA =  ee->ee_antennaControl[1][ix]
+                  | (ee->ee_antennaControl[2][ix] << 6)
+                  | (ee->ee_antennaControl[3][ix] << 12)
+                  | (ee->ee_antennaControl[4][ix] << 18)
+                  | (ee->ee_antennaControl[5][ix] << 24)
+                  ;
+       antSwitchB =  ee->ee_antennaControl[6][ix]
+                  | (ee->ee_antennaControl[7][ix] << 6)
+                  | (ee->ee_antennaControl[8][ix] << 12)
+                  | (ee->ee_antennaControl[9][ix] << 18)
+                  | (ee->ee_antennaControl[10][ix] << 24)
+                  ;
+       /*
+        * For fixed antenna, give the same setting for both switch banks
+        */
+       switch (settings) {
+       case HAL_ANT_FIXED_A:
+               antSwitchB = antSwitchA;
+               break;
+       case HAL_ANT_FIXED_B:
+               antSwitchA = antSwitchB;
+               break;
+       case HAL_ANT_VARIABLE:
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n",
+                   __func__, settings);
+               return AH_FALSE;
+       }
+       ahp->ah_diversityControl = settings;
+
+       OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA);
+       OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB);
+
+       return AH_TRUE;
+#undef ANT_SWITCH_TABLE1
+#undef ANT_SWITCH_TABLE2
+}
+
+/*
+ * Reads EEPROM header info and programs the device for correct operation
+ * given the channel value
+ */
+static HAL_BOOL
+ar5211SetBoardValues(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       int arrayMode, falseDectectBackoff;
+
+       switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:
+               arrayMode = 0;
+               OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
+                       AR_PHY_FRAME_CTL_TX_CLIP, ee->ee_cornerCal.clip);
+               break;
+       case CHANNEL_CCK|CHANNEL_2GHZ:
+               arrayMode = 1;
+               break;
+       case CHANNEL_OFDM|CHANNEL_2GHZ:
+               arrayMode = 2;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /* Set the antenna register(s) correctly for the chip revision */
+       if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
+               OS_REG_WRITE(ah, AR_PHY(68),
+                       (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | 0x3);
+       } else {
+               OS_REG_WRITE(ah, AR_PHY(68),
+                       (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFC06) |
+                       (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1);
+
+               ar5211SetAntennaSwitchInternal(ah,
+                       ahp->ah_diversityControl, chan);
+
+               /* Set the Noise Floor Thresh on ar5211 devices */
+               OS_REG_WRITE(ah, AR_PHY_BASE + (90 << 2),
+                       (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF) | (1<<9));
+       }
+       OS_REG_WRITE(ah, AR_PHY_BASE + (17 << 2),
+               (OS_REG_READ(ah, AR_PHY_BASE + (17 << 2)) & 0xFFFFC07F) |
+               ((ee->ee_switchSettling[arrayMode] << 7) & 0x3F80));
+       OS_REG_WRITE(ah, AR_PHY_BASE + (18 << 2),
+               (OS_REG_READ(ah, AR_PHY_BASE + (18 << 2)) & 0xFFFC0FFF) |
+               ((ee->ee_txrxAtten[arrayMode] << 12) & 0x3F000));
+       OS_REG_WRITE(ah, AR_PHY_BASE + (20 << 2),
+               (OS_REG_READ(ah, AR_PHY_BASE + (20 << 2)) & 0xFFFF0000) |
+               ((ee->ee_pgaDesiredSize[arrayMode] << 8) & 0xFF00) |
+               (ee->ee_adcDesiredSize[arrayMode] & 0x00FF));
+       OS_REG_WRITE(ah, AR_PHY_BASE + (13 << 2),
+               (ee->ee_txEndToXPAOff[arrayMode] << 24) |
+               (ee->ee_txEndToXPAOff[arrayMode] << 16) |
+               (ee->ee_txFrameToXPAOn[arrayMode] << 8) |
+               ee->ee_txFrameToXPAOn[arrayMode]);
+       OS_REG_WRITE(ah, AR_PHY_BASE + (10 << 2),
+               (OS_REG_READ(ah, AR_PHY_BASE + (10 << 2)) & 0xFFFF00FF) |
+               (ee->ee_txEndToXLNAOn[arrayMode] << 8));
+       OS_REG_WRITE(ah, AR_PHY_BASE + (25 << 2),
+               (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) & 0xFFF80FFF) |
+               ((ee->ee_thresh62[arrayMode] << 12) & 0x7F000));
+
+#define NO_FALSE_DETECT_BACKOFF   2
+#define CB22_FALSE_DETECT_BACKOFF 6
+       /*
+        * False detect backoff - suspected 32 MHz spur causes
+        * false detects in OFDM, causing Tx Hangs.  Decrease
+        * weak signal sensitivity for this card.
+        */
+       falseDectectBackoff = NO_FALSE_DETECT_BACKOFF;
+       if (AH_PRIVATE(ah)->ah_eeversion < AR_EEPROM_VER3_3) {
+               if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 &&
+                   IS_CHAN_OFDM(chan))
+                       falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF;
+       } else {
+               uint32_t remainder = chan->channel % 32;
+
+               if (remainder && (remainder < 10 || remainder > 22))
+                       falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode];
+       }
+       OS_REG_WRITE(ah, 0x9924,
+               (OS_REG_READ(ah, 0x9924) & 0xFFFFFF01)
+               | ((falseDectectBackoff << 1) & 0xF7));
+
+       return AH_TRUE;
+#undef NO_FALSE_DETECT_BACKOFF
+#undef CB22_FALSE_DETECT_BACKOFF
+}
+
+/*
+ * Set the limit on the overall output power.  Used for dynamic
+ * transmit power control and the like.
+ *
+ * NOTE: The power is passed in is in units of 0.5 dBm.
+ */
+HAL_BOOL
+ar5211SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
+{
+
+       AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
+       OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, limit);
+       return AH_TRUE;
+}
+
+/*
+ * Sets the transmit power in the baseband for the given
+ * operating channel and mode.
+ */
+HAL_BOOL
+ar5211SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       TRGT_POWER_INFO *pi;
+       RD_EDGES_POWER *rep;
+       PCDACS_EEPROM eepromPcdacs;
+       u_int nchan, cfgCtl;
+       int i;
+
+       /* setup the pcdac struct to point to the correct info, based on mode */
+       switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:
+               eepromPcdacs.numChannels = ee->ee_numChannels11a;
+               eepromPcdacs.pChannelList= ee->ee_channels11a;
+               eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a;
+               nchan = ee->ee_numTargetPwr_11a;
+               pi = ee->ee_trgtPwr_11a;
+               break;
+       case CHANNEL_OFDM|CHANNEL_2GHZ:
+               eepromPcdacs.numChannels = ee->ee_numChannels2_4;
+               eepromPcdacs.pChannelList= ee->ee_channels11g;
+               eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g;
+               nchan = ee->ee_numTargetPwr_11g;
+               pi = ee->ee_trgtPwr_11g;
+               break;
+       case CHANNEL_CCK|CHANNEL_2GHZ:
+               eepromPcdacs.numChannels = ee->ee_numChannels2_4;
+               eepromPcdacs.pChannelList= ee->ee_channels11b;
+               eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b;
+               nchan = ee->ee_numTargetPwr_11b;
+               pi = ee->ee_trgtPwr_11b;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       ar5211SetPowerTable(ah, &eepromPcdacs, chan->channel);
+
+       rep = AH_NULL;
+       /* Match CTL to EEPROM value */
+       cfgCtl = ath_hal_getctl(ah, chan);
+       for (i = 0; i < ee->ee_numCtls; i++)
+               if (ee->ee_ctl[i] != 0 && ee->ee_ctl[i] == cfgCtl) {
+                       rep = &ee->ee_rdEdgesPower[i * NUM_EDGES];
+                       break;
+               }
+       ar5211SetRateTable(ah, rep, pi, nchan, chan);
+
+       return AH_TRUE;
+}
+
+/*
+ * Read the transmit power levels from the structures taken
+ * from EEPROM. Interpolate read transmit power values for
+ * this channel. Organize the transmit power values into a
+ * table for writing into the hardware.
+ */
+void
+ar5211SetPowerTable(struct ath_hal *ah, PCDACS_EEPROM *pSrcStruct, uint16_t channel)
+{
+       static FULL_PCDAC_STRUCT pcdacStruct;
+       static uint16_t pcdacTable[PWR_TABLE_SIZE];
+
+       uint16_t         i, j;
+       uint16_t         *pPcdacValues;
+       int16_t   *pScaledUpDbm;
+       int16_t   minScaledPwr;
+       int16_t   maxScaledPwr;
+       int16_t   pwr;
+       uint16_t         pcdacMin = 0;
+       uint16_t         pcdacMax = 63;
+       uint16_t         pcdacTableIndex;
+       uint16_t         scaledPcdac;
+       uint32_t         addr;
+       uint32_t         temp32;
+
+       OS_MEMZERO(&pcdacStruct, sizeof(FULL_PCDAC_STRUCT));
+       OS_MEMZERO(pcdacTable, sizeof(uint16_t) * PWR_TABLE_SIZE);
+       pPcdacValues = pcdacStruct.PcdacValues;
+       pScaledUpDbm = pcdacStruct.PwrValues;
+
+       /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */
+       for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++)
+               pPcdacValues[j] = i;
+
+       pcdacStruct.numPcdacValues = j;
+       pcdacStruct.pcdacMin = PCDAC_START;
+       pcdacStruct.pcdacMax = PCDAC_STOP;
+
+       /* Fill out the power values for this channel */
+       for (j = 0; j < pcdacStruct.numPcdacValues; j++ )
+               pScaledUpDbm[j] = ar5211GetScaledPower(channel, pPcdacValues[j], pSrcStruct);
+
+       /* Now scale the pcdac values to fit in the 64 entry power table */
+       minScaledPwr = pScaledUpDbm[0];
+       maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1];
+
+       /* find minimum and make monotonic */
+       for (j = 0; j < pcdacStruct.numPcdacValues; j++) {
+               if (minScaledPwr >= pScaledUpDbm[j]) {
+                       minScaledPwr = pScaledUpDbm[j];
+                       pcdacMin = j;
+               }
+               /*
+                * Make the full_hsh monotonically increasing otherwise
+                * interpolation algorithm will get fooled gotta start
+                * working from the top, hence i = 63 - j.
+                */
+               i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j);
+               if (i == 0)
+                       break;
+               if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) {
+                       /*
+                        * It could be a glitch, so make the power for
+                        * this pcdac the same as the power from the
+                        * next highest pcdac.
+                        */
+                       pScaledUpDbm[i - 1] = pScaledUpDbm[i];
+               }
+       }
+
+       for (j = 0; j < pcdacStruct.numPcdacValues; j++)
+               if (maxScaledPwr < pScaledUpDbm[j]) {
+                       maxScaledPwr = pScaledUpDbm[j];
+                       pcdacMax = j;
+               }
+
+       /* Find the first power level with a pcdac */
+       pwr = (uint16_t)(PWR_STEP * ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP)  + PWR_MIN);
+
+       /* Write all the first pcdac entries based off the pcdacMin */
+       pcdacTableIndex = 0;
+       for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++)
+               pcdacTable[pcdacTableIndex++] = pcdacMin;
+
+       i = 0;
+       while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1]) {
+               pwr += PWR_STEP;
+               /* stop if dbM > max_power_possible */
+               while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] &&
+                      (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0)
+                       i++;
+               /* scale by 2 and add 1 to enable round up or down as needed */
+               scaledPcdac = (uint16_t)(ar5211GetInterpolatedValue(pwr,
+                               pScaledUpDbm[i], pScaledUpDbm[i+1],
+                               (uint16_t)(pPcdacValues[i] * 2),
+                               (uint16_t)(pPcdacValues[i+1] * 2), 0) + 1);
+
+               pcdacTable[pcdacTableIndex] = scaledPcdac / 2;
+               if (pcdacTable[pcdacTableIndex] > pcdacMax)
+                       pcdacTable[pcdacTableIndex] = pcdacMax;
+               pcdacTableIndex++;
+       }
+
+       /* Write all the last pcdac entries based off the last valid pcdac */
+       while (pcdacTableIndex < PWR_TABLE_SIZE) {
+               pcdacTable[pcdacTableIndex] = pcdacTable[pcdacTableIndex - 1];
+               pcdacTableIndex++;
+       }
+
+       /* Finally, write the power values into the baseband power table */
+       addr = AR_PHY_BASE + (608 << 2);
+       for (i = 0; i < 32; i++) {
+               temp32 = 0xffff & ((pcdacTable[2 * i + 1] << 8) | 0xff);
+               temp32 = (temp32 << 16) | (0xffff & ((pcdacTable[2 * i] << 8) | 0xff));
+               OS_REG_WRITE(ah, addr, temp32);
+               addr += 4;
+       }
+
+}
+
+/*
+ * Set the transmit power in the baseband for the given
+ * operating channel and mode.
+ */
+void
+ar5211SetRateTable(struct ath_hal *ah, RD_EDGES_POWER *pRdEdgesPower,
+       TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels,
+       HAL_CHANNEL *chan)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       static uint16_t ratesArray[NUM_RATES];
+       static const uint16_t tpcScaleReductionTable[5] =
+               { 0, 3, 6, 9, MAX_RATE_POWER };
+
+       uint16_t        *pRatesPower;
+       uint16_t        lowerChannel = 0, lowerIndex=0, lowerPower=0;
+       uint16_t        upperChannel = 0, upperIndex=0, upperPower=0;
+       uint16_t        twiceMaxEdgePower=63;
+       uint16_t        twicePower = 0;
+       uint16_t        i, numEdges;
+       uint16_t        tempChannelList[NUM_EDGES]; /* temp array for holding edge channels */
+       uint16_t        twiceMaxRDPower;
+       int16_t  scaledPower = 0;               /* for gcc -O2 */
+       uint16_t        mask = 0x3f;
+       HAL_BOOL          paPreDEnable = 0;
+       int8_t    twiceAntennaGain, twiceAntennaReduction = 0;
+
+       pRatesPower = ratesArray;
+       twiceMaxRDPower = chan->maxRegTxPower * 2;
+
+       if (IS_CHAN_5GHZ(chan)) {
+               twiceAntennaGain = ee->ee_antennaGainMax[0];
+       } else {
+               twiceAntennaGain = ee->ee_antennaGainMax[1];
+       }
+
+       twiceAntennaReduction = ath_hal_getantennareduction(ah, chan, twiceAntennaGain);
+
+       if (pRdEdgesPower) {
+               /* Get the edge power */
+               for (i = 0; i < NUM_EDGES; i++) {
+                       if (pRdEdgesPower[i].rdEdge == 0)
+                               break;
+                       tempChannelList[i] = pRdEdgesPower[i].rdEdge;
+               }
+               numEdges = i;
+
+               ar5211GetLowerUpperValues(chan->channel, tempChannelList,
+                       numEdges, &lowerChannel, &upperChannel);
+               /* Get the index for this channel */
+               for (i = 0; i < numEdges; i++)
+                       if (lowerChannel == tempChannelList[i])
+                               break;
+               HALASSERT(i != numEdges);
+
+               if ((lowerChannel == upperChannel &&
+                    lowerChannel == chan->channel) ||
+                   pRdEdgesPower[i].flag) {
+                       twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower;
+                       HALASSERT(twiceMaxEdgePower > 0);
+               }
+       }
+
+       /* extrapolate the power values for the test Groups */
+       for (i = 0; i < numChannels; i++)
+               tempChannelList[i] = pPowerInfo[i].testChannel;
+
+       ar5211GetLowerUpperValues(chan->channel, tempChannelList,
+               numChannels, &lowerChannel, &upperChannel);
+
+       /* get the index for the channel */
+       for (i = 0; i < numChannels; i++) {
+               if (lowerChannel == tempChannelList[i])
+                       lowerIndex = i;
+               if (upperChannel == tempChannelList[i]) {
+                       upperIndex = i;
+                       break;
+               }
+       }
+
+       for (i = 0; i < NUM_RATES; i++) {
+               if (IS_CHAN_OFDM(chan)) {
+                       /* power for rates 6,9,12,18,24 is all the same */
+                       if (i < 5) {
+                               lowerPower = pPowerInfo[lowerIndex].twicePwr6_24;
+                               upperPower = pPowerInfo[upperIndex].twicePwr6_24;
+                       } else if (i == 5) {
+                               lowerPower = pPowerInfo[lowerIndex].twicePwr36;
+                               upperPower = pPowerInfo[upperIndex].twicePwr36;
+                       } else if (i == 6) {
+                               lowerPower = pPowerInfo[lowerIndex].twicePwr48;
+                               upperPower = pPowerInfo[upperIndex].twicePwr48;
+                       } else if (i == 7) {
+                               lowerPower = pPowerInfo[lowerIndex].twicePwr54;
+                               upperPower = pPowerInfo[upperIndex].twicePwr54;
+                       }
+               } else {
+                       switch (i) {
+                       case 0:
+                       case 1:
+                               lowerPower = pPowerInfo[lowerIndex].twicePwr6_24;
+                               upperPower = pPowerInfo[upperIndex].twicePwr6_24;
+                               break;
+                       case 2:
+                       case 3:
+                               lowerPower = pPowerInfo[lowerIndex].twicePwr36;
+                               upperPower = pPowerInfo[upperIndex].twicePwr36;
+                               break;
+                       case 4:
+                       case 5:
+                               lowerPower = pPowerInfo[lowerIndex].twicePwr48;
+                               upperPower = pPowerInfo[upperIndex].twicePwr48;
+                               break;
+                       case 6:
+                       case 7:
+                               lowerPower = pPowerInfo[lowerIndex].twicePwr54;
+                               upperPower = pPowerInfo[upperIndex].twicePwr54;
+                               break;
+                       }
+               }
+
+               twicePower = ar5211GetInterpolatedValue(chan->channel,
+                       lowerChannel, upperChannel, lowerPower, upperPower, 0);
+
+               /* Reduce power by band edge restrictions */
+               twicePower = AH_MIN(twicePower, twiceMaxEdgePower);
+
+               /*
+                * If turbo is set, reduce power to keep power
+                * consumption under 2 Watts.  Note that we always do
+                * this unless specially configured.  Then we limit
+                * power only for non-AP operation.
+                */
+               if (IS_CHAN_TURBO(chan) &&
+                   AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1
+#ifdef AH_ENABLE_AP_SUPPORT
+                   && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP
+#endif
+               ) {
+                       twicePower = AH_MIN(twicePower, ee->ee_turbo2WMaxPower5);
+               }
+
+               /* Reduce power by max regulatory domain allowed restrictions */
+               pRatesPower[i] = AH_MIN(twicePower, twiceMaxRDPower - twiceAntennaReduction);
+
+               /* Use 6 Mb power level for transmit power scaling reduction */
+               /* We don't want to reduce higher rates if its not needed */
+               if (i == 0) {
+                       scaledPower = pRatesPower[0] -
+                               (tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2);
+                       if (scaledPower < 1)
+                               scaledPower = 1;
+               }
+
+               pRatesPower[i] = AH_MIN(pRatesPower[i], scaledPower);
+       }
+
+       /* Record txPower at Rate 6 for info gathering */
+       ahp->ah_tx6PowerInHalfDbm = pRatesPower[0];
+
+#ifdef AH_DEBUG
+       HALDEBUG(ah, HAL_DEBUG_RESET,
+           "%s: final output power setting %d MHz:\n",
+           __func__, chan->channel);
+       HALDEBUG(ah, HAL_DEBUG_RESET,
+           "6 Mb %d dBm, MaxRD: %d dBm, MaxEdge %d dBm\n",
+           scaledPower / 2, twiceMaxRDPower / 2, twiceMaxEdgePower / 2);
+       HALDEBUG(ah, HAL_DEBUG_RESET, "TPC Scale %d dBm - Ant Red %d dBm\n",
+           tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2,
+           twiceAntennaReduction / 2);
+       if (IS_CHAN_TURBO(chan) &&
+           AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1)
+               HALDEBUG(ah, HAL_DEBUG_RESET, "Max Turbo %d dBm\n",
+                   ee->ee_turbo2WMaxPower5);
+       HALDEBUG(ah, HAL_DEBUG_RESET,
+           "  %2d | %2d | %2d | %2d | %2d | %2d | %2d | %2d dBm\n",
+           pRatesPower[0] / 2, pRatesPower[1] / 2, pRatesPower[2] / 2,
+           pRatesPower[3] / 2, pRatesPower[4] / 2, pRatesPower[5] / 2,
+           pRatesPower[6] / 2, pRatesPower[7] / 2);
+#endif /* AH_DEBUG */
+
+       /* Write the power table into the hardware */
+       OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+                ((paPreDEnable & 1)<< 30) | ((pRatesPower[3] & mask) << 24) |
+                ((paPreDEnable & 1)<< 22) | ((pRatesPower[2] & mask) << 16) |
+                ((paPreDEnable & 1)<< 14) | ((pRatesPower[1] & mask) << 8) |
+                ((paPreDEnable & 1)<< 6 ) |  (pRatesPower[0] & mask));
+       OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+                ((paPreDEnable & 1)<< 30) | ((pRatesPower[7] & mask) << 24) |
+                ((paPreDEnable & 1)<< 22) | ((pRatesPower[6] & mask) << 16) |
+                ((paPreDEnable & 1)<< 14) | ((pRatesPower[5] & mask) << 8) |
+                ((paPreDEnable & 1)<< 6 ) |  (pRatesPower[4] & mask));
+
+       /* set max power to the power value at rate 6 */
+       ar5211SetTxPowerLimit(ah, pRatesPower[0]);
+
+       AH_PRIVATE(ah)->ah_maxPowerLevel = pRatesPower[0];
+}
+
+/*
+ * Get or interpolate the pcdac value from the calibrated data
+ */
+uint16_t
+ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct)
+{
+       uint16_t powerValue;
+       uint16_t lFreq = 0, rFreq = 0;          /* left and right frequency values */
+       uint16_t llPcdac = 0, ulPcdac = 0;      /* lower and upper left pcdac values */
+       uint16_t lrPcdac = 0, urPcdac = 0;      /* lower and upper right pcdac values */
+       uint16_t lPwr = 0, uPwr = 0;            /* lower and upper temp pwr values */
+       uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */
+
+       if (ar5211FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue))
+               /* value was copied from srcStruct */
+               return powerValue;
+
+       ar5211GetLowerUpperValues(channel, pSrcStruct->pChannelList,
+               pSrcStruct->numChannels, &lFreq, &rFreq);
+       ar5211GetLowerUpperPcdacs(pcdacValue, lFreq, pSrcStruct,
+               &llPcdac, &ulPcdac);
+       ar5211GetLowerUpperPcdacs(pcdacValue, rFreq, pSrcStruct,
+               &lrPcdac, &urPcdac);
+
+       /* get the power index for the pcdac value */
+       ar5211FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr);
+       ar5211FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr);
+       lScaledPwr = ar5211GetInterpolatedValue(pcdacValue,
+                               llPcdac, ulPcdac, lPwr, uPwr, 0);
+
+       ar5211FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr);
+       ar5211FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr);
+       rScaledPwr = ar5211GetInterpolatedValue(pcdacValue,
+                               lrPcdac, urPcdac, lPwr, uPwr, 0);
+
+       return ar5211GetInterpolatedValue(channel, lFreq, rFreq,
+               lScaledPwr, rScaledPwr, 0);
+}
+
+/*
+ * Find the value from the calibrated source data struct
+ */
+HAL_BOOL
+ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue,
+       const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue)
+{
+       const DATA_PER_CHANNEL *pChannelData;
+       const uint16_t *pPcdac;
+       uint16_t i, j;
+
+       pChannelData = pSrcStruct->pDataPerChannel;
+       for (i = 0; i < pSrcStruct->numChannels; i++ ) {
+               if (pChannelData->channelValue == channel) {
+                       pPcdac = pChannelData->PcdacValues;
+                       for (j = 0; j < pChannelData->numPcdacValues; j++ ) {
+                               if (*pPcdac == pcdacValue) {
+                                       *powerValue = pChannelData->PwrValues[j];
+                                       return AH_TRUE;
+                               }
+                               pPcdac++;
+                       }
+               }
+               pChannelData++;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+uint16_t
+ar5211GetInterpolatedValue(uint16_t target,
+       uint16_t srcLeft, uint16_t srcRight,
+       uint16_t targetLeft, uint16_t targetRight,
+       HAL_BOOL scaleUp)
+{
+       uint16_t rv;
+       int16_t lRatio;
+       uint16_t scaleValue = EEP_SCALE;
+
+       /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */
+       if ((targetLeft * targetRight) == 0)
+               return 0;
+       if (scaleUp)
+               scaleValue = 1;
+
+       if (srcRight != srcLeft) {
+               /*
+                * Note the ratio always need to be scaled,
+                * since it will be a fraction.
+                */
+               lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft);
+               if (lRatio < 0) {
+                   /* Return as Left target if value would be negative */
+                   rv = targetLeft * (scaleUp ? EEP_SCALE : 1);
+               } else if (lRatio > EEP_SCALE) {
+                   /* Return as Right target if Ratio is greater than 100% (SCALE) */
+                   rv = targetRight * (scaleUp ? EEP_SCALE : 1);
+               } else {
+                       rv = (lRatio * targetRight + (EEP_SCALE - lRatio) *
+                                       targetLeft) / scaleValue;
+               }
+       } else {
+               rv = targetLeft;
+               if (scaleUp)
+                       rv *= EEP_SCALE;
+       }
+       return rv;
+}
+
+/*
+ *  Look for value being within 0.1 of the search values
+ *  however, NDIS can't do float calculations, so multiply everything
+ *  up by EEP_SCALE so can do integer arithmatic
+ *
+ * INPUT  value           -value to search for
+ * INPUT  pList           -ptr to the list to search
+ * INPUT  listSize     -number of entries in list
+ * OUTPUT pLowerValue -return the lower value
+ * OUTPUT pUpperValue -return the upper value
+ */
+void
+ar5211GetLowerUpperValues(uint16_t value,
+       const uint16_t *pList, uint16_t listSize,
+       uint16_t *pLowerValue, uint16_t *pUpperValue)
+{
+       const uint16_t listEndValue = *(pList + listSize - 1);
+       uint32_t target = value * EEP_SCALE;
+       int i;
+
+       /*
+        * See if value is lower than the first value in the list
+        * if so return first value
+        */
+       if (target < (uint32_t)(*pList * EEP_SCALE - EEP_DELTA)) {
+               *pLowerValue = *pList;
+               *pUpperValue = *pList;
+               return;
+       }
+
+       /*
+        * See if value is greater than last value in list
+        * if so return last value
+        */
+       if (target > (uint32_t)(listEndValue * EEP_SCALE + EEP_DELTA)) {
+               *pLowerValue = listEndValue;
+               *pUpperValue = listEndValue;
+               return;
+       }
+
+       /* look for value being near or between 2 values in list */
+       for (i = 0; i < listSize; i++) {
+               /*
+                * If value is close to the current value of the list
+                * then target is not between values, it is one of the values
+                */
+               if (abs(pList[i] * EEP_SCALE - (int32_t) target) < EEP_DELTA) {
+                       *pLowerValue = pList[i];
+                       *pUpperValue = pList[i];
+                       return;
+               }
+
+               /*
+                * Look for value being between current value and next value
+                * if so return these 2 values
+                */
+               if (target < (uint32_t)(pList[i + 1] * EEP_SCALE - EEP_DELTA)) {
+                       *pLowerValue = pList[i];
+                       *pUpperValue = pList[i + 1];
+                       return;
+               }
+       }
+}
+
+/*
+ * Get the upper and lower pcdac given the channel and the pcdac
+ * used in the search
+ */
+void
+ar5211GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel,
+       const PCDACS_EEPROM *pSrcStruct,
+       uint16_t *pLowerPcdac, uint16_t *pUpperPcdac)
+{
+       const DATA_PER_CHANNEL *pChannelData;
+       int i;
+
+       /* Find the channel information */
+       pChannelData = pSrcStruct->pDataPerChannel;
+       for (i = 0; i < pSrcStruct->numChannels; i++) {
+               if (pChannelData->channelValue == channel)
+                       break;
+               pChannelData++;
+       }
+       ar5211GetLowerUpperValues(pcdac, pChannelData->PcdacValues,
+               pChannelData->numPcdacValues, pLowerPcdac, pUpperPcdac);
+}
+
+#define        DYN_ADJ_UP_MARGIN       15
+#define        DYN_ADJ_LO_MARGIN       20
+
+static const GAIN_OPTIMIZATION_LADDER gainLadder = {
+       9,                                      /* numStepsInLadder */
+       4,                                      /* defaultStepNum */
+       { { {4, 1, 1, 1},  6, "FG8"},
+         { {4, 0, 1, 1},  4, "FG7"},
+         { {3, 1, 1, 1},  3, "FG6"},
+         { {4, 0, 0, 1},  1, "FG5"},
+         { {4, 1, 1, 0},  0, "FG4"},   /* noJack */
+         { {4, 0, 1, 0}, -2, "FG3"},   /* halfJack */
+         { {3, 1, 1, 0}, -3, "FG2"},   /* clip3 */
+         { {4, 0, 0, 0}, -4, "FG1"},   /* noJack */
+         { {2, 1, 1, 0}, -6, "FG0"}    /* clip2 */
+       }
+};
+
+/*
+ * Initialize the gain structure to good values
+ */
+void
+ar5211InitializeGainValues(struct ath_hal *ah)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       GAIN_VALUES *gv = &ahp->ah_gainValues;
+
+       /* initialize gain optimization values */
+       gv->currStepNum = gainLadder.defaultStepNum;
+       gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum];
+       gv->active = AH_TRUE;
+       gv->loTrig = 20;
+       gv->hiTrig = 35;
+}
+
+static HAL_BOOL
+ar5211InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv)
+{
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       uint32_t gStep, g;
+       uint32_t L1, L2, L3, L4;
+
+       if (IS_CHAN_CCK(chan)) {
+               gStep = 0x18;
+               L1 = 0;
+               L2 = gStep + 4;
+               L3 = 0x40;
+               L4 = L3 + 50;
+
+               gv->loTrig = L1;
+               gv->hiTrig = L4+5;
+       } else {
+               gStep = 0x3f;
+               L1 = 0;
+               L2 = 50;
+               L3 = L1;
+               L4 = L3 + 50;
+
+               gv->loTrig = L1 + DYN_ADJ_LO_MARGIN;
+               gv->hiTrig = L4 - DYN_ADJ_UP_MARGIN;
+       }
+       g = gv->currGain;
+
+       return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4));
+}
+
+/*
+ * Enable the probe gain check on the next packet
+ */
+static void
+ar5211RequestRfgain(struct ath_hal *ah)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       /* Enable the gain readback probe */
+       OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE,
+                 SM(ahp->ah_tx6PowerInHalfDbm, AR_PHY_PAPD_PROBE_POWERTX)
+               | AR_PHY_PAPD_PROBE_NEXT_TX);
+
+       ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED;
+}
+
+/*
+ * Exported call to check for a recent gain reading and return
+ * the current state of the thermal calibration gain engine.
+ */
+HAL_RFGAIN
+ar5211GetRfgain(struct ath_hal *ah)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       GAIN_VALUES *gv = &ahp->ah_gainValues;
+       uint32_t rddata;
+
+       if (!gv->active)
+               return HAL_RFGAIN_INACTIVE;
+
+       if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) {
+               /* Caller had asked to setup a new reading. Check it. */
+               rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE);
+
+               if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) {
+                       /* bit got cleared, we have a new reading. */
+                       gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S;
+                       /* inactive by default */
+                       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+
+                       if (!ar5211InvalidGainReadback(ah, gv) &&
+                           ar5211IsGainAdjustNeeded(ah, gv) &&
+                           ar5211AdjustGain(ah, gv) > 0) {
+                               /*
+                                * Change needed. Copy ladder info
+                                * into eeprom info.
+                                */
+                               ar5211SetRfgain(ah, gv);
+                               ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE;
+                       }
+               }
+       }
+       return ahp->ah_rfgainState;
+}
+
+/*
+ * Check to see if our readback gain level sits within the linear
+ * region of our current variable attenuation window
+ */
+static HAL_BOOL
+ar5211IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv)
+{
+       return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig);
+}
+
+/*
+ * Move the rabbit ears in the correct direction.
+ */
+static int32_t
+ar5211AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv)
+{
+       /* return > 0 for valid adjustments. */
+       if (!gv->active)
+               return -1;
+
+       gv->currStep = &gainLadder.optStep[gv->currStepNum];
+       if (gv->currGain >= gv->hiTrig) {
+               if (gv->currStepNum == 0) {
+                       HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                           "%s: Max gain limit.\n", __func__);
+                       return -1;
+               }
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                   "%s: Adding gain: currG=%d [%s] --> ",
+                   __func__, gv->currGain, gv->currStep->stepName);
+               gv->targetGain = gv->currGain;
+               while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) {
+                       gv->targetGain -= 2 * (gainLadder.optStep[--(gv->currStepNum)].stepGain -
+                               gv->currStep->stepGain);
+                       gv->currStep = &gainLadder.optStep[gv->currStepNum];
+               }
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
+                   gv->targetGain, gv->currStep->stepName);
+               return 1;
+       }
+       if (gv->currGain <= gv->loTrig) {
+               if (gv->currStepNum == gainLadder.numStepsInLadder-1) {
+                       HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                           "%s: Min gain limit.\n", __func__);
+                       return -2;
+               }
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                   "%s: Deducting gain: currG=%d [%s] --> ",
+                   __func__, gv->currGain, gv->currStep->stepName);
+               gv->targetGain = gv->currGain;
+               while (gv->targetGain <= gv->loTrig &&
+                     gv->currStepNum < (gainLadder.numStepsInLadder - 1)) {
+                       gv->targetGain -= 2 *
+                               (gainLadder.optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain);
+                       gv->currStep = &gainLadder.optStep[gv->currStepNum];
+               }
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
+                   gv->targetGain, gv->currStep->stepName);
+               return 2;
+       }
+       return 0;               /* caller didn't call needAdjGain first */
+}
+
+/*
+ * Adjust the 5GHz EEPROM information with the desired calibration values.
+ */
+static void
+ar5211SetRfgain(struct ath_hal *ah, const GAIN_VALUES *gv)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       if (!gv->active)
+               return;
+       ee->ee_cornerCal.clip = gv->currStep->paramVal[0]; /* bb_tx_clip */
+       ee->ee_cornerCal.pd90 = gv->currStep->paramVal[1]; /* rf_pwd_90 */
+       ee->ee_cornerCal.pd84 = gv->currStep->paramVal[2]; /* rf_pwd_84 */
+       ee->ee_cornerCal.gSel = gv->currStep->paramVal[3]; /* rf_rfgainsel */
+}
+
+static void
+ar5211SetOperatingMode(struct ath_hal *ah, int opmode)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       uint32_t val;
+
+       val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff;
+       switch (opmode) {
+       case HAL_M_HOSTAP:
+               OS_REG_WRITE(ah, AR_STA_ID1, val
+                       | AR_STA_ID1_STA_AP
+                       | AR_STA_ID1_RTS_USE_DEF
+                       | ahp->ah_staId1Defaults);
+               break;
+       case HAL_M_IBSS:
+               OS_REG_WRITE(ah, AR_STA_ID1, val
+                       | AR_STA_ID1_ADHOC
+                       | AR_STA_ID1_DESC_ANTENNA
+                       | ahp->ah_staId1Defaults);
+               break;
+       case HAL_M_STA:
+       case HAL_M_MONITOR:
+               OS_REG_WRITE(ah, AR_STA_ID1, val
+                       | AR_STA_ID1_DEFAULT_ANTENNA
+                       | ahp->ah_staId1Defaults);
+               break;
+       }
+}
+
+void
+ar5211SetPCUConfig(struct ath_hal *ah)
+{
+       ar5211SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211_xmit.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211_xmit.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+
+#include "ar5211/ar5211.h"
+#include "ar5211/ar5211reg.h"
+#include "ar5211/ar5211desc.h"
+
+/*
+ * Update Tx FIFO trigger level.
+ *
+ * Set bIncTrigLevel to TRUE to increase the trigger level.
+ * Set bIncTrigLevel to FALSE to decrease the trigger level.
+ *
+ * Returns TRUE if the trigger level was updated
+ */
+HAL_BOOL
+ar5211UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel)
+{
+       uint32_t curTrigLevel, txcfg;
+       HAL_INT ints = ar5211GetInterrupts(ah);
+
+       /*
+        * Disable chip interrupts. This is because halUpdateTxTrigLevel
+        * is called from both ISR and non-ISR contexts.
+        */
+       ar5211SetInterrupts(ah, ints &~ HAL_INT_GLOBAL);
+       txcfg = OS_REG_READ(ah, AR_TXCFG);
+       curTrigLevel = (txcfg & AR_TXCFG_FTRIG_M) >> AR_TXCFG_FTRIG_S;
+       if (bIncTrigLevel){
+               /* increase the trigger level */
+               curTrigLevel = curTrigLevel +
+                       ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2);
+       } else {
+               /* decrease the trigger level if not already at the minimum */
+               if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) {
+                       /* decrease the trigger level */
+                       curTrigLevel--;
+               } else {
+                       /* no update to the trigger level */
+                       /* re-enable chip interrupts */
+                       ar5211SetInterrupts(ah, ints);
+                       return AH_FALSE;
+               }
+       }
+       /* Update the trigger level */
+       OS_REG_WRITE(ah, AR_TXCFG, (txcfg &~ AR_TXCFG_FTRIG_M) |
+               ((curTrigLevel << AR_TXCFG_FTRIG_S) & AR_TXCFG_FTRIG_M));
+       /* re-enable chip interrupts */
+       ar5211SetInterrupts(ah, ints);
+       return AH_TRUE;
+}
+
+/*
+ * Set the properties of the tx queue with the parameters
+ * from qInfo.  The queue must previously have been setup
+ * with a call to ar5211SetupTxQueue.
+ */
+HAL_BOOL
+ar5211SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       if (q >= HAL_NUM_TX_QUEUES) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo);
+}
+
+/*
+ * Return the properties for the specified tx queue.
+ */
+HAL_BOOL
+ar5211GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       if (q >= HAL_NUM_TX_QUEUES) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]);
+}
+
+/*
+ * Allocate and initialize a tx DCU/QCU combination.
+ */
+int
+ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
+       const HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       HAL_TX_QUEUE_INFO *qi;
+       int q;
+
+       switch (type) {
+       case HAL_TX_QUEUE_BEACON:
+               q = 9;
+               break;
+       case HAL_TX_QUEUE_CAB:
+               q = 8;
+               break;
+       case HAL_TX_QUEUE_DATA:
+               q = 0;
+               if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE)
+                       return q;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n",
+                   __func__, type);
+               return -1;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
+
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n",
+                   __func__, q);
+               return -1;
+       }
+       OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO));
+       qi->tqi_type = type;
+       if (qInfo == AH_NULL) {
+               /* by default enable OK+ERR+DESC+URN interrupts */
+               qi->tqi_qflags =
+                         HAL_TXQ_TXOKINT_ENABLE
+                       | HAL_TXQ_TXERRINT_ENABLE
+                       | HAL_TXQ_TXDESCINT_ENABLE
+                       | HAL_TXQ_TXURNINT_ENABLE
+                       ;
+               qi->tqi_aifs = INIT_AIFS;
+               qi->tqi_cwmin = HAL_TXQ_USEDEFAULT;     /* NB: do at reset */
+               qi->tqi_cwmax = INIT_CWMAX;
+               qi->tqi_shretry = INIT_SH_RETRY;
+               qi->tqi_lgretry = INIT_LG_RETRY;
+       } else
+               (void) ar5211SetTxQueueProps(ah, q, qInfo);
+       return q;
+}
+
+/*
+ * Update the h/w interrupt registers to reflect a tx q's configuration.
+ */
+static void
+setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
+           "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__
+               , ahp->ah_txOkInterruptMask
+               , ahp->ah_txErrInterruptMask
+               , ahp->ah_txDescInterruptMask
+               , ahp->ah_txEolInterruptMask
+               , ahp->ah_txUrnInterruptMask
+       );
+
+       OS_REG_WRITE(ah, AR_IMR_S0,
+                 SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
+               | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC)
+       );
+       OS_REG_WRITE(ah, AR_IMR_S1,
+                 SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
+               | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL)
+       );
+       OS_REG_RMW_FIELD(ah, AR_IMR_S2,
+               AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
+}
+
+
+/*
+ * Free a tx DCU/QCU combination.
+ */
+HAL_BOOL
+ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       HAL_TX_QUEUE_INFO *qi;
+
+       if (q >= HAL_NUM_TX_QUEUES) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q);
+
+       qi->tqi_type = HAL_TX_QUEUE_INACTIVE;
+       ahp->ah_txOkInterruptMask &= ~(1 << q);
+       ahp->ah_txErrInterruptMask &= ~(1 << q);
+       ahp->ah_txDescInterruptMask &= ~(1 << q);
+       ahp->ah_txEolInterruptMask &= ~(1 << q);
+       ahp->ah_txUrnInterruptMask &= ~(1 << q);
+       setTxQInterrupts(ah, qi);
+
+       return AH_TRUE;
+}
+
+/*
+ * Set the retry, aifs, cwmin/max, readyTime regs for specified queue
+ */
+HAL_BOOL
+ar5211ResetTxQueue(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5211 *ahp = AH5211(ah);
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       HAL_TX_QUEUE_INFO *qi;
+       uint32_t cwMin, chanCwMin, value;
+
+       if (q >= HAL_NUM_TX_QUEUES) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
+                   __func__, q);
+               return AH_TRUE;         /* XXX??? */
+       }
+
+       if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) {
+               /*
+                * Select cwmin according to channel type.
+                * NB: chan can be NULL during attach
+                */
+               if (chan && IS_CHAN_B(chan))
+                       chanCwMin = INIT_CWMIN_11B;
+               else
+                       chanCwMin = INIT_CWMIN;
+               /* make sure that the CWmin is of the form (2^n - 1) */
+               for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1)
+                       ;
+       } else
+               cwMin = qi->tqi_cwmin;
+
+       /* set cwMin/Max and AIFS values */
+       OS_REG_WRITE(ah, AR_DLCL_IFS(q),
+                 SM(cwMin, AR_D_LCL_IFS_CWMIN)
+               | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
+               | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+
+       /* Set retry limit values */
+       OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q),
+                  SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
+                | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
+                | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG)
+                | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)
+       );
+
+       /* enable early termination on the QCU */
+       OS_REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
+
+       if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
+               /* Configure DCU to use the global sequence count */
+               OS_REG_WRITE(ah, AR_DMISC(q), AR5311_D_MISC_SEQ_NUM_CONTROL);
+       }
+       /* multiqueue support */
+       if (qi->tqi_cbrPeriod) {
+               OS_REG_WRITE(ah, AR_QCBRCFG(q),
+                         SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL)
+                       | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH));
+               OS_REG_WRITE(ah, AR_QMISC(q),
+                       OS_REG_READ(ah, AR_QMISC(q)) |
+                       AR_Q_MISC_FSP_CBR |
+                       (qi->tqi_cbrOverflowLimit ?
+                               AR_Q_MISC_CBR_EXP_CNTR_LIMIT : 0));
+       }
+       if (qi->tqi_readyTime) {
+               OS_REG_WRITE(ah, AR_QRDYTIMECFG(q),
+                       SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) |
+                       AR_Q_RDYTIMECFG_EN);
+       }
+       if (qi->tqi_burstTime) {
+               OS_REG_WRITE(ah, AR_DCHNTIME(q),
+                       SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
+                       AR_D_CHNTIME_EN);
+               if (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE) {
+                       OS_REG_WRITE(ah, AR_QMISC(q),
+                            OS_REG_READ(ah, AR_QMISC(q)) |
+                            AR_Q_MISC_RDYTIME_EXP_POLICY);
+               }
+       }
+
+       if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) {
+               OS_REG_WRITE(ah, AR_DMISC(q),
+                       OS_REG_READ(ah, AR_DMISC(q)) |
+                       AR_D_MISC_POST_FR_BKOFF_DIS);
+       }
+       if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) {
+               OS_REG_WRITE(ah, AR_DMISC(q),
+                       OS_REG_READ(ah, AR_DMISC(q)) |
+                       AR_D_MISC_FRAG_BKOFF_EN);
+       }
+       switch (qi->tqi_type) {
+       case HAL_TX_QUEUE_BEACON:
+               /* Configure QCU for beacons */
+               OS_REG_WRITE(ah, AR_QMISC(q),
+                       OS_REG_READ(ah, AR_QMISC(q))
+                       | AR_Q_MISC_FSP_DBA_GATED
+                       | AR_Q_MISC_BEACON_USE
+                       | AR_Q_MISC_CBR_INCR_DIS1);
+               /* Configure DCU for beacons */
+               value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
+                       | AR_D_MISC_BEACON_USE | AR_D_MISC_POST_FR_BKOFF_DIS;
+               if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU)
+                       value |= AR5311_D_MISC_SEQ_NUM_CONTROL;
+               OS_REG_WRITE(ah, AR_DMISC(q), value);
+               break;
+       case HAL_TX_QUEUE_CAB:
+               /* Configure QCU for CAB (Crap After Beacon) frames */
+               OS_REG_WRITE(ah, AR_QMISC(q),
+                       OS_REG_READ(ah, AR_QMISC(q))
+                       | AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_CBR_INCR_DIS1
+                       | AR_Q_MISC_CBR_INCR_DIS0 | AR_Q_MISC_RDYTIME_EXP_POLICY);
+
+               value = (ahp->ah_beaconInterval
+                       - (ath_hal_sw_beacon_response_time - ath_hal_dma_beacon_response_time)
+                       - ath_hal_additional_swba_backoff) * 1024;
+               OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN);
+
+               /* Configure DCU for CAB */
+               value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S);
+               if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU)
+                       value |= AR5311_D_MISC_SEQ_NUM_CONTROL;
+               OS_REG_WRITE(ah, AR_QMISC(q), value);
+               break;
+       default:
+               /* NB: silence compiler */
+               break;
+       }
+
+       /*
+        * Always update the secondary interrupt mask registers - this
+        * could be a new queue getting enabled in a running system or
+        * hw getting re-initialized during a reset!
+        *
+        * Since we don't differentiate between tx interrupts corresponding
+        * to individual queues - secondary tx mask regs are always unmasked;
+        * tx interrupts are enabled/disabled for all queues collectively
+        * using the primary mask reg
+        */
+       if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE)
+               ahp->ah_txOkInterruptMask |= 1 << q;
+       else
+               ahp->ah_txOkInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE)
+               ahp->ah_txErrInterruptMask |= 1 << q;
+       else
+               ahp->ah_txErrInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE)
+               ahp->ah_txDescInterruptMask |= 1 << q;
+       else
+               ahp->ah_txDescInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE)
+               ahp->ah_txEolInterruptMask |= 1 << q;
+       else
+               ahp->ah_txEolInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE)
+               ahp->ah_txUrnInterruptMask |= 1 << q;
+       else
+               ahp->ah_txUrnInterruptMask &= ~(1 << q);
+       setTxQInterrupts(ah, qi);
+
+       return AH_TRUE;
+}
+
+/*
+ * Get the TXDP for the specified data queue.
+ */
+uint32_t
+ar5211GetTxDP(struct ath_hal *ah, u_int q)
+{
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+       return OS_REG_READ(ah, AR_QTXDP(q));
+}
+
+/*
+ * Set the TxDP for the specified tx queue.
+ */
+HAL_BOOL
+ar5211SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp)
+{
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+       HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       /*
+        * Make sure that TXE is deasserted before setting the TXDP.  If TXE
+        * is still asserted, setting TXDP will have no effect.
+        */
+       HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0);
+
+       OS_REG_WRITE(ah, AR_QTXDP(q), txdp);
+
+       return AH_TRUE;
+}
+
+/*
+ * Set Transmit Enable bits for the specified queues.
+ */
+HAL_BOOL
+ar5211StartTxDma(struct ath_hal *ah, u_int q)
+{
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+       HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       /* Check that queue is not already active */
+       HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1<<q)) == 0);
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
+
+       /* Check to be sure we're not enabling a q that has its TXD bit set. */
+       HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1 << q)) == 0);
+
+       OS_REG_WRITE(ah, AR_Q_TXE, 1 << q);
+       return AH_TRUE;
+}
+
+/*
+ * Return the number of frames pending on the specified queue.
+ */
+uint32_t
+ar5211NumTxPending(struct ath_hal *ah, u_int q)
+{
+       uint32_t n;
+
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+       HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       n = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT_M;
+       /*
+        * Pending frame count (PFC) can momentarily go to zero
+        * while TXE remains asserted.  In other words a PFC of
+        * zero is not sufficient to say that the queue has stopped.
+        */
+       if (n == 0 && (OS_REG_READ(ah, AR_Q_TXE) & (1<<q)))
+               n = 1;                  /* arbitrarily pick 1 */
+       return n;
+}
+
+/*
+ * Stop transmit on the specified queue
+ */
+HAL_BOOL
+ar5211StopTxDma(struct ath_hal *ah, u_int q)
+{
+       int i;
+
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+       HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       OS_REG_WRITE(ah, AR_Q_TXD, 1<<q);
+       for (i = 0; i < 10000; i++) {
+               if (ar5211NumTxPending(ah, q) == 0)
+                       break;
+               OS_DELAY(10);
+       }
+       OS_REG_WRITE(ah, AR_Q_TXD, 0);
+
+       return (i < 10000);
+}
+
+/*
+ * Descriptor Access Functions
+ */
+
+#define        VALID_PKT_TYPES \
+       ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\
+        (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\
+        (1<<HAL_PKT_TYPE_BEACON))
+#define        isValidPktType(_t)      ((1<<(_t)) & VALID_PKT_TYPES)
+#define        VALID_TX_RATES \
+       ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\
+        (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\
+        (1<<0x1d)|(1<<0x18)|(1<<0x1c))
+#define        isValidTxRate(_r)       ((1<<(_r)) & VALID_TX_RATES)
+
+HAL_BOOL
+ar5211SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int pktLen,
+       u_int hdrLen,
+       HAL_PKT_TYPE type,
+       u_int txPower,
+       u_int txRate0, u_int txTries0,
+       u_int keyIx,
+       u_int antMode,
+       u_int flags,
+       u_int rtsctsRate,
+       u_int rtsctsDuration,
+       u_int compicvLen,
+       u_int compivLen,
+       u_int comp)
+{
+       struct ar5211_desc *ads = AR5211DESC(ds);
+
+       (void) hdrLen;
+       (void) txPower;
+       (void) rtsctsRate; (void) rtsctsDuration;
+
+       HALASSERT(txTries0 != 0);
+       HALASSERT(isValidPktType(type));
+       HALASSERT(isValidTxRate(txRate0));
+       /* XXX validate antMode */
+
+       ads->ds_ctl0 = (pktLen & AR_FrameLen)
+                    | (txRate0 << AR_XmitRate_S)
+                    | (antMode << AR_AntModeXmit_S)
+                    | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0)
+                    | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0)
+                    | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0)
+                    | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
+                    ;
+       ads->ds_ctl1 = (type << 26)
+                    | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0)
+                    ;
+
+       if (keyIx != HAL_TXKEYIX_INVALID) {
+               ads->ds_ctl1 |=
+                       (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx;
+               ads->ds_ctl0 |= AR_EncryptKeyValid;
+       }
+       return AH_TRUE;
+#undef RATE
+}
+
+HAL_BOOL
+ar5211SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int txRate1, u_int txTries1,
+       u_int txRate2, u_int txTries2,
+       u_int txRate3, u_int txTries3)
+{
+       (void) ah; (void) ds;
+       (void) txRate1; (void) txTries1;
+       (void) txRate2; (void) txTries2;
+       (void) txRate3; (void) txTries3;
+       return AH_FALSE;
+}
+
+void
+ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+       struct ar5211_desc *ads = AR5211DESC(ds);
+
+       ads->ds_ctl0 |= AR_TxInterReq;
+}
+
+HAL_BOOL
+ar5211FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+       const struct ath_desc *ds0)
+{
+       struct ar5211_desc *ads = AR5211DESC(ds);
+
+       HALASSERT((segLen &~ AR_BufLen) == 0);
+
+       if (firstSeg) {
+               /*
+                * First descriptor, don't clobber xmit control data
+                * setup by ar5211SetupTxDesc.
+                */
+               ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More);
+       } else if (lastSeg) {           /* !firstSeg && lastSeg */
+               /*
+                * Last descriptor in a multi-descriptor frame,
+                * copy the transmit parameters from the first
+                * frame for processing on completion.
+                */
+               ads->ds_ctl0 = AR5211DESC_CONST(ds0)->ds_ctl0;
+               ads->ds_ctl1 = segLen;
+       } else {                        /* !firstSeg && !lastSeg */
+               /*
+                * Intermediate descriptor in a multi-descriptor frame.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 = segLen | AR_More;
+       }
+       ads->ds_status0 = ads->ds_status1 = 0;
+       return AH_TRUE;
+}
+
+/*
+ * Processing of HW TX descriptor.
+ */
+HAL_STATUS
+ar5211ProcTxDesc(struct ath_hal *ah,
+       struct ath_desc *ds, struct ath_tx_status *ts)
+{
+       struct ar5211_desc *ads = AR5211DESC(ds);
+
+       if ((ads->ds_status1 & AR_Done) == 0)
+               return HAL_EINPROGRESS;
+
+       /* Update software copies of the HW status */
+       ts->ts_seqnum = MS(ads->ds_status1, AR_SeqNum);
+       ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp);
+       ts->ts_status = 0;
+       if ((ads->ds_status0 & AR_FrmXmitOK) == 0) {
+               if (ads->ds_status0 & AR_ExcessiveRetries)
+                       ts->ts_status |= HAL_TXERR_XRETRY;
+               if (ads->ds_status0 & AR_Filtered)
+                       ts->ts_status |= HAL_TXERR_FILT;
+               if (ads->ds_status0 & AR_FIFOUnderrun)
+                       ts->ts_status |= HAL_TXERR_FIFO;
+       }
+       ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate);
+       ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength);
+       ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt);
+       ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt);
+       ts->ts_virtcol = MS(ads->ds_status0, AR_VirtCollCnt);
+       ts->ts_antenna = 0;             /* NB: don't know */
+       ts->ts_finaltsi = 0;
+       /*
+        * NB: the number of retries is one less than it should be.
+        * Also, 0 retries and 1 retry are both reported as 0 retries.
+        */
+       if (ts->ts_shortretry > 0)
+               ts->ts_shortretry++;
+       if (ts->ts_longretry > 0)
+               ts->ts_longretry++;
+
+       return HAL_OK;
+}
+
+/*
+ * Determine which tx queues need interrupt servicing.
+ * STUB.
+ */
+void
+ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs)
+{
+       return;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211desc.h       2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211desc.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5211DESC_H
+#define _DEV_ATH_AR5211DESC_H
+
+#include "ah_desc.h"
+
+/*
+ * Defintions for the DMA descriptors used by the Atheros
+ * AR5211 and AR5110 Wireless Lan controller parts.
+ */
+
+/* DMA descriptors */
+struct ar5211_desc {
+       uint32_t        ds_link;        /* link pointer */
+       uint32_t        ds_data;        /* data buffer pointer */
+       uint32_t        ds_ctl0;        /* DMA control 0 */
+       uint32_t        ds_ctl1;        /* DMA control 1 */
+       uint32_t        ds_status0;     /* DMA status 0 */
+       uint32_t        ds_status1;     /* DMA status 1 */
+} __packed;
+#define        AR5211DESC(_ds) ((struct ar5211_desc *)(_ds))
+#define        AR5211DESC_CONST(_ds)   ((const struct ar5211_desc *)(_ds))
+
+/* TX ds_ctl0 */
+#define        AR_FrameLen             0x00000fff      /* frame length */
+/* bits 12-17 are reserved */
+#define        AR_XmitRate             0x003c0000      /* txrate */
+#define        AR_XmitRate_S           18
+#define        AR_RTSCTSEnable         0x00400000      /* RTS/CTS enable */
+#define        AR_VEOL                 0x00800000      /* virtual end-of-list */
+#define        AR_ClearDestMask        0x01000000      /* Clear destination mask bit */
+#define        AR_AntModeXmit          0x1e000000      /* TX antenna seslection */
+#define        AR_AntModeXmit_S        25
+#define        AR_TxInterReq           0x20000000      /* TX interrupt request */
+#define        AR_EncryptKeyValid      0x40000000      /* EncryptKeyIdx is valid */
+/* bit 31 is reserved */
+
+/* TX ds_ctl1 */
+#define        AR_BufLen               0x00000fff      /* data buffer length */
+#define        AR_More                 0x00001000      /* more desc in this frame */
+#define        AR_EncryptKeyIdx        0x000fe000      /* ecnrypt key table index */
+#define        AR_EncryptKeyIdx_S      13
+#define        AR_FrmType              0x00700000      /* frame type indication */
+#define        AR_FrmType_S            20
+#define        AR_Frm_Normal           0x00000000      /* normal frame */
+#define        AR_Frm_ATIM             0x00100000      /* ATIM frame */
+#define        AR_Frm_PSPOLL           0x00200000      /* PS poll frame */
+#define        AR_Frm_Beacon           0x00300000      /* Beacon frame */
+#define        AR_Frm_ProbeResp        0x00400000      /* no delay data */
+#define        AR_NoAck                0x00800000      /* No ACK flag */
+/* bits 24-31 are reserved */
+
+/* RX ds_ctl1 */
+/*     AR_BufLen               0x00000fff         data buffer length */
+/* bit 12 is reserved */
+#define        AR_RxInterReq           0x00002000      /* RX interrupt request */
+/* bits 14-31 are reserved */
+
+/* TX ds_status0 */
+#define        AR_FrmXmitOK            0x00000001      /* TX success */
+#define        AR_ExcessiveRetries     0x00000002      /* excessive retries */
+#define        AR_FIFOUnderrun         0x00000004      /* TX FIFO underrun */
+#define        AR_Filtered             0x00000008      /* TX filter indication */
+/* NB: the spec has the Short+Long retry counts reversed */
+#define        AR_LongRetryCnt         0x000000f0      /* long retry count */
+#define        AR_LongRetryCnt_S       4
+#define        AR_ShortRetryCnt        0x00000f00      /* short retry count */
+#define        AR_ShortRetryCnt_S      8
+#define        AR_VirtCollCnt          0x0000f000      /* virtual collision count */
+#define        AR_VirtCollCnt_S        12
+#define        AR_SendTimestamp        0xffff0000      /* TX timestamp */
+#define        AR_SendTimestamp_S      16
+
+/* RX ds_status0 */
+#define        AR_DataLen              0x00000fff      /* RX data length */
+/*     AR_More                 0x00001000         more desc in this frame */
+/* bits 13-14 are reserved */
+#define        AR_RcvRate              0x00078000      /* reception rate */
+#define        AR_RcvRate_S            15
+#define        AR_RcvSigStrength       0x07f80000      /* receive signal strength */
+#define        AR_RcvSigStrength_S     19
+#define        AR_RcvAntenna           0x38000000      /* receive antenaa */
+#define        AR_RcvAntenna_S         27
+/* bits 30-31 are reserved */
+
+/* TX ds_status1 */
+#define        AR_Done                 0x00000001      /* descripter complete */
+#define        AR_SeqNum               0x00001ffe      /* TX sequence number */
+#define        AR_SeqNum_S             1
+#define        AR_AckSigStrength       0x001fe000      /* strength of ACK */
+#define        AR_AckSigStrength_S     13
+/* bits 21-31 are reserved */
+
+/* RX ds_status1 */
+/*     AR_Done                 0x00000001         descripter complete */
+#define        AR_FrmRcvOK             0x00000002      /* frame reception success */
+#define        AR_CRCErr               0x00000004      /* CRC error */
+/* bit 3 reserved */
+#define        AR_DecryptCRCErr        0x00000010      /* Decryption CRC fiailure */
+#define        AR_PHYErr               0x000000e0      /* PHY error */
+#define        AR_PHYErr_S             5
+#define        AR_PHYErr_Underrun      0x00000000      /* Transmit underrun */
+#define        AR_PHYErr_Tim           0x00000020      /* Timing error */
+#define        AR_PHYErr_Par           0x00000040      /* Parity error */
+#define        AR_PHYErr_Rate          0x00000060      /* Illegal rate */
+#define        AR_PHYErr_Len           0x00000080      /* Illegal length */
+#define        AR_PHYErr_Radar         0x000000a0      /* Radar detect */
+#define        AR_PHYErr_Srv           0x000000c0      /* Illegal service */
+#define        AR_PHYErr_TOR           0x000000e0      /* Transmit override receive */
+#define        AR_KeyIdxValid          0x00000100      /* decryption key index valid */
+#define        AR_KeyIdx               0x00007e00      /* Decryption key index */
+#define        AR_KeyIdx_S             9
+#define        AR_RcvTimestamp         0x0fff8000      /* timestamp */
+#define        AR_RcvTimestamp_S       15
+#define        AR_KeyCacheMiss         0x10000000      /* key cache miss indication */
+
+#endif /* _DEV_ATH_AR5211DESC_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211phy.h        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211phy.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5211PHY_H
+#define _DEV_ATH_AR5211PHY_H
+
+/*
+ * Definitions for the PHY on the Atheros AR5211/5311 chipset.
+ */
+
+/* PHY registers */
+#define        AR_PHY_BASE     0x9800  /* PHY registers base address */
+#define        AR_PHY(_n)      (AR_PHY_BASE + ((_n)<<2))
+
+#define        AR_PHY_TURBO    0x9804  /* PHY frame control register */
+#define        AR_PHY_FC_TURBO_MODE    0x00000001      /* Set turbo mode bits */
+#define        AR_PHY_FC_TURBO_SHORT   0x00000002      /* Set short symbols to turbo mode setting */
+
+#define        AR_PHY_CHIP_ID  0x9818  /* PHY chip revision ID */
+
+#define        AR_PHY_ACTIVE   0x981C  /* PHY activation register */
+#define        AR_PHY_ACTIVE_EN        0x00000001      /* Activate PHY chips */
+#define        AR_PHY_ACTIVE_DIS       0x00000000      /* Deactivate PHY chips */
+
+#define        AR_PHY_AGC_CONTROL      0x9860  /* PHY chip calibration and noise floor setting */
+#define        AR_PHY_AGC_CONTROL_CAL  0x00000001      /* Perform PHY chip internal calibration */
+#define        AR_PHY_AGC_CONTROL_NF   0x00000002      /* Perform PHY chip noise-floor calculation */
+
+#define        AR_PHY_PLL_CTL  0x987c  /* PLL control register */
+#define        AR_PHY_PLL_CTL_44       0x19    /* 44 MHz for 11b channels and FPGA */
+#define        AR_PHY_PLL_CTL_40       0x18    /* 40 MHz */
+#define        AR_PHY_PLL_CTL_20       0x13    /* 20 MHz half rate 11a for emulation */
+
+
+#define        AR_PHY_RX_DELAY 0x9914  /* PHY analog_power_on_time, in 100ns increments */
+#define        AR_PHY_RX_DELAY_M       0x00003FFF      /* Mask for delay from active assertion (wake up) */
+                               /* to enable_receiver */
+
+#define        AR_PHY_TIMING_CTRL4     0x9920  /* PHY */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_M   0x0000001F      /* Mask for kcos_theta-1 for q correction */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_M   0x000007E0      /* Mask for sin_theta for i correction */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5               /* Shift for sin_theta for i correction */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_ENABLE       0x00000800      /* enable IQ correction */
+#define        AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_M       0x0000F000      /* Mask for max number of samples (logarithmic) */
+#define        AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S       12              /* Shift for max number of samples */
+#define        AR_PHY_TIMING_CTRL4_DO_IQCAL    0x00010000      /* perform IQ calibration */
+
+#define        AR_PHY_PAPD_PROBE       0x9930
+#define        AR_PHY_PAPD_PROBE_POWERTX       0x00007E00
+#define        AR_PHY_PAPD_PROBE_POWERTX_S     9
+#define        AR_PHY_PAPD_PROBE_NEXT_TX       0x00008000      /* command to take next reading */
+#define        AR_PHY_PAPD_PROBE_GAINF 0xFE000000
+#define        AR_PHY_PAPD_PROBE_GAINF_S       25
+
+#define        AR_PHY_POWER_TX_RATE1           0x9934
+#define        AR_PHY_POWER_TX_RATE2           0x9938
+#define        AR_PHY_POWER_TX_RATE_MAX        0x993c
+
+#define        AR_PHY_FRAME_CTL        0x9944
+#define        AR_PHY_FRAME_CTL_TX_CLIP        0x00000038
+#define        AR_PHY_FRAME_CTL_TX_CLIP_S      3
+#define AR_PHY_FRAME_CTL_ERR_SERV      0x20000000
+#define AR_PHY_FRAME_CTL_ERR_SERV_S    29
+
+#define        AR_PHY_RADAR_0  0x9954  /* PHY radar detection settings */
+#define        AR_PHY_RADAR_0_ENA      0x00000001      /* Enable radar detection */
+
+#define        AR_PHY_IQCAL_RES_PWR_MEAS_I     0x9c10  /*PHY IQ calibration results - power measurement for I */
+#define        AR_PHY_IQCAL_RES_PWR_MEAS_Q     0x9c14  /*PHY IQ calibration results - power measurement for Q */
+#define        AR_PHY_IQCAL_RES_IQ_CORR_MEAS   0x9c18  /*PHY IQ calibration results - IQ correlation measurement */
+#define        AR_PHY_CURRENT_RSSI     0x9c1c  /* rssi of current frame being received */
+
+#define        AR5211_PHY_MODE 0xA200  /* Mode register */
+#define        AR5211_PHY_MODE_OFDM    0x0     /* bit 0 = 0 for OFDM */
+#define        AR5211_PHY_MODE_CCK     0x1     /* bit 0 = 1 for CCK */
+#define        AR5211_PHY_MODE_RF5GHZ  0x0     /* bit 1 = 0 for 5 GHz */
+#define        AR5211_PHY_MODE_RF2GHZ  0x2     /* bit 1 = 1 for 2.4 GHz */
+
+#endif /* _DEV_ATH_AR5211PHY_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/ar5211reg.h        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,853 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5211reg.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5211REG_H
+#define _DEV_ATH_AR5211REG_H
+
+/*
+ * Definitions for the Atheros AR5211/5311 chipset.
+ */
+
+/*
+ * Maui2/Spirit specific registers/fields are indicated by AR5311.
+ * Oahu specific registers/fields are indicated by AR5211.
+ */
+
+/* DMA Control and Interrupt Registers */
+#define        AR_CR           0x0008          /* control register */
+#define        AR_RXDP         0x000C          /* receive queue descriptor pointer */
+#define        AR_CFG          0x0014          /* configuration and status register */
+#define        AR_IER          0x0024          /* Interrupt enable register */
+#define        AR_RTSD0        0x0028          /* RTS Duration Parameters 0 */
+#define        AR_RTSD1        0x002c          /* RTS Duration Parameters 1 */
+#define        AR_TXCFG        0x0030          /* tx DMA size config register */
+#define        AR_RXCFG        0x0034          /* rx DMA size config register */
+#define        AR5211_JUMBO_LAST       0x0038  /* Jumbo descriptor last address */
+#define        AR_MIBC         0x0040          /* MIB control register */
+#define        AR_TOPS         0x0044          /* timeout prescale count */
+#define        AR_RXNPTO       0x0048          /* no frame received timeout */
+#define        AR_TXNPTO       0x004C          /* no frame trasmitted timeout */
+#define        AR_RFGTO        0x0050          /* receive frame gap timeout */
+#define        AR_RFCNT        0x0054          /* receive frame count limit */
+#define        AR_MACMISC      0x0058          /* miscellaneous control/status */
+#define        AR5311_QDCLKGATE        0x005c  /* QCU/DCU clock gating control */
+#define        AR_ISR          0x0080          /* Primary interrupt status register */
+#define        AR_ISR_S0       0x0084          /* Secondary interrupt status reg 0 */
+#define        AR_ISR_S1       0x0088          /* Secondary interrupt status reg 1 */
+#define        AR_ISR_S2       0x008c          /* Secondary interrupt status reg 2 */
+#define        AR_ISR_S3       0x0090          /* Secondary interrupt status reg 3 */
+#define        AR_ISR_S4       0x0094          /* Secondary interrupt status reg 4 */
+#define        AR_IMR          0x00a0          /* Primary interrupt mask register */
+#define        AR_IMR_S0       0x00a4          /* Secondary interrupt mask reg 0 */
+#define        AR_IMR_S1       0x00a8          /* Secondary interrupt mask reg 1 */
+#define        AR_IMR_S2       0x00ac          /* Secondary interrupt mask reg 2 */
+#define        AR_IMR_S3       0x00b0          /* Secondary interrupt mask reg 3 */
+#define        AR_IMR_S4       0x00b4          /* Secondary interrupt mask reg 4 */
+#define        AR_ISR_RAC      0x00c0          /* Primary interrupt status reg, */
+/* Shadow copies with read-and-clear access */
+#define        AR_ISR_S0_S     0x00c4          /* Secondary interrupt status reg 0 */
+#define        AR_ISR_S1_S     0x00c8          /* Secondary interrupt status reg 1 */
+#define        AR_ISR_S2_S     0x00cc          /* Secondary interrupt status reg 2 */
+#define        AR_ISR_S3_S     0x00d0          /* Secondary interrupt status reg 3 */
+#define        AR_ISR_S4_S     0x00d4          /* Secondary interrupt status reg 4 */
+
+#define        AR_Q0_TXDP      0x0800          /* Transmit Queue descriptor pointer */
+#define        AR_Q1_TXDP      0x0804          /* Transmit Queue descriptor pointer */
+#define        AR_Q2_TXDP      0x0808          /* Transmit Queue descriptor pointer */
+#define        AR_Q3_TXDP      0x080c          /* Transmit Queue descriptor pointer */
+#define        AR_Q4_TXDP      0x0810          /* Transmit Queue descriptor pointer */
+#define        AR_Q5_TXDP      0x0814          /* Transmit Queue descriptor pointer */
+#define        AR_Q6_TXDP      0x0818          /* Transmit Queue descriptor pointer */
+#define        AR_Q7_TXDP      0x081c          /* Transmit Queue descriptor pointer */
+#define        AR_Q8_TXDP      0x0820          /* Transmit Queue descriptor pointer */
+#define        AR_Q9_TXDP      0x0824          /* Transmit Queue descriptor pointer */
+#define        AR_QTXDP(i)     (AR_Q0_TXDP + ((i)<<2))
+
+#define        AR_Q_TXE        0x0840          /* Transmit Queue enable */
+#define        AR_Q_TXD        0x0880          /* Transmit Queue disable */
+
+#define        AR_Q0_CBRCFG    0x08c0          /* CBR configuration */
+#define        AR_Q1_CBRCFG    0x08c4          /* CBR configuration */
+#define        AR_Q2_CBRCFG    0x08c8          /* CBR configuration */
+#define        AR_Q3_CBRCFG    0x08cc          /* CBR configuration */
+#define        AR_Q4_CBRCFG    0x08d0          /* CBR configuration */
+#define        AR_Q5_CBRCFG    0x08d4          /* CBR configuration */
+#define        AR_Q6_CBRCFG    0x08d8          /* CBR configuration */
+#define        AR_Q7_CBRCFG    0x08dc          /* CBR configuration */
+#define        AR_Q8_CBRCFG    0x08e0          /* CBR configuration */
+#define        AR_Q9_CBRCFG    0x08e4          /* CBR configuration */
+#define        AR_QCBRCFG(i)   (AR_Q0_CBRCFG + ((i)<<2))
+
+#define        AR_Q0_RDYTIMECFG        0x0900  /* ReadyTime configuration */
+#define        AR_Q1_RDYTIMECFG        0x0904  /* ReadyTime configuration */
+#define        AR_Q2_RDYTIMECFG        0x0908  /* ReadyTime configuration */
+#define        AR_Q3_RDYTIMECFG        0x090c  /* ReadyTime configuration */
+#define        AR_Q4_RDYTIMECFG        0x0910  /* ReadyTime configuration */
+#define        AR_Q5_RDYTIMECFG        0x0914  /* ReadyTime configuration */
+#define        AR_Q6_RDYTIMECFG        0x0918  /* ReadyTime configuration */
+#define        AR_Q7_RDYTIMECFG        0x091c  /* ReadyTime configuration */
+#define        AR_Q8_RDYTIMECFG        0x0920  /* ReadyTime configuration */
+#define        AR_Q9_RDYTIMECFG        0x0924  /* ReadyTime configuration */
+#define        AR_QRDYTIMECFG(i)       (AR_Q0_RDYTIMECFG + ((i)<<2))
+
+#define        AR_Q_ONESHOTARM_SC      0x0940  /* OneShotArm set control */
+#define        AR_Q_ONESHOTARM_CC      0x0980  /* OneShotArm clear control */
+
+#define        AR_Q0_MISC      0x09c0          /* Miscellaneous QCU settings */
+#define        AR_Q1_MISC      0x09c4          /* Miscellaneous QCU settings */
+#define        AR_Q2_MISC      0x09c8          /* Miscellaneous QCU settings */
+#define        AR_Q3_MISC      0x09cc          /* Miscellaneous QCU settings */
+#define        AR_Q4_MISC      0x09d0          /* Miscellaneous QCU settings */
+#define        AR_Q5_MISC      0x09d4          /* Miscellaneous QCU settings */
+#define        AR_Q6_MISC      0x09d8          /* Miscellaneous QCU settings */
+#define        AR_Q7_MISC      0x09dc          /* Miscellaneous QCU settings */
+#define        AR_Q8_MISC      0x09e0          /* Miscellaneous QCU settings */
+#define        AR_Q9_MISC      0x09e4          /* Miscellaneous QCU settings */
+#define        AR_QMISC(i)     (AR_Q0_MISC + ((i)<<2))
+
+#define        AR_Q0_STS       0x0a00          /* Miscellaneous QCU status */
+#define        AR_Q1_STS       0x0a04          /* Miscellaneous QCU status */
+#define        AR_Q2_STS       0x0a08          /* Miscellaneous QCU status */
+#define        AR_Q3_STS       0x0a0c          /* Miscellaneous QCU status */
+#define        AR_Q4_STS       0x0a10          /* Miscellaneous QCU status */
+#define        AR_Q5_STS       0x0a14          /* Miscellaneous QCU status */
+#define        AR_Q6_STS       0x0a18          /* Miscellaneous QCU status */
+#define        AR_Q7_STS       0x0a1c          /* Miscellaneous QCU status */
+#define        AR_Q8_STS       0x0a20          /* Miscellaneous QCU status */
+#define        AR_Q9_STS       0x0a24          /* Miscellaneous QCU status */
+#define        AR_QSTS(i)      (AR_Q0_STS + ((i)<<2))
+
+#define        AR_Q_RDYTIMESHDN        0x0a40  /* ReadyTimeShutdown status */
+#define        AR_D0_QCUMASK   0x1000          /* QCU Mask */
+#define        AR_D1_QCUMASK   0x1004          /* QCU Mask */
+#define        AR_D2_QCUMASK   0x1008          /* QCU Mask */
+#define        AR_D3_QCUMASK   0x100c          /* QCU Mask */
+#define        AR_D4_QCUMASK   0x1010          /* QCU Mask */
+#define        AR_D5_QCUMASK   0x1014          /* QCU Mask */
+#define        AR_D6_QCUMASK   0x1018          /* QCU Mask */
+#define        AR_D7_QCUMASK   0x101c          /* QCU Mask */
+#define        AR_D8_QCUMASK   0x1020          /* QCU Mask */
+#define        AR_D9_QCUMASK   0x1024          /* QCU Mask */
+#define        AR_DQCUMASK(i)  (AR_D0_QCUMASK + ((i)<<2))
+
+#define        AR_D0_LCL_IFS   0x1040          /* DCU-specific IFS settings */
+#define        AR_D1_LCL_IFS   0x1044          /* DCU-specific IFS settings */
+#define        AR_D2_LCL_IFS   0x1048          /* DCU-specific IFS settings */
+#define        AR_D3_LCL_IFS   0x104c          /* DCU-specific IFS settings */
+#define        AR_D4_LCL_IFS   0x1050          /* DCU-specific IFS settings */
+#define        AR_D5_LCL_IFS   0x1054          /* DCU-specific IFS settings */
+#define        AR_D6_LCL_IFS   0x1058          /* DCU-specific IFS settings */
+#define        AR_D7_LCL_IFS   0x105c          /* DCU-specific IFS settings */
+#define        AR_D8_LCL_IFS   0x1060          /* DCU-specific IFS settings */
+#define        AR_D9_LCL_IFS   0x1064          /* DCU-specific IFS settings */
+#define        AR_DLCL_IFS(i)  (AR_D0_LCL_IFS + ((i)<<2))
+
+#define        AR_D0_RETRY_LIMIT       0x1080  /* Retry limits */
+#define        AR_D1_RETRY_LIMIT       0x1084  /* Retry limits */
+#define        AR_D2_RETRY_LIMIT       0x1088  /* Retry limits */
+#define        AR_D3_RETRY_LIMIT       0x108c  /* Retry limits */
+#define        AR_D4_RETRY_LIMIT       0x1090  /* Retry limits */
+#define        AR_D5_RETRY_LIMIT       0x1094  /* Retry limits */
+#define        AR_D6_RETRY_LIMIT       0x1098  /* Retry limits */
+#define        AR_D7_RETRY_LIMIT       0x109c  /* Retry limits */
+#define        AR_D8_RETRY_LIMIT       0x10a0  /* Retry limits */
+#define        AR_D9_RETRY_LIMIT       0x10a4  /* Retry limits */
+#define        AR_DRETRY_LIMIT(i)      (AR_D0_RETRY_LIMIT + ((i)<<2))
+
+#define        AR_D0_CHNTIME   0x10c0          /* ChannelTime settings */
+#define        AR_D1_CHNTIME   0x10c4          /* ChannelTime settings */
+#define        AR_D2_CHNTIME   0x10c8          /* ChannelTime settings */
+#define        AR_D3_CHNTIME   0x10cc          /* ChannelTime settings */
+#define        AR_D4_CHNTIME   0x10d0          /* ChannelTime settings */
+#define        AR_D5_CHNTIME   0x10d4          /* ChannelTime settings */
+#define        AR_D6_CHNTIME   0x10d8          /* ChannelTime settings */
+#define        AR_D7_CHNTIME   0x10dc          /* ChannelTime settings */
+#define        AR_D8_CHNTIME   0x10e0          /* ChannelTime settings */
+#define        AR_D9_CHNTIME   0x10e4          /* ChannelTime settings */
+#define        AR_DCHNTIME(i)  (AR_D0_CHNTIME + ((i)<<2))
+
+#define        AR_D0_MISC      0x1100          /* Misc DCU-specific settings */
+#define        AR_D1_MISC      0x1104          /* Misc DCU-specific settings */
+#define        AR_D2_MISC      0x1108          /* Misc DCU-specific settings */
+#define        AR_D3_MISC      0x110c          /* Misc DCU-specific settings */
+#define        AR_D4_MISC      0x1110          /* Misc DCU-specific settings */
+#define        AR_D5_MISC      0x1114          /* Misc DCU-specific settings */
+#define        AR_D6_MISC      0x1118          /* Misc DCU-specific settings */
+#define        AR_D7_MISC      0x111c          /* Misc DCU-specific settings */
+#define        AR_D8_MISC      0x1120          /* Misc DCU-specific settings */
+#define        AR_D9_MISC      0x1124          /* Misc DCU-specific settings */
+#define        AR_DMISC(i)     (AR_D0_MISC + ((i)<<2))
+
+#define        AR_D0_SEQNUM    0x1140          /* Frame seqnum control/status */
+#define        AR_D1_SEQNUM    0x1144          /* Frame seqnum control/status */
+#define        AR_D2_SEQNUM    0x1148          /* Frame seqnum control/status */
+#define        AR_D3_SEQNUM    0x114c          /* Frame seqnum control/status */
+#define        AR_D4_SEQNUM    0x1150          /* Frame seqnum control/status */
+#define        AR_D5_SEQNUM    0x1154          /* Frame seqnum control/status */
+#define        AR_D6_SEQNUM    0x1158          /* Frame seqnum control/status */
+#define        AR_D7_SEQNUM    0x115c          /* Frame seqnum control/status */
+#define        AR_D8_SEQNUM    0x1160          /* Frame seqnum control/status */
+#define        AR_D9_SEQNUM    0x1164          /* Frame seqnum control/status */
+#define        AR_DSEQNUM(i)   (AR_D0_SEQNUM + ((i<<2)))
+
+/* MAC DCU-global IFS settings */
+#define        AR_D_GBL_IFS_SIFS       0x1030  /* DCU global SIFS settings */
+#define        AR_D_GBL_IFS_SLOT       0x1070  /* DC global slot interval */
+#define        AR_D_GBL_IFS_EIFS       0x10b0  /* DCU global EIFS setting */
+#define        AR_D_GBL_IFS_MISC       0x10f0  /* DCU global misc. IFS settings */
+#define        AR_D_FPCTL      0x1230          /* DCU frame prefetch settings */
+#define        AR_D_TXPSE      0x1270          /* DCU transmit pause control/status */
+#define        AR_D_TXBLK_CMD  0x1038          /* DCU transmit filter cmd (w/only) */
+#define        AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) /* DCU transmit filter data */
+#define        AR_D_TXBLK_CLR  0x143c          /* DCU clear tx filter (w/only) */
+#define        AR_D_TXBLK_SET  0x147c          /* DCU set tx filter (w/only) */
+
+#define        AR_D_TXPSE      0x1270          /* DCU transmit pause control/status */
+
+#define        AR_RC           0x4000          /* Warm reset control register */
+#define        AR_SCR          0x4004          /* Sleep control register */
+#define        AR_INTPEND      0x4008          /* Interrupt Pending register */
+#define        AR_SFR          0x400C          /* Sleep force register */
+#define        AR_PCICFG       0x4010          /* PCI configuration register */
+#define        AR_GPIOCR       0x4014          /* GPIO control register */
+#define        AR_GPIODO       0x4018          /* GPIO data output access register */
+#define        AR_GPIODI       0x401C          /* GPIO data input access register */
+#define        AR_SREV         0x4020          /* Silicon Revision register */
+
+#define        AR_EEPROM_ADDR  0x6000          /* EEPROM address register (10 bit) */
+#define        AR_EEPROM_DATA  0x6004          /* EEPROM data register (16 bit) */
+#define        AR_EEPROM_CMD   0x6008          /* EEPROM command register */
+#define        AR_EEPROM_STS   0x600c          /* EEPROM status register */
+#define        AR_EEPROM_CFG   0x6010          /* EEPROM configuration register */
+
+#define        AR_STA_ID0      0x8000          /* station ID0 - low 32 bits */
+#define        AR_STA_ID1      0x8004          /* station ID1 - upper 16 bits */
+#define        AR_BSS_ID0      0x8008          /* BSSID low 32 bits */
+#define        AR_BSS_ID1      0x800C          /* BSSID upper 16 bits / AID */
+#define        AR_SLOT_TIME    0x8010          /* Time-out after a collision */
+#define        AR_TIME_OUT     0x8014          /* ACK & CTS time-out */
+#define        AR_RSSI_THR     0x8018          /* RSSI warning & missed beacon threshold */
+#define        AR_USEC         0x801c          /* transmit latency register */
+#define        AR_BEACON       0x8020          /* beacon control value/mode bits */
+#define        AR_CFP_PERIOD   0x8024          /* CFP Interval (TU/msec) */
+#define        AR_TIMER0       0x8028          /* Next beacon time (TU/msec) */
+#define        AR_TIMER1       0x802c          /* DMA beacon alert time (1/8 TU) */
+#define        AR_TIMER2       0x8030          /* Software beacon alert (1/8 TU) */
+#define        AR_TIMER3       0x8034          /* ATIM window time */
+#define        AR_CFP_DUR      0x8038          /* maximum CFP duration in TU */
+#define        AR_RX_FILTER    0x803C          /* receive filter register */
+#define        AR_MCAST_FIL0   0x8040          /* multicast filter lower 32 bits */
+#define        AR_MCAST_FIL1   0x8044          /* multicast filter upper 32 bits */
+#define        AR_DIAG_SW      0x8048          /* PCU control register */
+#define        AR_TSF_L32      0x804c          /* local clock lower 32 bits */
+#define        AR_TSF_U32      0x8050          /* local clock upper 32 bits */
+#define        AR_TST_ADDAC    0x8054          /* ADDAC test register */
+#define        AR_DEF_ANTENNA  0x8058          /* default antenna register */
+
+#define        AR_LAST_TSTP    0x8080          /* Time stamp of the last beacon rcvd */
+#define        AR_NAV          0x8084          /* current NAV value */
+#define        AR_RTS_OK       0x8088          /* RTS exchange success counter */
+#define        AR_RTS_FAIL     0x808c          /* RTS exchange failure counter */
+#define        AR_ACK_FAIL     0x8090          /* ACK failure counter */
+#define        AR_FCS_FAIL     0x8094          /* FCS check failure counter */
+#define        AR_BEACON_CNT   0x8098          /* Valid beacon counter */
+
+#define        AR_KEYTABLE_0   0x8800          /* Encryption key table */
+#define        AR_KEYTABLE(n)  (AR_KEYTABLE_0 + ((n)*32))
+
+#define        AR_CR_RXE       0x00000004      /* Receive enable */
+#define        AR_CR_RXD       0x00000020      /* Receive disable */
+#define        AR_CR_SWI       0x00000040      /* One-shot software interrupt */
+#define        AR_CR_BITS      "\20\3RXE\6RXD\7SWI"
+
+#define        AR_CFG_SWTD     0x00000001      /* byteswap tx descriptor words */
+#define        AR_CFG_SWTB     0x00000002      /* byteswap tx data buffer words */
+#define        AR_CFG_SWRD     0x00000004      /* byteswap rx descriptor words */
+#define        AR_CFG_SWRB     0x00000008      /* byteswap rx data buffer words */
+#define        AR_CFG_SWRG     0x00000010      /* byteswap register access data words */
+#define        AR_CFG_AP_ADHOC_INDICATION      0x00000020      /* AP/adhoc indication (0-AP, 1-Adhoc) */
+#define        AR_CFG_PHOK     0x00000100      /* PHY OK status */
+#define        AR_CFG_EEBS     0x00000200      /* EEPROM busy */
+#define        AR_CFG_CLK_GATE_DIS     0x00000400      /* Clock gating disable (Oahu only) */
+#define        AR_CFG_PCI_MASTER_REQ_Q_THRESH_M        0x00060000      /* Mask of PCI core master request queue full threshold */
+#define        AR_CFG_PCI_MASTER_REQ_Q_THRESH_S        17              /* Shift for PCI core master request queue full threshold */
+#define        AR_CFG_BITS \
+       "\20\1SWTD\2SWTB\3SWRD\4SWRB\5SWRG\10PHYOK11EEBS"
+
+#define        AR_IER_ENABLE   0x00000001      /* Global interrupt enable */
+#define        AR_IER_DISABLE  0x00000000      /* Global interrupt disable */
+#define        AR_IER_BITS     "\20\1ENABLE"
+
+#define        AR_RTSD0_RTS_DURATION_6_M       0x000000FF
+#define        AR_RTSD0_RTS_DURATION_6_S       0
+#define        AR_RTSD0_RTS_DURATION_9_M       0x0000FF00
+#define        AR_RTSD0_RTS_DURATION_9_S       8
+#define        AR_RTSD0_RTS_DURATION_12_M      0x00FF0000
+#define        AR_RTSD0_RTS_DURATION_12_S      16
+#define        AR_RTSD0_RTS_DURATION_18_M      0xFF000000
+#define        AR_RTSD0_RTS_DURATION_18_S      24
+
+#define        AR_RTSD0_RTS_DURATION_24_M      0x000000FF
+#define        AR_RTSD0_RTS_DURATION_24_S      0
+#define        AR_RTSD0_RTS_DURATION_36_M      0x0000FF00
+#define        AR_RTSD0_RTS_DURATION_36_S      8
+#define        AR_RTSD0_RTS_DURATION_48_M      0x00FF0000
+#define        AR_RTSD0_RTS_DURATION_48_S      16
+#define        AR_RTSD0_RTS_DURATION_54_M      0xFF000000
+#define        AR_RTSD0_RTS_DURATION_54_S      24
+
+#define        AR_DMASIZE_4B   0x00000000      /* DMA size 4 bytes (TXCFG + RXCFG) */
+#define        AR_DMASIZE_8B   0x00000001      /* DMA size 8 bytes */
+#define        AR_DMASIZE_16B  0x00000002      /* DMA size 16 bytes */
+#define        AR_DMASIZE_32B  0x00000003      /* DMA size 32 bytes */
+#define        AR_DMASIZE_64B  0x00000004      /* DMA size 64 bytes */
+#define        AR_DMASIZE_128B 0x00000005      /* DMA size 128 bytes */
+#define        AR_DMASIZE_256B 0x00000006      /* DMA size 256 bytes */
+#define        AR_DMASIZE_512B 0x00000007      /* DMA size 512 bytes */
+
+#define        AR_TXCFG_FTRIG_M        0x000003F0      /* Mask for Frame trigger level */
+#define        AR_TXCFG_FTRIG_S        4               /* Shift for Frame trigger level */
+#define        AR_TXCFG_FTRIG_IMMED    0x00000000      /* bytes in PCU TX FIFO before air */
+#define        AR_TXCFG_FTRIG_64B      0x00000010      /* default */
+#define        AR_TXCFG_FTRIG_128B     0x00000020
+#define        AR_TXCFG_FTRIG_192B     0x00000030
+#define        AR_TXCFG_FTRIG_256B     0x00000040      /* 5 bits total */
+#define        AR_TXCFG_BITS   "\20"
+
+#define        AR5311_RXCFG_DEF_RX_ANTENNA     0x00000008      /* Default Receive Antenna */
+                                               /* Maui2/Spirit only - reserved on Oahu */
+#define        AR_RXCFG_ZLFDMA 0x00000010      /* Enable DMA of zero-length frame */
+#define        AR_RXCFG_EN_JUM 0x00000020      /* Enable jumbo rx descriptors */
+#define        AR_RXCFG_WR_JUM 0x00000040      /* Wrap jumbo rx descriptors */
+
+#define        AR_MIBC_COW     0x00000001      /* counter overflow warning */
+#define        AR_MIBC_FMC     0x00000002      /* freeze MIB counters */
+#define        AR_MIBC_CMC     0x00000004      /* clear MIB counters */
+#define        AR_MIBC_MCS     0x00000008      /* MIB counter strobe, increment all */
+
+#define        AR_TOPS_MASK    0x0000FFFF      /* Mask for timeout prescale */
+
+#define        AR_RXNPTO_MASK  0x000003FF      /* Mask for no frame received timeout */
+
+#define        AR_TXNPTO_MASK  0x000003FF      /* Mask for no frame transmitted timeout */
+#define        AR_TXNPTO_QCU_MASK      0x03FFFC00      /* Mask indicating the set of QCUs */
+                                       /* for which frame completions will cause */
+                                       /* a reset of the no frame transmitted timeout */
+
+#define        AR_RPGTO_MASK   0x000003FF      /* Mask for receive frame gap timeout */
+
+#define        AR_RPCNT_MASK   0x0000001F      /* Mask for receive frame count limit */
+
+#define        AR_MACMISC_DMA_OBS_M    0x000001E0      /* Mask for DMA observation bus mux select */
+#define        AR_MACMISC_DMA_OBS_S    5               /* Shift for DMA observation bus mux select */
+#define        AR_MACMISC_MISC_OBS_M   0x00000E00      /* Mask for MISC observation bus mux select */
+#define        AR_MACMISC_MISC_OBS_S   9               /* Shift for MISC observation bus mux select */
+#define        AR_MACMISC_MAC_OBS_BUS_LSB_M    0x00007000      /* Mask for MAC observation bus mux select (lsb) */
+#define        AR_MACMISC_MAC_OBS_BUS_LSB_S    12              /* Shift for MAC observation bus mux select (lsb) */
+#define        AR_MACMISC_MAC_OBS_BUS_MSB_M    0x00038000      /* Mask for MAC observation bus mux select (msb) */
+#define        AR_MACMISC_MAC_OBS_BUS_MSB_S    15              /* Shift for MAC observation bus mux select (msb) */
+
+                               /* Maui2/Spirit only. */
+#define        AR5311_QDCLKGATE_QCU_M  0x0000FFFF      /* Mask for QCU clock disable */
+#define        AR5311_QDCLKGATE_DCU_M  0x07FF0000      /* Mask for DCU clock disable */
+
+       /* Interrupt Status Registers */
+#define        AR_ISR_RXOK     0x00000001      /* At least one frame received sans errors */
+#define        AR_ISR_RXDESC   0x00000002      /* Receive interrupt request */
+#define        AR_ISR_RXERR    0x00000004      /* Receive error interrupt */
+#define        AR_ISR_RXNOPKT  0x00000008      /* No frame received within timeout clock */
+#define        AR_ISR_RXEOL    0x00000010      /* Received descriptor empty interrupt */
+#define        AR_ISR_RXORN    0x00000020      /* Receive FIFO overrun interrupt */
+#define        AR_ISR_TXOK     0x00000040      /* Transmit okay interrupt */
+#define        AR_ISR_TXDESC   0x00000080      /* Transmit interrupt request */
+#define        AR_ISR_TXERR    0x00000100      /* Transmit error interrupt */
+#define        AR_ISR_TXNOPKT  0x00000200      /* No frame transmitted interrupt */
+#define        AR_ISR_TXEOL    0x00000400      /* Transmit descriptor empty interrupt */
+#define        AR_ISR_TXURN    0x00000800      /* Transmit FIFO underrun interrupt */
+#define        AR_ISR_MIB      0x00001000      /* MIB interrupt - see MIBC */
+#define        AR_ISR_SWI      0x00002000      /* Software interrupt */
+#define        AR_ISR_RXPHY    0x00004000      /* PHY receive error interrupt */
+#define        AR_ISR_RXKCM    0x00008000      /* Key-cache miss interrupt */
+#define        AR_ISR_SWBA     0x00010000      /* Software beacon alert interrupt */
+#define        AR_ISR_BRSSI    0x00020000      /* Beacon threshold interrupt */
+#define        AR_ISR_BMISS    0x00040000      /* Beacon missed interrupt */
+#define        AR_ISR_HIUERR   0x00080000      /* An unexpected bus error has occurred */
+#define        AR_ISR_BNR      0x00100000      /* Beacon not ready interrupt */
+#define        AR_ISR_TIM      0x00800000      /* TIM interrupt */
+#define        AR_ISR_GPIO     0x01000000      /* GPIO Interrupt */
+#define        AR_ISR_QCBROVF  0x02000000      /* QCU CBR overflow interrupt */
+#define        AR_ISR_QCBRURN  0x04000000      /* QCU CBR underrun interrupt */
+#define        AR_ISR_QTRIG    0x08000000      /* QCU scheduling trigger interrupt */
+#define        AR_ISR_RESV0    0xF0000000      /* Reserved */
+
+#define        AR_ISR_S0_QCU_TXOK_M    0x000003FF      /* Mask for TXOK (QCU 0-9) */
+#define        AR_ISR_S0_QCU_TXDESC_M  0x03FF0000      /* Mask for TXDESC (QCU 0-9) */
+
+#define        AR_ISR_S1_QCU_TXERR_M   0x000003FF      /* Mask for TXERR (QCU 0-9) */
+#define        AR_ISR_S1_QCU_TXEOL_M   0x03FF0000      /* Mask for TXEOL (QCU 0-9) */
+
+#define        AR_ISR_S2_QCU_TXURN_M   0x000003FF      /* Mask for TXURN (QCU 0-9) */
+#define        AR_ISR_S2_MCABT 0x00010000      /* Master cycle abort interrupt */
+#define        AR_ISR_S2_SSERR 0x00020000      /* SERR interrupt */
+#define        AR_ISR_S2_DPERR 0x00040000      /* PCI bus parity error */
+#define        AR_ISR_S2_RESV0 0xFFF80000      /* Reserved */
+
+#define        AR_ISR_S3_QCU_QCBROVF_M 0x000003FF      /* Mask for QCBROVF (QCU 0-9) */
+#define        AR_ISR_S3_QCU_QCBRURN_M 0x03FF0000      /* Mask for QCBRURN (QCU 0-9) */
+
+#define        AR_ISR_S4_QCU_QTRIG_M   0x000003FF      /* Mask for QTRIG (QCU 0-9) */
+#define        AR_ISR_S4_RESV0 0xFFFFFC00      /* Reserved */
+
+       /* Interrupt Mask Registers */
+#define        AR_IMR_RXOK     0x00000001      /* At least one frame received sans errors */
+#define        AR_IMR_RXDESC   0x00000002      /* Receive interrupt request */
+#define        AR_IMR_RXERR    0x00000004      /* Receive error interrupt */
+#define        AR_IMR_RXNOPKT  0x00000008      /* No frame received within timeout clock */
+#define        AR_IMR_RXEOL    0x00000010      /* Received descriptor empty interrupt */
+#define        AR_IMR_RXORN    0x00000020      /* Receive FIFO overrun interrupt */
+#define        AR_IMR_TXOK     0x00000040      /* Transmit okay interrupt */
+#define        AR_IMR_TXDESC   0x00000080      /* Transmit interrupt request */
+#define        AR_IMR_TXERR    0x00000100      /* Transmit error interrupt */
+#define        AR_IMR_TXNOPKT  0x00000200      /* No frame transmitted interrupt */
+#define        AR_IMR_TXEOL    0x00000400      /* Transmit descriptor empty interrupt */
+#define        AR_IMR_TXURN    0x00000800      /* Transmit FIFO underrun interrupt */
+#define        AR_IMR_MIB      0x00001000      /* MIB interrupt - see MIBC */
+#define        AR_IMR_SWI      0x00002000      /* Software interrupt */
+#define        AR_IMR_RXPHY    0x00004000      /* PHY receive error interrupt */
+#define        AR_IMR_RXKCM    0x00008000      /* Key-cache miss interrupt */
+#define        AR_IMR_SWBA     0x00010000      /* Software beacon alert interrupt */
+#define        AR_IMR_BRSSI    0x00020000      /* Beacon threshold interrupt */
+#define        AR_IMR_BMISS    0x00040000      /* Beacon missed interrupt */
+#define        AR_IMR_HIUERR   0x00080000      /* An unexpected bus error has occurred */
+#define        AR_IMR_BNR      0x00100000      /* BNR interrupt */
+#define        AR_IMR_TIM      0x00800000      /* TIM interrupt */
+#define        AR_IMR_GPIO     0x01000000      /* GPIO Interrupt */
+#define        AR_IMR_QCBROVF  0x02000000      /* QCU CBR overflow interrupt */
+#define        AR_IMR_QCBRURN  0x04000000      /* QCU CBR underrun interrupt */
+#define        AR_IMR_QTRIG    0x08000000      /* QCU scheduling trigger interrupt */
+#define        AR_IMR_RESV0    0xF0000000      /* Reserved */
+
+#define        AR_IMR_S0_QCU_TXOK      0x000003FF      /* Mask for TXOK (QCU 0-9) */
+#define        AR_IMR_S0_QCU_TXOK_S    0
+#define        AR_IMR_S0_QCU_TXDESC    0x03FF0000      /* Mask for TXDESC (QCU 0-9) */
+#define        AR_IMR_S0_QCU_TXDESC_S  16              /* Shift for TXDESC (QCU 0-9) */
+
+#define        AR_IMR_S1_QCU_TXERR     0x000003FF      /* Mask for TXERR (QCU 0-9) */
+#define        AR_IMR_S1_QCU_TXERR_S   0
+#define        AR_IMR_S1_QCU_TXEOL     0x03FF0000      /* Mask for TXEOL (QCU 0-9) */
+#define        AR_IMR_S1_QCU_TXEOL_S   16              /* Shift for TXEOL (QCU 0-9) */
+
+#define        AR_IMR_S2_QCU_TXURN     0x000003FF      /* Mask for TXURN (QCU 0-9) */
+#define        AR_IMR_S2_QCU_TXURN_S   0
+#define        AR_IMR_S2_MCABT 0x00010000      /* Master cycle abort interrupt */
+#define        AR_IMR_S2_SSERR 0x00020000      /* SERR interrupt */
+#define        AR_IMR_S2_DPERR 0x00040000      /* PCI bus parity error */
+#define        AR_IMR_S2_RESV0 0xFFF80000      /* Reserved */
+
+#define        AR_IMR_S3_QCU_QCBROVF_M 0x000003FF      /* Mask for QCBROVF (QCU 0-9) */
+#define        AR_IMR_S3_QCU_QCBRURN_M 0x03FF0000      /* Mask for QCBRURN (QCU 0-9) */
+#define        AR_IMR_S3_QCU_QCBRURN_S 16              /* Shift for QCBRURN (QCU 0-9) */
+
+#define        AR_IMR_S4_QCU_QTRIG_M   0x000003FF      /* Mask for QTRIG (QCU 0-9) */
+#define        AR_IMR_S4_RESV0 0xFFFFFC00      /* Reserved */
+
+       /* Interrupt status registers (read-and-clear access, secondary shadow copies) */
+
+       /* QCU registers */
+#define        AR_NUM_QCU      10      /* Only use QCU 0-9 for forward QCU compatibility */
+#define        AR_QCU_0        0x0001
+#define        AR_QCU_1        0x0002
+#define        AR_QCU_2        0x0004
+#define        AR_QCU_3        0x0008
+#define        AR_QCU_4        0x0010
+#define        AR_QCU_5        0x0020
+#define        AR_QCU_6        0x0040
+#define        AR_QCU_7        0x0080
+#define        AR_QCU_8        0x0100
+#define        AR_QCU_9        0x0200
+
+#define        AR_Q_TXE_M      0x000003FF      /* Mask for TXE (QCU 0-9) */
+
+#define        AR_Q_TXD_M      0x000003FF      /* Mask for TXD (QCU 0-9) */
+
+#define        AR_Q_CBRCFG_CBR_INTERVAL        0x00FFFFFF      /* Mask for CBR interval (us) */
+#define        AR_Q_CBRCFG_CBR_INTERVAL_S              0       /* Shift for CBR interval */
+#define        AR_Q_CBRCFG_CBR_OVF_THRESH      0xFF000000      /* Mask for CBR overflow threshold */
+#define        AR_Q_CBRCFG_CBR_OVF_THRESH_S            24      /* Shift for " " " */
+
+#define        AR_Q_RDYTIMECFG_INT     0x00FFFFFF      /* CBR interval (us) */
+#define        AR_Q_RDYTIMECFG_INT_S   0               /* Shift for ReadyTime Interval (us) */
+#define        AR_Q_RDYTIMECFG_DURATION_M      0x00FFFFFF      /* Mask for CBR interval (us) */
+#define        AR_Q_RDYTIMECFG_EN      0x01000000      /* ReadyTime enable */
+#define        AR_Q_RDYTIMECFG_RESV0   0xFE000000      /* Reserved */
+
+#define        AR_Q_ONESHOTARM_SC_M    0x0000FFFF      /* Mask for MAC_Q_ONESHOTARM_SC (QCU 0-15) */
+#define        AR_Q_ONESHOTARM_SC_RESV0 0xFFFF0000     /* Reserved */
+
+#define        AR_Q_ONESHOTARM_CC_M    0x0000FFFF      /* Mask for MAC_Q_ONESHOTARM_CC (QCU 0-15) */
+#define        AR_Q_ONESHOTARM_CC_RESV0 0xFFFF0000     /* Reserved */
+
+#define        AR_Q_MISC_FSP_M         0x0000000F      /* Mask for Frame Scheduling Policy */
+#define        AR_Q_MISC_FSP_ASAP              0       /* ASAP */
+#define        AR_Q_MISC_FSP_CBR               1       /* CBR */
+#define        AR_Q_MISC_FSP_DBA_GATED         2       /* DMA Beacon Alert gated */
+#define        AR_Q_MISC_FSP_TIM_GATED         3       /* TIM gated */
+#define        AR_Q_MISC_FSP_BEACON_SENT_GATED 4       /* Beacon-sent-gated */
+#define        AR_Q_MISC_ONE_SHOT_EN   0x00000010      /* OneShot enable */
+#define        AR_Q_MISC_CBR_INCR_DIS1 0x00000020      /* Disable CBR expired counter
+                                                  incr (empty q) */
+#define        AR_Q_MISC_CBR_INCR_DIS0 0x00000040      /* Disable CBR expired counter
+                                                  incr (empty beacon q) */
+#define        AR_Q_MISC_BEACON_USE    0x00000080      /* Beacon use indication */
+#define        AR_Q_MISC_CBR_EXP_CNTR_LIMIT    0x00000100      /* CBR expired counter limit enable */
+#define        AR_Q_MISC_RDYTIME_EXP_POLICY    0x00000200      /* Enable TXE cleared on ReadyTime expired or VEOL */
+#define        AR_Q_MISC_RESET_CBR_EXP_CTR     0x00000400      /* Reset CBR expired counter */
+#define        AR_Q_MISC_DCU_EARLY_TERM_REQ    0x00000800      /* DCU frame early termination request control */
+#define        AR_Q_MISC_RESV0 0xFFFFF000      /* Reserved */
+
+#define        AR_Q_STS_PEND_FR_CNT_M  0x00000003      /* Mask for Pending Frame Count */
+#define        AR_Q_STS_RESV0  0x000000FC      /* Reserved */
+#define        AR_Q_STS_CBR_EXP_CNT_M  0x0000FF00      /* Mask for CBR expired counter */
+#define        AR_Q_STS_RESV1  0xFFFF0000      /* Reserved */
+
+#define        AR_Q_RDYTIMESHDN_M      0x000003FF      /* Mask for ReadyTimeShutdown status (QCU 0-9) */
+
+       /* DCU registers */
+#define        AR_NUM_DCU      10      /* Only use 10 DCU's for forward QCU/DCU compatibility */
+#define        AR_DCU_0        0x0001
+#define        AR_DCU_1        0x0002
+#define        AR_DCU_2        0x0004
+#define        AR_DCU_3        0x0008
+#define        AR_DCU_4        0x0010
+#define        AR_DCU_5        0x0020
+#define        AR_DCU_6        0x0040
+#define        AR_DCU_7        0x0080
+#define        AR_DCU_8        0x0100
+#define        AR_DCU_9        0x0200
+
+#define        AR_D_QCUMASK_M  0x000003FF      /* Mask for QCU Mask (QCU 0-9) */
+#define        AR_D_QCUMASK_RESV0      0xFFFFFC00      /* Reserved */
+
+#define        AR_D_LCL_IFS_CWMIN      0x000003FF      /* Mask for CW_MIN */
+#define        AR_D_LCL_IFS_CWMIN_S    0               /* Shift for CW_MIN */
+#define        AR_D_LCL_IFS_CWMAX      0x000FFC00      /* Mask for CW_MAX */
+#define        AR_D_LCL_IFS_CWMAX_S    10              /* Shift for CW_MAX */
+#define        AR_D_LCL_IFS_AIFS       0x0FF00000      /* Mask for AIFS */
+#define        AR_D_LCL_IFS_AIFS_S     20              /* Shift for AIFS */
+#define        AR_D_LCL_IFS_RESV0      0xF0000000      /* Reserved */
+
+#define        AR_D_RETRY_LIMIT_FR_SH  0x0000000F      /* Mask for frame short retry limit */
+#define        AR_D_RETRY_LIMIT_FR_SH_S        0       /* Shift for frame short retry limit */
+#define        AR_D_RETRY_LIMIT_FR_LG  0x000000F0      /* Mask for frame long retry limit */
+#define        AR_D_RETRY_LIMIT_FR_LG_S        4       /* Shift for frame long retry limit */
+#define        AR_D_RETRY_LIMIT_STA_SH 0x00003F00      /* Mask for station short retry limit */
+#define        AR_D_RETRY_LIMIT_STA_SH_S       8       /* Shift for station short retry limit */
+#define        AR_D_RETRY_LIMIT_STA_LG 0x000FC000      /* Mask for station short retry limit */
+#define        AR_D_RETRY_LIMIT_STA_LG_S       14      /* Shift for station short retry limit */
+#define        AR_D_RETRY_LIMIT_RESV0  0xFFF00000      /* Reserved */
+
+#define        AR_D_CHNTIME_EN 0x00100000      /* ChannelTime enable */
+#define        AR_D_CHNTIME_RESV0      0xFFE00000      /* Reserved */
+#define        AR_D_CHNTIME_DUR        0x000FFFFF      /* Mask for ChannelTime duration (us) */
+#define AR_D_CHNTIME_DUR_S              0 /* Shift for ChannelTime duration */
+
+#define        AR_D_MISC_BKOFF_THRESH_M        0x000007FF      /* Mask for Backoff threshold setting */
+#define AR_D_MISC_FRAG_BKOFF_EN         0x00000200 /* Backoff during a frag burst */
+#define        AR_D_MISC_HCF_POLL_EN   0x00000800      /* HFC poll enable */
+#define        AR_D_MISC_BKOFF_PERSISTENCE     0x00001000      /* Backoff persistence factor setting */
+#define        AR_D_MISC_FR_PREFETCH_EN        0x00002000      /* Frame prefetch enable */
+#define        AR_D_MISC_VIR_COL_HANDLING_M    0x0000C000      /* Mask for Virtual collision handling policy */
+#define        AR_D_MISC_VIR_COL_HANDLING_NORMAL       0       /* Normal */
+#define        AR_D_MISC_VIR_COL_HANDLING_MODIFIED     1       /* Modified */
+#define        AR_D_MISC_VIR_COL_HANDLING_IGNORE       2       /* Ignore */
+#define        AR_D_MISC_BEACON_USE    0x00010000      /* Beacon use indication */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL     0x00060000      /* Mask for DCU arbiter lockout control */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL_S   17              /* Shift for DCU arbiter lockout control */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE        0       /* No lockout */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR    1       /* Intra-frame */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL      2       /* Global */
+#define        AR_D_MISC_ARB_LOCKOUT_IGNORE    0x00080000      /* DCU arbiter lockout ignore control */
+#define        AR_D_MISC_SEQ_NUM_INCR_DIS      0x00100000      /* Sequence number increment disable */
+#define        AR_D_MISC_POST_FR_BKOFF_DIS     0x00200000      /* Post-frame backoff disable */
+#define        AR_D_MISC_VIRT_COLL_POLICY      0x00400000      /* Virtual coll. handling policy */
+#define        AR_D_MISC_BLOWN_IFS_POLICY      0x00800000      /* Blown IFS handling policy */
+#define        AR5311_D_MISC_SEQ_NUM_CONTROL   0x01000000      /* Sequence Number local or global */
+                                               /* Maui2/Spirit only, reserved on Oahu */
+#define        AR_D_MISC_RESV0 0xFE000000      /* Reserved */
+
+#define        AR_D_SEQNUM_M   0x00000FFF      /* Mask for value of sequence number */
+#define        AR_D_SEQNUM_RESV0       0xFFFFF000      /* Reserved */
+
+#define        AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007      /* Mask forLFSR slice select */
+#define        AR_D_GBL_IFS_MISC_TURBO_MODE    0x00000008      /* Turbo mode indication */
+#define        AR_D_GBL_IFS_MISC_SIFS_DURATION_USEC    0x000003F0      /* Mask for SIFS duration (us) */
+#define        AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00      /* Mask for microsecond duration */
+#define        AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY       0x00300000      /* Mask for DCU arbiter delay */
+#define        AR_D_GBL_IFS_MISC_RESV0 0xFFC00000      /* Reserved */
+
+/* Oahu only */
+#define        AR_D_TXPSE_CTRL_M       0x000003FF      /* Mask of DCUs to pause (DCUs 0-9) */
+#define        AR_D_TXPSE_RESV0        0x0000FC00      /* Reserved */
+#define        AR_D_TXPSE_STATUS       0x00010000      /* Transmit pause status */
+#define        AR_D_TXPSE_RESV1        0xFFFE0000      /* Reserved */
+
+       /* DMA & PCI Registers in PCI space (usable during sleep) */
+#define        AR_RC_MAC       0x00000001      /* MAC reset */
+#define        AR_RC_BB        0x00000002      /* Baseband reset */
+#define        AR_RC_RESV0     0x00000004      /* Reserved */
+#define        AR_RC_RESV1     0x00000008      /* Reserved */
+#define        AR_RC_PCI       0x00000010      /* PCI-core reset */
+#define        AR_RC_BITS      "\20\1MAC\2BB\3RESV0\4RESV1\5RPCI"
+
+#define        AR_SCR_SLDUR    0x0000ffff      /* sleep duration mask, units of 128us */
+#define        AR_SCR_SLDUR_S  0
+#define        AR_SCR_SLE      0x00030000      /* sleep enable mask */
+#define        AR_SCR_SLE_S    16              /* sleep enable bits shift */
+#define        AR_SCR_SLE_WAKE 0x00000000      /* force wake */
+#define        AR_SCR_SLE_SLP  0x00010000      /* force sleep */
+#define        AR_SCR_SLE_NORM 0x00020000      /* sleep logic normal operation */
+#define        AR_SCR_SLE_UNITS        0x00000008      /* SCR units/TU */
+#define        AR_SCR_BITS     "\20\20SLE_SLP\21SLE"
+
+#define        AR_INTPEND_TRUE 0x00000001      /* interrupt pending */
+#define        AR_INTPEND_BITS "\20\1IP"
+
+#define        AR_SFR_SLEEP    0x00000001      /* force sleep */
+
+#define        AR_PCICFG_CLKRUNEN      0x00000004      /* enable PCI CLKRUN function */
+#define        AR_PCICFG_EEPROM_SIZE_M 0x00000018      /* Mask for EEPROM size */
+#define        AR_PCICFG_EEPROM_SIZE_S   3     /* Mask for EEPROM size */
+#define        AR_PCICFG_EEPROM_SIZE_4K         0      /* EEPROM size 4 Kbit */
+#define        AR_PCICFG_EEPROM_SIZE_8K         1      /* EEPROM size 8 Kbit */
+#define        AR_PCICFG_EEPROM_SIZE_16K       2       /* EEPROM size 16 Kbit */
+#define        AR_PCICFG_EEPROM_SIZE_FAILED    3       /* Failure */
+#define        AR_PCICFG_LEDCTL        0x00000060 /* LED control Status */
+#define        AR_PCICFG_LEDCTL_NONE   0x00000000 /* STA is not associated or trying */
+#define        AR_PCICFG_LEDCTL_PEND   0x00000020 /* STA is trying to associate */
+#define        AR_PCICFG_LEDCTL_ASSOC  0x00000040 /* STA is associated */
+#define        AR_PCICFG_PCI_BUS_SEL_M 0x00000380      /* Mask for PCI observation bus mux select */
+#define        AR_PCICFG_DIS_CBE_FIX   0x00000400      /* Disable fix for bad PCI CBE# generation */
+#define        AR_PCICFG_SL_INTEN      0x00000800      /* enable interrupt line assertion when asleep */
+#define        AR_PCICFG_RESV0         0x00001000      /* Reserved */
+#define        AR_PCICFG_SL_INPEN      0x00002000      /* Force asleep when an interrupt is pending */
+#define        AR_PCICFG_RESV1         0x0000C000      /* Reserved */
+#define        AR_PCICFG_SPWR_DN       0x00010000      /* mask for sleep/awake indication */
+#define        AR_PCICFG_LEDMODE       0x000E0000 /* LED mode */
+#define        AR_PCICFG_LEDMODE_PROP  0x00000000 /* Blink prop to filtered tx/rx */
+#define        AR_PCICFG_LEDMODE_RPROP 0x00020000 /* Blink prop to unfiltered tx/rx */
+#define        AR_PCICFG_LEDMODE_SPLIT 0x00040000 /* Blink power for tx/net for rx */
+#define        AR_PCICFG_LEDMODE_RAND  0x00060000 /* Blink randomly */
+#define        AR_PCICFG_LEDBLINK      0x00700000 /* LED blink threshold select */
+#define        AR_PCICFG_LEDBLINK_S    20
+#define        AR_PCICFG_LEDSLOW       0x00800000 /* LED slowest blink rate mode */
+#define        AR_PCICFG_RESV2         0xFF000000      /* Reserved */
+#define        AR_PCICFG_BITS  "\20\3CLKRUNEN\13SL_INTEN"
+
+#define        AR_GPIOCR_CR_SHIFT      2               /* Each CR is 2 bits */
+#define        AR_GPIOCR_0_CR_N        0x00000000      /* Input only mode for GPIODO[0] */
+#define        AR_GPIOCR_0_CR_0        0x00000001      /* Output only if GPIODO[0] = 0 */
+#define        AR_GPIOCR_0_CR_1        0x00000002      /* Output only if GPIODO[0] = 1 */
+#define        AR_GPIOCR_0_CR_A        0x00000003      /* Always output */
+#define        AR_GPIOCR_1_CR_N        0x00000000      /* Input only mode for GPIODO[1] */
+#define        AR_GPIOCR_1_CR_0        0x00000004      /* Output only if GPIODO[1] = 0 */
+#define        AR_GPIOCR_1_CR_1        0x00000008      /* Output only if GPIODO[1] = 1 */
+#define        AR_GPIOCR_1_CR_A        0x0000000C      /* Always output */
+#define        AR_GPIOCR_2_CR_N        0x00000000      /* Input only mode for GPIODO[2] */
+#define        AR_GPIOCR_2_CR_0        0x00000010      /* Output only if GPIODO[2] = 0 */
+#define        AR_GPIOCR_2_CR_1        0x00000020      /* Output only if GPIODO[2] = 1 */
+#define        AR_GPIOCR_2_CR_A        0x00000030      /* Always output */
+#define        AR_GPIOCR_3_CR_N        0x00000000      /* Input only mode for GPIODO[3] */
+#define        AR_GPIOCR_3_CR_0        0x00000040      /* Output only if GPIODO[3] = 0 */
+#define        AR_GPIOCR_3_CR_1        0x00000080      /* Output only if GPIODO[3] = 1 */
+#define        AR_GPIOCR_3_CR_A        0x000000C0      /* Always output */
+#define        AR_GPIOCR_4_CR_N        0x00000000      /* Input only mode for GPIODO[4] */
+#define        AR_GPIOCR_4_CR_0        0x00000100      /* Output only if GPIODO[4] = 0 */
+#define        AR_GPIOCR_4_CR_1        0x00000200      /* Output only if GPIODO[4] = 1 */
+#define        AR_GPIOCR_4_CR_A        0x00000300      /* Always output */
+#define        AR_GPIOCR_5_CR_N        0x00000000      /* Input only mode for GPIODO[5] */
+#define        AR_GPIOCR_5_CR_0        0x00000400      /* Output only if GPIODO[5] = 0 */
+#define        AR_GPIOCR_5_CR_1        0x00000800      /* Output only if GPIODO[5] = 1 */
+#define        AR_GPIOCR_5_CR_A        0x00000C00      /* Always output */
+#define        AR_GPIOCR_INT_SHIFT     12              /* Interrupt select field shifter */
+#define        AR_GPIOCR_INT_MASK      0x00007000      /* Interrupt select field mask */
+#define        AR_GPIOCR_INT_SEL0      0x00000000      /* Select Interrupt Pin GPIO_0 */
+#define        AR_GPIOCR_INT_SEL1      0x00001000      /* Select Interrupt Pin GPIO_1 */
+#define        AR_GPIOCR_INT_SEL2      0x00002000      /* Select Interrupt Pin GPIO_2 */
+#define        AR_GPIOCR_INT_SEL3      0x00003000      /* Select Interrupt Pin GPIO_3 */
+#define        AR_GPIOCR_INT_SEL4      0x00004000      /* Select Interrupt Pin GPIO_4 */
+#define        AR_GPIOCR_INT_SEL5      0x00005000      /* Select Interrupt Pin GPIO_5 */
+#define        AR_GPIOCR_INT_ENA       0x00008000      /* Enable GPIO Interrupt */
+#define        AR_GPIOCR_INT_SELL      0x00000000      /* Generate Interrupt if selected pin is low */
+#define        AR_GPIOCR_INT_SELH      0x00010000      /* Generate Interrupt if selected pin is high */
+
+#define        AR_SREV_ID_M    0x000000FF      /* Mask to read SREV info */
+#define        AR_PCICFG_EEPROM_SIZE_16K       2       /* EEPROM size 16 Kbit */
+#define        AR_SREV_ID_S            4               /* Major Rev Info */
+#define        AR_SREV_REVISION_M      0x0000000F      /* Chip revision level */
+#define        AR_SREV_FPGA            1
+#define        AR_SREV_D2PLUS          2
+#define        AR_SREV_D2PLUS_MS       3               /* metal spin */
+#define        AR_SREV_CRETE           4
+#define        AR_SREV_CRETE_MS        5               /* FCS metal spin */
+#define        AR_SREV_CRETE_MS23      7               /* 2.3 metal spin (6 skipped) */
+#define        AR_SREV_CRETE_23        8               /* 2.3 full tape out */
+#define        AR_SREV_VERSION_M       0x000000F0      /* Chip version indication */
+#define        AR_SREV_VERSION_CRETE   0
+#define        AR_SREV_VERSION_MAUI_1  1
+#define        AR_SREV_VERSION_MAUI_2  2
+#define        AR_SREV_VERSION_SPIRIT  3
+#define        AR_SREV_VERSION_OAHU    4
+#define        AR_SREV_OAHU_ES         0       /* Engineering Sample */
+#define        AR_SREV_OAHU_PROD       2       /* Production */
+
+#define        RAD5_SREV_MAJOR 0x10    /* All current supported ar5211 5 GHz radios are rev 0x10 */
+#define        RAD5_SREV_PROD  0x15    /* Current production level radios */
+#define        RAD2_SREV_MAJOR 0x20    /* All current supported ar5211 2 GHz radios are rev 0x10 */
+
+       /* EEPROM Registers in the MAC */
+#define        AR_EEPROM_CMD_READ      0x00000001
+#define        AR_EEPROM_CMD_WRITE     0x00000002
+#define        AR_EEPROM_CMD_RESET     0x00000004
+
+#define        AR_EEPROM_STS_READ_ERROR        0x00000001
+#define        AR_EEPROM_STS_READ_COMPLETE     0x00000002
+#define        AR_EEPROM_STS_WRITE_ERROR       0x00000004
+#define        AR_EEPROM_STS_WRITE_COMPLETE    0x00000008
+
+#define        AR_EEPROM_CFG_SIZE_M    0x00000003      /* Mask for EEPROM size determination override */
+#define        AR_EEPROM_CFG_SIZE_AUTO 0
+#define        AR_EEPROM_CFG_SIZE_4KBIT        1
+#define        AR_EEPROM_CFG_SIZE_8KBIT        2
+#define        AR_EEPROM_CFG_SIZE_16KBIT       3
+#define        AR_EEPROM_CFG_DIS_WAIT_WRITE_COMPL      0x00000004      /* Disable wait for write completion */
+#define        AR_EEPROM_CFG_CLOCK_M   0x00000018      /* Mask for EEPROM clock rate control */
+#define        AR_EEPROM_CFG_CLOCK_S   3               /* Shift for EEPROM clock rate control */
+#define        AR_EEPROM_CFG_CLOCK_156KHZ      0
+#define        AR_EEPROM_CFG_CLOCK_312KHZ      1
+#define        AR_EEPROM_CFG_CLOCK_625KHZ      2
+#define        AR_EEPROM_CFG_RESV0     0x000000E0      /* Reserved */
+#define        AR_EEPROM_CFG_PROT_KEY_M        0x00FFFF00      /* Mask for EEPROM protection key */
+#define        AR_EEPROM_CFG_PROT_KEY_S        8               /* Shift for EEPROM protection key */
+#define        AR_EEPROM_CFG_EN_L      0x01000000      /* EPRM_EN_L setting */
+
+       /* MAC PCU Registers */
+#define        AR_STA_ID1_SADH_MASK    0x0000FFFF      /* Mask for upper 16 bits of MAC addr */
+#define        AR_STA_ID1_STA_AP       0x00010000      /* Device is AP */
+#define        AR_STA_ID1_ADHOC        0x00020000      /* Device is ad-hoc */
+#define        AR_STA_ID1_PWR_SAV      0x00040000      /* Power save reporting in self-generated frames */
+#define        AR_STA_ID1_KSRCHDIS     0x00080000      /* Key search disable */
+#define        AR_STA_ID1_PCF  0x00100000      /* Observe PCF */
+#define        AR_STA_ID1_DEFAULT_ANTENNA      0x00200000      /* Use default antenna */
+#define        AR_STA_ID1_DESC_ANTENNA 0x00400000      /* Update default antenna w/ TX antenna */
+#define        AR_STA_ID1_RTS_USE_DEF  0x00800000      /* Use default antenna to send RTS */
+#define        AR_STA_ID1_ACKCTS_6MB   0x01000000      /* Use 6Mb/s rate for ACK & CTS */
+#define        AR_STA_ID1_BASE_RATE_11B        0x02000000      /* Use 11b base rate for ACK & CTS */
+#define        AR_STA_ID1_BITS \
+       "\20\20AP\21ADHOC\22PWR_SAV\23KSRCHDIS\25PCF"
+
+#define        AR_BSS_ID1_U16_M        0x0000FFFF      /* Mask for upper 16 bits of BSSID */
+#define        AR_BSS_ID1_AID_M        0xFFFF0000      /* Mask for association ID */
+#define        AR_BSS_ID1_AID_S        16              /* Shift for association ID */
+
+#define        AR_SLOT_TIME_MASK       0x000007FF      /* Slot time mask */
+
+#define        AR_TIME_OUT_ACK         0x00001FFF      /* Mask for ACK time-out */
+#define        AR_TIME_OUT_ACK_S       0               /* Shift for ACK time-out */
+#define        AR_TIME_OUT_CTS         0x1FFF0000      /* Mask for CTS time-out */
+#define        AR_TIME_OUT_CTS_S       16              /* Shift for CTS time-out */
+
+#define        AR_RSSI_THR_MASK        0x000000FF      /* Mask for Beacon RSSI warning threshold */
+#define        AR_RSSI_THR_BM_THR      0x0000FF00      /* Mask for Missed beacon threshold */
+#define        AR_RSSI_THR_BM_THR_S    8               /* Shift for Missed beacon threshold */
+
+#define        AR_USEC_M       0x0000007F              /* Mask for clock cycles in 1 usec */
+#define        AR_USEC_32_M    0x00003F80              /* Mask for number of 32MHz clock cycles in 1 usec */
+#define        AR_USEC_32_S    7                       /* Shift for number of 32MHz clock cycles in 1 usec */
+/*
+ * Tx/Rx latencies are to signal start and are in usecs.
+ *
+ * NOTE: AR5211/AR5311 difference: on Oahu, the TX latency field
+ *       has increased from 6 bits to 9 bits.  The RX latency field
+ *      is unchanged, but is shifted over 3 bits.
+ */
+#define        AR5311_USEC_TX_LAT_M    0x000FC000      /* Tx latency */
+#define        AR5311_USEC_TX_LAT_S    14
+#define        AR5311_USEC_RX_LAT_M    0x03F00000      /* Rx latency */
+#define        AR5311_USEC_RX_LAT_S    20
+
+#define        AR5211_USEC_TX_LAT_M    0x007FC000      /* Tx latency */
+#define        AR5211_USEC_TX_LAT_S    14
+#define        AR5211_USEC_RX_LAT_M    0x1F800000      /* Rx latency */
+#define        AR5211_USEC_RX_LAT_S    23
+
+
+#define        AR_BEACON_PERIOD        0x0000FFFF      /* Beacon period in TU/msec */
+#define        AR_BEACON_PERIOD_S      0               /* Byte offset of PERIOD start*/
+#define        AR_BEACON_TIM           0x007F0000      /* Byte offset of TIM start */
+#define        AR_BEACON_TIM_S         16              /* Byte offset of TIM start */
+#define        AR_BEACON_EN            0x00800000      /* beacon enable */
+#define        AR_BEACON_RESET_TSF     0x01000000      /* Clears TSF to 0 */
+#define        AR_BEACON_BITS  "\20\27ENABLE\30RESET_TSF"
+
+#define        AR_RX_FILTER_ALL        0x00000000      /* Disallow all frames */
+#define        AR_RX_UCAST             0x00000001      /* Allow unicast frames */
+#define        AR_RX_MCAST             0x00000002      /* Allow multicast frames */
+#define        AR_RX_BCAST             0x00000004      /* Allow broadcast frames */
+#define        AR_RX_CONTROL           0x00000008      /* Allow control frames */
+#define        AR_RX_BEACON            0x00000010      /* Allow beacon frames */
+#define        AR_RX_PROM              0x00000020      /* Promiscuous mode */
+#define        AR_RX_PHY_ERR           0x00000040      /* Allow all phy errors */
+#define        AR_RX_PHY_RADAR         0x00000080      /* Allow radar phy errors */
+#define        AR_RX_FILTER_BITS \
+       "\20\1UCAST\2MCAST\3BCAST\4CONTROL\5BEACON\6PROMISC\7PHY_ERR\10PHY_RADAR"
+
+#define        AR_DIAG_SW_CACHE_ACK    0x00000001      /* disable ACK if no valid key*/
+#define        AR_DIAG_SW_DIS_ACK      0x00000002      /* disable ACK generation */
+#define        AR_DIAG_SW_DIS_CTS      0x00000004      /* disable CTS generation */
+#define        AR_DIAG_SW_DIS_ENCRYPT  0x00000008      /* disable encryption */
+#define        AR_DIAG_SW_DIS_DECRYPT  0x00000010      /* disable decryption */
+#define        AR_DIAG_SW_DIS_RX       0x00000020      /* disable receive */
+#define        AR_DIAG_SW_CORR_FCS     0x00000080      /* corrupt FCS */
+#define        AR_DIAG_SW_CHAN_INFO    0x00000100      /* dump channel info */
+#define        AR_DIAG_SW_EN_SCRAMSD   0x00000200      /* enable fixed scrambler seed*/
+#define        AR5311_DIAG_SW_USE_ECO  0x00000400      /* "super secret" use ECO enable bit */
+#define        AR_DIAG_SW_SCRAM_SEED_M 0x0001FC00      /* Fixed scrambler seed mask */
+#define        AR_DIAG_SW_SCRAM_SEED_S 10              /* Fixed scrambler seed shfit */
+#define        AR_DIAG_SW_FRAME_NV0    0x00020000      /* accept frames of non-zero protocol version */
+#define        AR_DIAG_SW_OBS_PT_SEL_M 0x000C0000      /* Observation point select */
+#define        AR_DIAG_SW_OBS_PT_SEL_S 18              /* Observation point select */
+#define        AR_DIAG_SW_BITS \
+       "\20\1DIS_CACHE_ACK\2DIS_ACK\3DIS_CTS\4DIS_ENC\5DIS_DEC\6DIS_RX"\
+       "\11CORR_FCS\12CHAN_INFO\13EN_SCRAM_SEED\14USE_ECO\24FRAME_NV0"
+
+#define        AR_KEYTABLE_KEY0(n)     (AR_KEYTABLE(n) + 0)    /* key bit 0-31 */
+#define        AR_KEYTABLE_KEY1(n)     (AR_KEYTABLE(n) + 4)    /* key bit 32-47 */
+#define        AR_KEYTABLE_KEY2(n)     (AR_KEYTABLE(n) + 8)    /* key bit 48-79 */
+#define        AR_KEYTABLE_KEY3(n)     (AR_KEYTABLE(n) + 12)   /* key bit 80-95 */
+#define        AR_KEYTABLE_KEY4(n)     (AR_KEYTABLE(n) + 16)   /* key bit 96-127 */
+#define        AR_KEYTABLE_TYPE(n)     (AR_KEYTABLE(n) + 20)   /* key type */
+#define        AR_KEYTABLE_TYPE_40     0x00000000      /* WEP 40 bit key */
+#define        AR_KEYTABLE_TYPE_104    0x00000001      /* WEP 104 bit key */
+#define        AR_KEYTABLE_TYPE_128    0x00000003      /* WEP 128 bit key */
+#define        AR_KEYTABLE_TYPE_AES    0x00000005      /* AES 128 bit key */
+#define        AR_KEYTABLE_TYPE_CLR    0x00000007      /* no encryption */
+#define        AR_KEYTABLE_MAC0(n)     (AR_KEYTABLE(n) + 24)   /* MAC address 1-32 */
+#define        AR_KEYTABLE_MAC1(n)     (AR_KEYTABLE(n) + 28)   /* MAC address 33-47 */
+#define        AR_KEYTABLE_VALID       0x00008000      /* key and MAC address valid */
+
+#endif /* _DEV_ATH_AR5211REG_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5211/boss.ini   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2006 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: boss.ini,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+/* Auto Generated PCI Register Writes.  Created: 09/12/02 */
+
+static const uint32_t ar5211Modes[][5] = {
+       { 0x00000030, 0x00000015, 0x00000015, 0x0000001d, 0x00000015 },
+       { 0x00001040, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x00001044, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x00001048, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x0000104c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x00001050, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x00001054, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x00001058, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x0000105c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x00001060, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x00001064, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f },
+       { 0x00001070, 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 },
+       { 0x00001030, 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 },
+       { 0x000010b0, 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 },
+       { 0x000010f0, 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 },
+       { 0x00008014, 0x04000400, 0x08000800, 0x20003000, 0x04000400 },
+       { 0x0000801c, 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 },
+       { 0x00009804, 0x00000000, 0x00000003, 0x00000000, 0x00000000 },
+       { 0x00009820, 0x02020200, 0x02020200, 0x02010200, 0x02020200 },
+       { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e },
+       { 0x00009828, 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 },
+       { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+       { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b },
+       { 0x00009844, 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c },
+       { 0x00009848, 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 },
+       { 0x00009850, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 },
+       { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e },
+       { 0x0000985c, 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e },
+       { 0x00009860, 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 },
+       { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+       { 0x00009914, 0x00002710, 0x00002710, 0x0000157c, 0x00002710 },
+       { 0x00009918, 0x00000190, 0x00000190, 0x00000084, 0x00000190 },
+       { 0x00009944, 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 },
+       { 0x0000a180, 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff },
+       { 0x000098d4, 0x00000010, 0x00000014, 0x00000010, 0x00000010 },
+};
+
+static const uint32_t ar5211Common[][2] = {
+       { 0x0000000c, 0x00000000 },
+       { 0x00000028, 0x84849c9c },
+       { 0x0000002c, 0x7c7c7c7c },
+       { 0x00000034, 0x00000005 },
+       { 0x00000040, 0x00000000 },
+       { 0x00000044, 0x00000008 },
+       { 0x00000048, 0x00000008 },
+       { 0x0000004c, 0x00000010 },
+       { 0x00000050, 0x00000000 },
+       { 0x00000054, 0x0000001f },
+       { 0x00000800, 0x00000000 },
+       { 0x00000804, 0x00000000 },
+       { 0x00000808, 0x00000000 },
+       { 0x0000080c, 0x00000000 },
+       { 0x00000810, 0x00000000 },
+       { 0x00000814, 0x00000000 },
+       { 0x00000818, 0x00000000 },
+       { 0x0000081c, 0x00000000 },
+       { 0x00000820, 0x00000000 },
+       { 0x00000824, 0x00000000 },
+       { 0x00001230, 0x00000000 },
+       { 0x00008004, 0x00000000 },
+       { 0x00008008, 0x00000000 },
+       { 0x0000800c, 0x00000000 },
+       { 0x00008018, 0x00000000 },
+       { 0x00008024, 0x00000000 },
+       { 0x00008028, 0x00000030 },
+       { 0x0000802c, 0x0007ffff },
+       { 0x00008030, 0x01ffffff },
+       { 0x00008034, 0x00000031 },
+       { 0x00008038, 0x00000000 },
+       { 0x0000803c, 0x00000000 },
+       { 0x00008040, 0x00000000 },
+       { 0x00008044, 0x00000002 },
+       { 0x00008048, 0x00000000 },
+       { 0x00008054, 0x00000000 },
+       { 0x00008058, 0x00000000 },
+       { 0x00009808, 0x00000000 },
+       { 0x0000980c, 0x2d849093 },
+       { 0x00009810, 0x7d32e000 },
+       { 0x00009814, 0x00000f6b },
+       { 0x0000981c, 0x00000000 },
+       { 0x0000982c, 0x00026ffe },
+       { 0x00009830, 0x00000000 },
+       { 0x0000983c, 0x00020100 },
+       { 0x00009840, 0x206a017a },
+       { 0x0000984c, 0x1284613c },
+       { 0x00009854, 0x00000859 },
+       { 0x00009868, 0x409a4190 },
+       { 0x0000986c, 0x050cb081 },
+       { 0x00009870, 0x0000000f },
+       { 0x00009874, 0x00000080 },
+       { 0x00009878, 0x0000000c },
+       { 0x00009900, 0x00000000 },
+       { 0x00009904, 0x00000000 },
+       { 0x00009908, 0x00000000 },
+       { 0x0000990c, 0x00800000 },
+       { 0x00009910, 0x00000001 },
+       { 0x0000991c, 0x0000092a },
+       { 0x00009920, 0x00000000 },
+       { 0x00009924, 0x00058a05 },
+       { 0x00009928, 0x00000001 },
+       { 0x0000992c, 0x00000000 },
+       { 0x00009930, 0x00000000 },
+       { 0x00009934, 0x00000000 },
+       { 0x00009938, 0x00000000 },
+       { 0x0000993c, 0x0000003f },
+       { 0x00009940, 0x00000004 },
+       { 0x00009948, 0x00000000 },
+       { 0x0000994c, 0x00000000 },
+       { 0x00009950, 0x00000000 },
+       { 0x00009954, 0x5d50f14c },
+       { 0x00009958, 0x00000018 },
+       { 0x0000995c, 0x004b6a8e },
+       { 0x0000a184, 0x06ff05ff },
+       { 0x0000a188, 0x07ff07ff },
+       { 0x0000a18c, 0x08ff08ff },
+       { 0x0000a190, 0x09ff09ff },
+       { 0x0000a194, 0x0aff0aff },
+       { 0x0000a198, 0x0bff0bff },
+       { 0x0000a19c, 0x0cff0cff },
+       { 0x0000a1a0, 0x0dff0dff },
+       { 0x0000a1a4, 0x0fff0eff },
+       { 0x0000a1a8, 0x12ff12ff },
+       { 0x0000a1ac, 0x14ff13ff },
+       { 0x0000a1b0, 0x16ff15ff },
+       { 0x0000a1b4, 0x19ff17ff },
+       { 0x0000a1b8, 0x1bff1aff },
+       { 0x0000a1bc, 0x1eff1dff },
+       { 0x0000a1c0, 0x23ff20ff },
+       { 0x0000a1c4, 0x27ff25ff },
+       { 0x0000a1c8, 0x2cff29ff },
+       { 0x0000a1cc, 0x31ff2fff },
+       { 0x0000a1d0, 0x37ff34ff },
+       { 0x0000a1d4, 0x3aff3aff },
+       { 0x0000a1d8, 0x3aff3aff },
+       { 0x0000a1dc, 0x3aff3aff },
+       { 0x0000a1e0, 0x3aff3aff },
+       { 0x0000a1e4, 0x3aff3aff },
+       { 0x0000a1e8, 0x3aff3aff },
+       { 0x0000a1ec, 0x3aff3aff },
+       { 0x0000a1f0, 0x3aff3aff },
+       { 0x0000a1f4, 0x3aff3aff },
+       { 0x0000a1f8, 0x3aff3aff },
+       { 0x0000a1fc, 0x3aff3aff },
+       { 0x00009b00, 0x00000000 },
+       { 0x00009b04, 0x00000020 },
+       { 0x00009b08, 0x00000010 },
+       { 0x00009b0c, 0x00000030 },
+       { 0x00009b10, 0x00000008 },
+       { 0x00009b14, 0x00000028 },
+       { 0x00009b18, 0x00000004 },
+       { 0x00009b1c, 0x00000024 },
+       { 0x00009b20, 0x00000014 },
+       { 0x00009b24, 0x00000034 },
+       { 0x00009b28, 0x0000000c },
+       { 0x00009b2c, 0x0000002c },
+       { 0x00009b30, 0x00000002 },
+       { 0x00009b34, 0x00000022 },
+       { 0x00009b38, 0x00000012 },
+       { 0x00009b3c, 0x00000032 },
+       { 0x00009b40, 0x0000000a },
+       { 0x00009b44, 0x0000002a },
+       { 0x00009b48, 0x00000006 },
+       { 0x00009b4c, 0x00000026 },
+       { 0x00009b50, 0x00000016 },
+       { 0x00009b54, 0x00000036 },
+       { 0x00009b58, 0x0000000e },
+       { 0x00009b5c, 0x0000002e },
+       { 0x00009b60, 0x00000001 },
+       { 0x00009b64, 0x00000021 },
+       { 0x00009b68, 0x00000011 },
+       { 0x00009b6c, 0x00000031 },
+       { 0x00009b70, 0x00000009 },
+       { 0x00009b74, 0x00000029 },
+       { 0x00009b78, 0x00000005 },
+       { 0x00009b7c, 0x00000025 },
+       { 0x00009b80, 0x00000015 },
+       { 0x00009b84, 0x00000035 },
+       { 0x00009b88, 0x0000000d },
+       { 0x00009b8c, 0x0000002d },
+       { 0x00009b90, 0x00000003 },
+       { 0x00009b94, 0x00000023 },
+       { 0x00009b98, 0x00000013 },
+       { 0x00009b9c, 0x00000033 },
+       { 0x00009ba0, 0x0000000b },
+       { 0x00009ba4, 0x0000002b },
+       { 0x00009ba8, 0x0000002b },
+       { 0x00009bac, 0x0000002b },
+       { 0x00009bb0, 0x0000002b },
+       { 0x00009bb4, 0x0000002b },
+       { 0x00009bb8, 0x0000002b },
+       { 0x00009bbc, 0x0000002b },
+       { 0x00009bc0, 0x0000002b },
+       { 0x00009bc4, 0x0000002b },
+       { 0x00009bc8, 0x0000002b },
+       { 0x00009bcc, 0x0000002b },
+       { 0x00009bd0, 0x0000002b },
+       { 0x00009bd4, 0x0000002b },
+       { 0x00009bd8, 0x0000002b },
+       { 0x00009bdc, 0x0000002b },
+       { 0x00009be0, 0x0000002b },
+       { 0x00009be4, 0x0000002b },
+       { 0x00009be8, 0x0000002b },
+       { 0x00009bec, 0x0000002b },
+       { 0x00009bf0, 0x0000002b },
+       { 0x00009bf4, 0x0000002b },
+       { 0x00009bf8, 0x00000002 },
+       { 0x00009bfc, 0x00000016 },
+       { 0x000098d4, 0x00000020 },
+       { 0x000098d8, 0x00601068 },
+};
+
+static uint32_t ar5211Mode2_4[][3] = {
+       { 0x0000a204, 0x00000000, 0x00000000 },
+       { 0x0000a208, 0x503e4646, 0x503e4646 },
+       { 0x0000a20c, 0x6480416c, 0x6480416c },
+       { 0x0000a210, 0x0199a003, 0x0199a003 },
+       { 0x0000a214, 0x044cd610, 0x044cd610 },
+       { 0x0000a218, 0x13800040, 0x13800040 },
+       { 0x0000a21c, 0x1be00060, 0x1be00060 },
+       { 0x0000a220, 0x0c53800a, 0x0c53800a },
+       { 0x0000a224, 0x0014df3b, 0x0014df3b },
+       { 0x0000a228, 0x000001b5, 0x000001b5 },
+       { 0x0000a22c, 0x00000020, 0x00000020 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00380000, 0x00380000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x000400f9, 0x000400f9 },
+       { 0x000098d4, 0x00000000, 0x00000004 },
+};
+
+static const uint32_t ar5211BB_RfGain[][3] = {
+       { 0x00009a00, 0x000001a9, 0x00000000 },
+       { 0x00009a04, 0x000001e9, 0x00000040 },
+       { 0x00009a08, 0x00000029, 0x00000080 },
+       { 0x00009a0c, 0x00000069, 0x00000150 },
+       { 0x00009a10, 0x00000199, 0x00000190 },
+       { 0x00009a14, 0x000001d9, 0x000001d0 },
+       { 0x00009a18, 0x00000019, 0x00000010 },
+       { 0x00009a1c, 0x00000059, 0x00000044 },
+       { 0x00009a20, 0x00000099, 0x00000084 },
+       { 0x00009a24, 0x000001a5, 0x00000148 },
+       { 0x00009a28, 0x000001e5, 0x00000188 },
+       { 0x00009a2c, 0x00000025, 0x000001c8 },
+       { 0x00009a30, 0x000001c8, 0x00000014 },
+       { 0x00009a34, 0x00000008, 0x00000042 },
+       { 0x00009a38, 0x00000048, 0x00000082 },
+       { 0x00009a3c, 0x00000088, 0x00000178 },
+       { 0x00009a40, 0x00000198, 0x000001b8 },
+       { 0x00009a44, 0x000001d8, 0x000001f8 },
+       { 0x00009a48, 0x00000018, 0x00000012 },
+       { 0x00009a4c, 0x00000058, 0x00000052 },
+       { 0x00009a50, 0x00000098, 0x00000092 },
+       { 0x00009a54, 0x000001a4, 0x0000017c },
+       { 0x00009a58, 0x000001e4, 0x000001bc },
+       { 0x00009a5c, 0x00000024, 0x000001fc },
+       { 0x00009a60, 0x00000064, 0x0000000a },
+       { 0x00009a64, 0x000000a4, 0x0000004a },
+       { 0x00009a68, 0x000000e4, 0x0000008a },
+       { 0x00009a6c, 0x0000010a, 0x0000015a },
+       { 0x00009a70, 0x0000014a, 0x0000019a },
+       { 0x00009a74, 0x0000018a, 0x000001da },
+       { 0x00009a78, 0x000001ca, 0x0000000e },
+       { 0x00009a7c, 0x0000000a, 0x0000004e },
+       { 0x00009a80, 0x0000004a, 0x0000008e },
+       { 0x00009a84, 0x0000008a, 0x0000015e },
+       { 0x00009a88, 0x000001ba, 0x0000019e },
+       { 0x00009a8c, 0x000001fa, 0x000001de },
+       { 0x00009a90, 0x0000003a, 0x00000009 },
+       { 0x00009a94, 0x0000007a, 0x00000049 },
+       { 0x00009a98, 0x00000186, 0x00000089 },
+       { 0x00009a9c, 0x000001c6, 0x00000179 },
+       { 0x00009aa0, 0x00000006, 0x000001b9 },
+       { 0x00009aa4, 0x00000046, 0x000001f9 },
+       { 0x00009aa8, 0x00000086, 0x00000039 },
+       { 0x00009aac, 0x000000c6, 0x00000079 },
+       { 0x00009ab0, 0x000000c6, 0x000000b9 },
+       { 0x00009ab4, 0x000000c6, 0x000001bd },
+       { 0x00009ab8, 0x000000c6, 0x000001fd },
+       { 0x00009abc, 0x000000c6, 0x0000003d },
+       { 0x00009ac0, 0x000000c6, 0x0000007d },
+       { 0x00009ac4, 0x000000c6, 0x000000bd },
+       { 0x00009ac8, 0x000000c6, 0x000000fd },
+       { 0x00009acc, 0x000000c6, 0x000000fd },
+       { 0x00009ad0, 0x000000c6, 0x000000fd },
+       { 0x00009ad4, 0x000000c6, 0x000000fd },
+       { 0x00009ad8, 0x000000c6, 0x000000fd },
+       { 0x00009adc, 0x000000c6, 0x000000fd },
+       { 0x00009ae0, 0x000000c6, 0x000000fd },
+       { 0x00009ae4, 0x000000c6, 0x000000fd },
+       { 0x00009ae8, 0x000000c6, 0x000000fd },
+       { 0x00009aec, 0x000000c6, 0x000000fd },
+       { 0x00009af0, 0x000000c6, 0x000000fd },
+       { 0x00009af4, 0x000000c6, 0x000000fd },
+       { 0x00009af8, 0x000000c6, 0x000000fd },
+       { 0x00009afc, 0x000000c6, 0x000000fd },
+};
+
+static uint32_t ar5211Rf6n7[][3] = {
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x10000000, 0x10000000 },
+       { 0x0000989c, 0x04000000, 0x04000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x00000000 },
+       { 0x0000989c, 0x00000000, 0x0a000000 },
+       { 0x0000989c, 0x00380080, 0x02380080 },
+       { 0x0000989c, 0x00020006, 0x00000006 },
+       { 0x0000989c, 0x00000092, 0x00000092 },
+       { 0x0000989c, 0x000000a0, 0x000000a0 },
+       { 0x0000989c, 0x00040007, 0x00040007 },
+       { 0x000098d4, 0x0000001a, 0x0000001a },
+       { 0x0000989c, 0x00000048, 0x00000048 },
+       { 0x0000989c, 0x00000010, 0x00000010 },
+       { 0x0000989c, 0x00000008, 0x00000008 },
+       { 0x0000989c, 0x0000000f, 0x0000000f },
+       { 0x0000989c, 0x000000f2, 0x00000062 },
+       { 0x0000989c, 0x0000904f, 0x0000904c },
+       { 0x0000989c, 0x0000125a, 0x0000129a },
+       { 0x000098cc, 0x0000000e, 0x0000000f },
+};
+
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312.h   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _ATH_AR5312_H_
+#define _ATH_AR5312_H_
+
+#include "ah_soc.h"
+#include "ar5212/ar5212.h"
+
+#define AR5312_UNIT(_ah) \
+       (((const struct ar531x_config *)((_ah)->ah_st))->unit)
+#define AR5312_BOARDCONFIG(_ah) \
+       (((const struct ar531x_config *)((_ah)->ah_st))->board)
+#define AR5312_RADIOCONFIG(_ah) \
+       (((const struct ar531x_config *)((_ah)->ah_st))->radio)
+
+#define        IS_5312_2_X(ah) \
+       (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && \
+        (AH_PRIVATE(ah)->ah_macRev == 2 || AH_PRIVATE(ah)->ah_macRev == 7))
+#define IS_5315(ah) \
+       (AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV6 || \
+        AH_PRIVATE(ah)->ah_devid == AR5212_AR2315_REV7 || \
+        AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1 || \
+        AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2)
+
+extern  HAL_BOOL ar5312IsInterruptPending(struct ath_hal *ah);
+
+/* AR5312 */
+extern HAL_BOOL ar5312GpioCfgOutput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5312GpioCfgInput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5312GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val);
+extern uint32_t ar5312GpioGet(struct ath_hal *ah, uint32_t gpio);
+extern void ar5312GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel);
+
+/* AR2315+ */
+extern HAL_BOOL ar5315GpioCfgOutput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5315GpioCfgInput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5315GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val);
+extern uint32_t ar5315GpioGet(struct ath_hal *ah, uint32_t gpio);
+extern void ar5315GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel);
+
+extern  void ar5312SetLedState(struct ath_hal *ah, HAL_LED_STATE state);
+extern  HAL_BOOL ar5312DetectCardPresent(struct ath_hal *ah);
+extern  void ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode);
+extern  void ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode);
+extern  void ar5312DumpState(struct ath_hal *ah);
+extern  HAL_BOOL ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+              HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status);
+extern  HAL_BOOL ar5312ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan);
+extern  HAL_BOOL ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
+                                    int setChip);
+extern  HAL_BOOL ar5312PhyDisable(struct ath_hal *ah);
+extern  HAL_BOOL ar5312Disable(struct ath_hal *ah);
+extern  HAL_BOOL ar5312MacReset(struct ath_hal *ah, unsigned int RCMask);
+extern  uint32_t ar5312GetPowerMode(struct ath_hal *ah);
+extern  HAL_BOOL ar5312GetPowerStatus(struct ath_hal *ah);
+
+/* BSP functions */
+extern HAL_BOOL ar5312EepromRead(struct ath_hal *, u_int off, uint16_t *data);
+extern HAL_BOOL ar5312EepromWrite(struct ath_hal *, u_int off, uint16_t data);
+
+#endif /* _ATH_AR3212_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312_attach.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312_attach.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5312/ar5312.h"
+#include "ar5312/ar5312reg.h"
+#include "ar5312/ar5312phy.h"
+
+/* Add static register initialization vectors */
+#define AH_5212_COMMON
+#include "ar5212/ar5212.ini"
+
+static  HAL_BOOL ar5312GetMacAddr(struct ath_hal *ah);
+
+static void
+ar5312AniSetup(struct ath_hal *ah)
+{
+       static const struct ar5212AniParams aniparams = {
+               .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
+               .totalSizeDesired       = { -41, -41, -48, -48, -48 },
+               .coarseHigh             = { -18, -18, -16, -14, -12 },
+               .coarseLow              = { -56, -56, -60, -60, -60 },
+               .firpwr                 = { -72, -72, -75, -78, -80 },
+               .maxSpurImmunityLevel   = 2,
+               .cycPwrThr1             = { 2, 4, 6 },
+               .maxFirstepLevel        = 2,    /* levels 0..2 */
+               .firstep                = { 0, 4, 8 },
+               .ofdmTrigHigh           = 500,
+               .ofdmTrigLow            = 200,
+               .cckTrigHigh            = 200,
+               .cckTrigLow             = 100,
+               .rssiThrHigh            = 40,
+               .rssiThrLow             = 7,
+               .period                 = 100,
+       };
+       ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
+}
+
+/*
+ * Attach for an AR5312 part.
+ */
+static struct ath_hal *
+ar5312Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH_NULL;
+       struct ath_hal *ah;
+       struct ath_hal_rf *rf;
+       uint32_t val;
+       uint16_t eeval;
+       HAL_STATUS ecode;
+
+       HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
+                __func__, sc, st, (void*) sh);
+
+       /* NB: memory is returned zero'd */
+       ahp = ath_hal_malloc(sizeof (struct ath_hal_5212));
+       if (ahp == AH_NULL) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                   "%s: cannot allocate memory for state block\n", __func__);
+               *status = HAL_ENOMEM;
+               return AH_NULL;
+       }
+       ar5212InitState(ahp, devid, sc, st, sh, status);
+       ah = &ahp->ah_priv.h;
+
+       /* override 5212 methods for our needs */
+       ah->ah_reset                    = ar5312Reset;
+       ah->ah_phyDisable               = ar5312PhyDisable;
+       ah->ah_setLedState              = ar5312SetLedState;
+       ah->ah_detectCardPresent        = ar5312DetectCardPresent;
+       ah->ah_setPowerMode             = ar5312SetPowerMode;
+       ah->ah_getPowerMode             = ar5312GetPowerMode;
+       ah->ah_isInterruptPending       = ar5312IsInterruptPending;
+
+       ahp->ah_priv.ah_eepromRead      = ar5312EepromRead;
+#ifdef AH_SUPPORT_WRITE_EEPROM
+       ahp->ah_priv.ah_eepromWrite     = ar5312EepromWrite;
+#endif
+#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317)
+       if (IS_5315(ah)) {
+               ahp->ah_priv.ah_gpioCfgOutput   = ar5315GpioCfgOutput;
+               ahp->ah_priv.ah_gpioCfgInput    = ar5315GpioCfgInput;
+               ahp->ah_priv.ah_gpioGet         = ar5315GpioGet;
+               ahp->ah_priv.ah_gpioSet         = ar5315GpioSet;
+               ahp->ah_priv.ah_gpioSetIntr     = ar5315GpioSetIntr;
+       } else
+#endif
+       {
+               ahp->ah_priv.ah_gpioCfgOutput   = ar5312GpioCfgOutput;
+               ahp->ah_priv.ah_gpioCfgInput    = ar5312GpioCfgInput;
+               ahp->ah_priv.ah_gpioGet         = ar5312GpioGet;
+               ahp->ah_priv.ah_gpioSet         = ar5312GpioSet;
+               ahp->ah_priv.ah_gpioSetIntr     = ar5312GpioSetIntr;
+       }
+
+       ah->ah_gpioCfgInput             = ahp->ah_priv.ah_gpioCfgInput;
+       ah->ah_gpioCfgOutput            = ahp->ah_priv.ah_gpioCfgOutput;
+       ah->ah_gpioGet                  = ahp->ah_priv.ah_gpioGet;
+       ah->ah_gpioSet                  = ahp->ah_priv.ah_gpioSet;
+       ah->ah_gpioSetIntr              = ahp->ah_priv.ah_gpioSetIntr;
+
+       /* setup common ini data; rf backends handle remainder */
+       HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6);
+       HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 6);
+
+       if (!ar5312ChipReset(ah, AH_NULL)) {    /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317)
+       if ((devid == AR5212_AR2315_REV6) ||
+           (devid == AR5212_AR2315_REV7) ||
+           (devid == AR5212_AR2317_REV1) ||
+           (devid == AR5212_AR2317_REV2) ) {
+               val = ((OS_REG_READ(ah, (AR5315_RSTIMER_BASE -((uint32_t) sh)) + AR5315_WREV)) >> AR5315_WREV_S)
+                       & AR5315_WREV_ID;
+               AH_PRIVATE(ah)->ah_macVersion = val >> AR5315_WREV_ID_S;
+               AH_PRIVATE(ah)->ah_macRev = val & AR5315_WREV_REVISION;
+               HALDEBUG(ah, HAL_DEBUG_ATTACH,
+                   "%s: Mac Chip Rev 0x%02x.%x\n" , __func__,
+                   AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev);
+       } else
+#endif
+       {
+               val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0020);
+               val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0080);
+               /* Read Revisions from Chips */
+               val = ((OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + AR5312_WREV)) >> AR5312_WREV_S) & AR5312_WREV_ID;
+               AH_PRIVATE(ah)->ah_macVersion = val >> AR5312_WREV_ID_S;
+               AH_PRIVATE(ah)->ah_macRev = val & AR5312_WREV_REVISION;
+       }
+       /* XXX - THIS IS WRONG. NEEDS TO BE FIXED */
+       if (((AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE &&
+              AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE) ||
+             AH_PRIVATE(ah)->ah_macRev < AR_SREV_D2PLUS) &&
+              AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_COBRA) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s: Mac Chip Rev 0x%02x.%x is not supported by "
+                         "this driver\n", __func__,
+                         AH_PRIVATE(ah)->ah_macVersion,
+                         AH_PRIVATE(ah)->ah_macRev);
+#endif
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+       }
+
+       AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
+
+       if (!ar5212ChipTest(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
+                   __func__);
+               ecode = HAL_ESELFTEST;
+               goto bad;
+       }
+
+       /*
+        * Set correct Baseband to analog shift
+        * setting to access analog chips.
+        */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       /* Read Radio Chip Rev Extract */
+       AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
+
+       rf = ath_hal_rfprobe(ah, &ecode);
+       if (rf == AH_NULL)
+               goto bad;
+       if (IS_RAD5112(ah) && !IS_RADX112_REV2(ah)) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s: 5112 Rev 1 is not supported by this "
+                         "driver (analog5GhzRev 0x%x)\n", __func__,
+                         AH_PRIVATE(ah)->ah_analog5GhzRev);
+#endif
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+       }
+
+       ecode = ath_hal_legacyEepromAttach(ah);
+       if (ecode != HAL_OK) {
+               goto bad;
+       }
+
+       /*
+        * If Bmode and AR5212, verify 2.4 analog exists
+        */
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) &&
+           (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) {
+               /*
+                * Set correct Baseband to analog shift
+                * setting to access analog chips.
+                */
+               OS_REG_WRITE(ah, AR_PHY(0), 0x00004007);
+               OS_DELAY(2000);
+               AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah);
+
+               /* Set baseband for 5GHz chip */
+               OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+               OS_DELAY(2000);
+               if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) {
+#ifdef AH_DEBUG
+                       ath_hal_printf(ah, "%s: 2G Radio Chip Rev 0x%02X is not "
+                               "supported by this driver\n", __func__,
+                               AH_PRIVATE(ah)->ah_analog2GhzRev);
+#endif
+                       ecode = HAL_ENOTSUPP;
+                       goto bad;
+               }
+       }
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot read regulatory domain from EEPROM\n",
+                   __func__);
+               goto bad;
+        }
+       AH_PRIVATE(ah)->ah_currentRD = eeval;
+       /* XXX record serial number */
+
+       /* XXX other capabilities */
+       /*
+        * Got everything we need now to setup the capabilities.
+        */
+       if (!ar5212FillCapabilityInfo(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: failed ar5212FillCapabilityInfo\n", __func__);
+               ecode = HAL_EEREAD;
+               goto bad;
+       }
+
+       if (!rf->attach(ah, &ecode)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
+                   __func__, ecode);
+               goto bad;
+       }
+       /* arrange a direct call instead of thunking */
+       AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust;
+
+       /* Initialize gain ladder thermal calibration structure */
+       ar5212InitializeGainValues(ah);
+
+        /* BSP specific call for MAC address of this WMAC device */
+        if (!ar5312GetMacAddr(ah)) {
+                ecode = HAL_EEBADMAC;
+                goto bad;
+        }
+
+       ar5312AniSetup(ah);
+       ar5212InitNfCalHistBuffer(ah);
+
+       /* XXX EAR stuff goes here */
+       return ah;
+
+bad:
+       if (ahp)
+               ar5212Detach((struct ath_hal *) ahp);
+       if (status)
+               *status = ecode;
+       return AH_NULL;
+}
+
+static HAL_BOOL
+ar5312GetMacAddr(struct ath_hal *ah)
+{
+       const struct ar531x_boarddata *board = AR5312_BOARDCONFIG(ah);
+        int wlanNum = AR5312_UNIT(ah);
+        const uint8_t *macAddr;
+
+       switch (wlanNum) {
+       case 0:
+               macAddr = board->wlan0Mac;
+               break;
+       case 1:
+               macAddr = board->wlan1Mac;
+               break;
+       default:
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "Invalid WLAN wmac index (%d)\n",
+                              wlanNum);
+#endif
+               return AH_FALSE;
+       }
+       OS_MEMCPY(AH5212(ah)->ah_macaddr, macAddr, 6);
+       return AH_TRUE;
+}
+
+static const char*
+ar5312Probe(uint16_t vendorid, uint16_t devid)
+{
+       if (vendorid == ATHEROS_VENDOR_ID) {
+               switch (devid) {
+               case AR5212_AR5312_REV2:
+               case AR5212_AR5312_REV7:
+                       return "Atheros 5312 WiSoC";
+               case AR5212_AR2313_REV8:
+                       return "Atheros 2313 WiSoC";
+               case AR5212_AR2315_REV6:
+               case AR5212_AR2315_REV7:
+                       return "Atheros 2315 WiSoC";
+               case AR5212_AR2317_REV1:
+                       return "Atheros 2317 WiSoC";
+               case AR5212_AR2413:
+                       return "Atheros 2413";
+               case AR5212_AR2417:
+                       return "Atheros 2417";
+               }
+       }
+       return AH_NULL;
+}
+AH_CHIP(AR5312, ar5312Probe, ar5312Attach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312_eeprom.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312_eeprom.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+
+#ifdef AH_SUPPORT_AR5312
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5312/ar5312.h"
+#include "ar5312/ar5312reg.h"
+#include "ar5212/ar5212desc.h"
+
+/*
+ * Read 16 bits of data from offset into *data
+ */
+HAL_BOOL
+ar5312EepromRead(struct ath_hal *ah, u_int off, uint16_t *dataIn)
+{
+        int i,offset;
+       const char *eepromAddr = AR5312_RADIOCONFIG(ah);
+       uint8_t *data;
+
+       data = (uint8_t *) dataIn;
+       for (i=0,offset=2*off; i<2; i++,offset++) {
+               data[i] = eepromAddr[offset];
+       }
+        return AH_TRUE;
+}
+#endif /* AH_SUPPORT_AR5312 */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312_gpio.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312_gpio.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#ifdef AH_SUPPORT_AR5312
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5312/ar5312.h"
+#include "ar5312/ar5312reg.h"
+#include "ar5312/ar5312phy.h"
+
+#define        AR_NUM_GPIO     6               /* 6 GPIO pins */
+#define        AR5312_GPIOD_MASK       0x0000002F      /* GPIO data reg r/w mask */
+
+/*
+ * Configure GPIO Output lines
+ */
+HAL_BOOL
+ar5312GpioCfgOutput(struct ath_hal *ah, uint32_t gpio)
+{
+       uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR,
+                 (OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR) &~ AR_GPIOCR_CR_A(gpio))
+               | AR_GPIOCR_CR_A(gpio));
+
+       return AH_TRUE;
+}
+
+/*
+ * Configure GPIO Input lines
+ */
+HAL_BOOL
+ar5312GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
+{
+       uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR,
+                 (OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR) &~ AR_GPIOCR_CR_A(gpio))
+               | AR_GPIOCR_CR_N(gpio));
+
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - set output lines
+ */
+HAL_BOOL
+ar5312GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
+{
+       uint32_t reg;
+        uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       reg =  OS_REG_READ(ah, gpioOffset+AR5312_GPIODO);
+       reg &= ~(1 << gpio);
+       reg |= (val&1) << gpio;
+
+       OS_REG_WRITE(ah, gpioOffset+AR5312_GPIODO, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - get input lines
+ */
+uint32_t
+ar5312GpioGet(struct ath_hal *ah, uint32_t gpio)
+{
+       uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       if (gpio < AR_NUM_GPIO) {
+               uint32_t val = OS_REG_READ(ah, gpioOffset+AR5312_GPIODI);
+               val = ((val & AR5312_GPIOD_MASK) >> gpio) & 0x1;
+               return val;
+       } else {
+               return 0xffffffff;
+       }
+}
+
+/*
+ * Set the GPIO Interrupt
+ */
+void
+ar5312GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
+{
+       uint32_t val;
+        uint32_t gpioOffset = (AR5312_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       /* XXX bounds check gpio */
+       val = OS_REG_READ(ah, gpioOffset+AR5312_GPIOCR);
+       val &= ~(AR_GPIOCR_CR_A(gpio) |
+                AR_GPIOCR_INT_MASK | AR_GPIOCR_INT_ENA | AR_GPIOCR_INT_SEL);
+       val |= AR_GPIOCR_CR_N(gpio) | AR_GPIOCR_INT(gpio) | AR_GPIOCR_INT_ENA;
+       if (ilevel)
+               val |= AR_GPIOCR_INT_SELH;      /* interrupt on pin high */
+       else
+               val |= AR_GPIOCR_INT_SELL;      /* interrupt on pin low */
+
+       /* Don't need to change anything for low level interrupt. */
+       OS_REG_WRITE(ah, gpioOffset+AR5312_GPIOCR, val);
+
+       /* Change the interrupt mask. */
+       (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO);
+}
+
+
+#endif /* AH_SUPPORT_AR5312 */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312_interrupts.c        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312_interrupts.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#ifdef AH_SUPPORT_AR5312
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5312/ar5312.h"
+#include "ar5312/ar5312reg.h"
+#include "ar5312/ar5312phy.h"
+
+
+/*
+ * Checks to see if an interrupt is pending on our NIC
+ *
+ * Returns: TRUE    if an interrupt is pending
+ *          FALSE   if not
+ */
+HAL_BOOL
+ar5312IsInterruptPending(struct ath_hal *ah)
+{
+        /*
+         * Some platforms trigger our ISR before applying power to
+         * the card.  For the 5312, this is always true.
+         */
+
+       return(AH_TRUE);
+}
+#endif /* AH_SUPPORT_AR5312 */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312_misc.c      2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312_misc.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#ifdef AH_SUPPORT_AR5312
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5312/ar5312.h"
+#include "ar5312/ar5312reg.h"
+#include "ar5312/ar5312phy.h"
+
+#define        AR_NUM_GPIO     6               /* 6 GPIO pins */
+#define        AR_GPIOD_MASK   0x0000002F      /* GPIO data reg r/w mask */
+
+/*
+ * Change the LED blinking pattern to correspond to the connectivity
+ */
+void
+ar5312SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
+{
+       uint32_t val;
+       uint32_t resOffset = (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh));
+    if(IS_2316(ah)) return; /* not yet */
+       val = SM(AR5312_PCICFG_LEDSEL0, AR5312_PCICFG_LEDSEL) |
+               SM(AR5312_PCICFG_LEDMOD0, AR5312_PCICFG_LEDMODE) |
+               2;
+       OS_REG_WRITE(ah, resOffset+AR5312_PCICFG,
+               (OS_REG_READ(ah, AR5312_PCICFG) &~
+                (AR5312_PCICFG_LEDSEL | AR5312_PCICFG_LEDMODE |
+                 AR5312_PCICFG_LEDSBR))
+                    | val);
+}
+
+/*
+ * Detect if our wireless mac is present.
+ */
+HAL_BOOL
+ar5312DetectCardPresent(struct ath_hal *ah)
+{
+       uint16_t macVersion, macRev;
+       uint32_t v;
+
+       /*
+        * Read the Silicon Revision register and compare that
+        * to what we read at attach time.  If the same, we say
+        * a card/device is present.
+        */
+#if (AH_SUPPORT_2316 || AH_SUPPORT_2317)
+    if(IS_5315(ah))
+    {
+               v = (OS_REG_READ(ah,
+                         (AR5315_RSTIMER_BASE-((uint32_t) ah->ah_sh)) + AR5315_WREV))
+                       & AR_SREV_ID;
+               macVersion = v >> AR_SREV_ID_S;
+               macRev = v & AR_SREV_REVISION;
+               return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
+                               AH_PRIVATE(ah)->ah_macRev == macRev);
+    }
+    else
+#endif
+    {
+               v = (OS_REG_READ(ah,
+                         (AR5312_RSTIMER_BASE-((uint32_t) ah->ah_sh)) + AR5312_WREV))
+                       & AR_SREV_ID;
+               macVersion = v >> AR_SREV_ID_S;
+               macRev = v & AR_SREV_REVISION;
+               return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
+                               AH_PRIVATE(ah)->ah_macRev == macRev);
+    }
+}
+
+/*
+ * If 32KHz clock exists, use it to lower power consumption during sleep
+ *
+ * Note: If clock is set to 32 KHz, delays on accessing certain
+ *       baseband registers (27-31, 124-127) are required.
+ */
+void
+ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode)
+{
+       if (ar5212Use32KHzclock(ah, opmode)) {
+               /*
+                * Enable clocks to be turned OFF in BB during sleep
+                * and also enable turning OFF 32MHz/40MHz Refclk
+                * from A2.
+                */
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x0d);
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0c);
+               OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x03);
+               OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0x05);
+               OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
+                   IS_RAD5112_ANY(ah) ? 0x14 : 0x18);
+
+               OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1);
+               OS_REG_WRITE(ah, AR_TSF_PARM, 61);      /* 32 KHz TSF incr */
+
+       } else {
+               OS_REG_WRITE(ah, AR_TSF_PARM, 1);       /* 32 MHz TSF incr */
+               OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
+                   IS_RAD5112_ANY(ah) ? 39 : 31);
+
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x7f);
+
+               if (IS_5312_2_X(ah)) {
+                       /* Set ADC/DAC select values */
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x04);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0e);
+                       OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x0c);
+                       OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0xff);
+                       OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
+                           IS_RAD5112_ANY(ah) ? 0x14 : 0x18);
+               }
+       }
+}
+
+/*
+ * If 32KHz clock exists, turn it off and turn back on the 32Mhz
+ */
+void
+ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode)
+{
+       if (ar5212Use32KHzclock(ah, opmode)) {
+               /* # Set sleep clock rate back to 32 MHz. */
+               OS_REG_WRITE(ah, AR_TSF_PARM, 1);       /* 32 MHz TSF incr */
+               OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
+                   IS_RAD5112_ANY(ah) ? 39 : 31);
+
+               /*
+                * Restore BB registers to power-on defaults
+                */
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x7f);
+               if (IS_5312_2_X(ah)) {
+                       /* Set ADC/DAC select values */
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x04);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0e);
+                       OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x0c);
+                       OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0xff);
+                       OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
+                           IS_RAD5112_ANY(ah) ? 0x14 : 0x18);
+               }
+       }
+}
+
+#endif /* AH_SUPPORT_AR5312 */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312_power.c     2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312_power.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#ifdef AH_SUPPORT_AR5312
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5312/ar5312.h"
+#include "ar5312/ar5312reg.h"
+#include "ar5212/ar5212desc.h"
+
+/*
+ * Notify Power Mgt is enabled in self-generated frames.
+ * If requested, force chip awake.
+ *
+ * Returns A_OK if chip is awake or successfully forced awake.
+ *
+ * WARNING WARNING WARNING
+ * There is a problem with the chip where sometimes it will not wake up.
+ */
+static HAL_BOOL
+ar5312SetPowerModeAwake(struct ath_hal *ah, int setChip)
+{
+        /* No need for this at the moment for APs */
+       return AH_TRUE;
+}
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
+static void
+ar5312SetPowerModeSleep(struct ath_hal *ah, int setChip)
+{
+        /* No need for this at the moment for APs */
+}
+
+/*
+ * Notify Power Management is enabled in self-generating
+ * fames.  If request, set power mode of chip to
+ * auto/normal.  Duration in units of 128us (1/8 TU).
+ */
+static void
+ar5312SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
+{
+        /* No need for this at the moment for APs */
+}
+
+/*
+ * Set power mgt to the requested mode, and conditionally set
+ * the chip as well
+ */
+HAL_BOOL
+ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+#ifdef AH_DEBUG
+       static const char* modes[] = {
+               "AWAKE",
+               "FULL-SLEEP",
+               "NETWORK SLEEP",
+               "UNDEFINED"
+       };
+#endif
+       int status = AH_TRUE;
+
+       HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
+               modes[ahp->ah_powerMode], modes[mode],
+               setChip ? "set chip " : "");
+       switch (mode) {
+       case HAL_PM_AWAKE:
+               status = ar5312SetPowerModeAwake(ah, setChip);
+               break;
+       case HAL_PM_FULL_SLEEP:
+               ar5312SetPowerModeSleep(ah, setChip);
+               break;
+       case HAL_PM_NETWORK_SLEEP:
+               ar5312SetPowerModeNetworkSleep(ah, setChip);
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_POWER, "%s: unknown power mode %u\n",
+                   __func__, mode);
+               return AH_FALSE;
+       }
+       ahp->ah_powerMode = mode;
+       return status;
+}
+
+/*
+ * Return the current sleep mode of the chip
+ */
+uint32_t
+ar5312GetPowerMode(struct ath_hal *ah)
+{
+       return HAL_PM_AWAKE;
+}
+
+/*
+ * Return the current sleep state of the chip
+ * TRUE = sleeping
+ */
+HAL_BOOL
+ar5312GetPowerStatus(struct ath_hal *ah)
+{
+        return 0;              /* Currently, 5312 is never in sleep mode. */
+}
+#endif /* AH_SUPPORT_AR5312 */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312_reset.c     2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,919 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312_reset.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#ifdef AH_SUPPORT_AR5312
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5312/ar5312.h"
+#include "ar5312/ar5312reg.h"
+#include "ar5312/ar5312phy.h"
+
+#include "ah_eeprom_v3.h"
+
+/* Additional Time delay to wait after activiting the Base band */
+#define BASE_ACTIVATE_DELAY    100     /* 100 usec */
+#define PLL_SETTLE_DELAY       300     /* 300 usec */
+
+extern int16_t ar5212GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+extern void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *);
+extern HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah,
+                      HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain);
+extern void ar5212SetDeltaSlope(struct ath_hal *, HAL_CHANNEL *);
+extern HAL_BOOL ar5212SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+extern void ar5212SetIFSTiming(struct ath_hal *, HAL_CHANNEL *);
+extern HAL_BOOL        ar5212IsSpurChannel(struct ath_hal *, HAL_CHANNEL *);
+extern HAL_BOOL        ar5212ChannelChange(struct ath_hal *, HAL_CHANNEL *);
+
+static HAL_BOOL ar5312SetResetReg(struct ath_hal *, uint32_t resetMask);
+
+static int
+write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
+       HAL_BOOL bChannelChange, int writes)
+{
+#define IS_NO_RESET_TIMER_ADDR(x)                      \
+    ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \
+      (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3)))
+#define        V(r, c) (ia)->data[((r)*(ia)->cols) + (c)]
+       int i;
+
+       /* Write Common Array Parameters */
+       for (i = 0; i < ia->rows; i++) {
+               uint32_t reg = V(i, 0);
+               /* XXX timer/beacon setup registers? */
+               /* On channel change, don't reset the PCU registers */
+               if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) {
+                       OS_REG_WRITE(ah, reg, V(i, 1));
+                       DMA_YIELD(writes);
+               }
+       }
+       return writes;
+#undef IS_NO_RESET_TIMER_ADDR
+#undef V
+}
+
+/*
+ * Places the device in and out of reset and then places sane
+ * values in the registers based on EEPROM config, initialization
+ * vectors (as determined by the mode), and station configuration
+ *
+ * bChannelChange is used to preserve DMA/PCU registers across
+ * a HW Reset during channel change.
+ */
+HAL_BOOL
+ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+       HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+#define        FAIL(_code)     do { ecode = _code; goto bad; } while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *ichan;
+       const HAL_EEPROM *ee;
+       uint32_t saveFrameSeqCount, saveDefAntenna;
+       uint32_t macStaId1, synthDelay, txFrm2TxDStart;
+       uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
+       int16_t cckOfdmPwrDelta = 0;
+       u_int modesIndex, freqIndex;
+       HAL_STATUS ecode;
+       int i, regWrites = 0;
+       uint32_t testReg;
+       uint32_t saveLedState = 0;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+       ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       OS_MARK(ah, AH_MARK_RESET, bChannelChange);
+#define        IS(_c,_f)       (((_c)->channelFlags & _f) || 0)
+       if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+#undef IS
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       switch (opmode) {
+       case HAL_M_STA:
+       case HAL_M_IBSS:
+       case HAL_M_HOSTAP:
+       case HAL_M_MONITOR:
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
+                   __func__, opmode);
+               FAIL(HAL_EINVAL);
+               break;
+       }
+       HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3);
+
+       /* Preserve certain DMA hardware registers on a channel change */
+       if (bChannelChange) {
+               /*
+                * On Venice, the TSF is almost preserved across a reset;
+                * it requires the doubling writes to the RESET_TSF
+                * bit in the AR_BEACON register; it also has the quirk
+                * of the TSF going back in time on the station (station
+                * latches onto the last beacon's tsf during a reset 50%
+                * of the times); the latter is not a problem for adhoc
+                * stations since as long as the TSF is behind, it will
+                * get resynchronized on receiving the next beacon; the
+                * TSF going backwards in time could be a problem for the
+                * sleep operation (supported on infrastructure stations
+                * only) - the best and most general fix for this situation
+                * is to resynchronize the various sleep/beacon timers on
+                * the receipt of the next beacon i.e. when the TSF itself
+                * gets resynchronized to the AP's TSF - power save is
+                * needed to be temporarily disabled until that time
+                *
+                * Need to save the sequence number to restore it after
+                * the reset!
+                */
+               saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);
+       } else
+               saveFrameSeqCount = 0;          /* NB: silence compiler */
+
+       /* If the channel change is across the same mode - perform a fast channel change */
+       if ((IS_2413(ah) || IS_5413(ah))) {
+               /*
+                * Channel change can only be used when:
+                *  -channel change requested - so it's not the initial reset.
+                *  -it's not a change to the current channel - often called when switching modes
+                *   on a channel
+                *  -the modes of the previous and requested channel are the same - some ugly code for XR
+                */
+               if (bChannelChange &&
+                   (AH_PRIVATE(ah)->ah_curchan != AH_NULL) &&
+                   (chan->channel != AH_PRIVATE(ah)->ah_curchan->channel) &&
+                   ((chan->channelFlags & CHANNEL_ALL) ==
+                    (AH_PRIVATE(ah)->ah_curchan->channelFlags & CHANNEL_ALL))) {
+                       if (ar5212ChannelChange(ah, chan))
+                               /* If ChannelChange completed - skip the rest of reset */
+                               return AH_TRUE;
+               }
+       }
+
+       /*
+        * Preserve the antenna on a channel change
+        */
+       saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
+       if (saveDefAntenna == 0)                /* XXX magic constants */
+               saveDefAntenna = 1;
+
+       /* Save hardware flag before chip reset clears the register */
+       macStaId1 = OS_REG_READ(ah, AR_STA_ID1) &
+               (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);
+
+       /* Save led state from pci config register */
+       if (!IS_5315(ah))
+               saveLedState = OS_REG_READ(ah, AR5312_PCICFG) &
+                       (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
+                        AR_PCICFG_LEDSLOW);
+
+       ar5312RestoreClock(ah, opmode);         /* move to refclk operation */
+
+       /*
+        * Adjust gain parameters before reset if
+        * there's an outstanding gain updated.
+        */
+       (void) ar5212GetRfgain(ah);
+
+       if (!ar5312ChipReset(ah, chan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Setup the indices for the next set of register array writes */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+               modesIndex = 1;
+               freqIndex  = 1;
+               break;
+       case CHANNEL_T:
+               modesIndex = 2;
+               freqIndex  = 1;
+               break;
+       case CHANNEL_B:
+               modesIndex = 3;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_PUREG:
+               modesIndex = 4;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_108G:
+               modesIndex = 5;
+               freqIndex  = 2;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       /* Set correct Baseband to analog shift setting to access analog chips. */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
+       regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
+               regWrites);
+       ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) {
+               ar5212SetIFSTiming(ah, chan);
+       }
+
+       /* Overwrite INI values for revised chipsets */
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
+               /* ADC_CTL */
+               OS_REG_WRITE(ah, AR_PHY_ADC_CTL,
+                            SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |
+                            SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |
+                            AR_PHY_ADC_CTL_OFF_PWDDAC |
+                            AR_PHY_ADC_CTL_OFF_PWDADC);
+
+               /* TX_PWR_ADJ */
+               if (chan->channel == 2484) {
+                       cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta);
+               } else {
+                       cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta);
+               }
+
+               if (IS_CHAN_G(chan)) {
+                       OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,
+                                    SM((ee->ee_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |
+                                    SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);
+               }
+
+               /* Add barker RSSI thresh enable as disabled */
+               OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,
+                              AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);
+               OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,
+                                AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);
+
+               /* Set the mute mask to the correct default */
+               OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
+       }
+
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
+               /* Clear reg to alllow RX_CLEAR line debug */
+               OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
+       }
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
+#ifdef notyet
+               /* Enable burst prefetch for the data queues */
+               OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
+               /* Enable double-buffering */
+               OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
+#endif
+       }
+
+       if (IS_5312_2_X(ah)) {
+               /* ADC_CTRL */
+               OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA,
+                            SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) |
+                            SM(4, AR_PHY_SIGMA_DELTA_FILT2) |
+                            SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) |
+                            SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP));
+
+               if (IS_CHAN_2GHZ(chan))
+                       OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F);
+
+               /* CCK Short parameter adjustment in 11B mode */
+               if (IS_CHAN_B(chan))
+                       OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12);
+
+               /* Set ADC/DAC select values */
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04);
+
+               /* Increase 11A AGC Settling */
+               if ((chan->channelFlags & CHANNEL_ALL) == CHANNEL_A)
+                       OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32);
+       } else {
+               /* Set ADC/DAC select values */
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
+       }
+
+       /* Setup the transmit power values. */
+       if (!ar5212SetTransmitPower(ah, ichan, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Write the analog registers */
+       if (!ahp->ah_rfHal->setRfRegs(ah, ichan, modesIndex, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n",
+                   __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
+       if (IS_CHAN_OFDM(chan)) {
+               if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) &&
+                   (!IS_CHAN_B(chan)))
+                       ar5212SetSpurMitigation(ah, ichan);
+               ar5212SetDeltaSlope(ah, chan);
+       }
+
+       /* Setup board specific options for EEPROM version 3 */
+       if (!ar5212SetBoardValues(ah, ichan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error setting board options\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Restore certain DMA hardware registers on a channel change */
+       if (bChannelChange)
+               OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
+       OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
+               | macStaId1
+               | AR_STA_ID1_RTS_USE_DEF
+               | ahp->ah_staId1Defaults
+       );
+       ar5212SetOperatingMode(ah, opmode);
+
+       /* Set Venice BSSID mask according to current state */
+       OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
+       OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
+
+       /* Restore previous led state */
+       if (!IS_5315(ah))
+               OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);
+
+       /* Restore previous antenna */
+       OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+
+       /* then our BSSID */
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
+
+       /* Restore bmiss rssi & count thresholds */
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+
+       OS_REG_WRITE(ah, AR_ISR, ~0);           /* cleared on write */
+
+       if (!ar5212SetChannel(ah, ichan))
+               FAIL(HAL_EIO);
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
+
+       ar5212SetRateDurationTable(ah, chan);
+
+       /* Set Tx frame start to tx data start delay */
+       if (IS_RAD5112_ANY(ah) &&
+           (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) ||
+            IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) {
+               txFrm2TxDStart =
+                       (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) ?
+                                       TX_FRAME_D_START_HALF_RATE:
+                                       TX_FRAME_D_START_QUARTER_RATE;
+               OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL,
+                       AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart);
+       }
+
+       /*
+        * Setup fast diversity.
+        * Fast diversity can be enabled or disabled via regadd.txt.
+        * Default is enabled.
+        * For reference,
+        *    Disable: reg        val
+        *             0x00009860 0x00009d18 (if 11a / 11g, else no change)
+        *             0x00009970 0x192bb514
+        *             0x0000a208 0xd03e4648
+        *
+        *    Enable:  0x00009860 0x00009d10 (if 11a / 11g, else no change)
+        *             0x00009970 0x192fb514
+        *             0x0000a208 0xd03e6788
+        */
+
+       /* XXX Setup pre PHY ENABLE EAR additions */
+
+       /* flush SCAL reg */
+       if (IS_5312_2_X(ah)) {
+               (void) OS_REG_READ(ah, AR_PHY_SLEEP_SCAL);
+       }
+
+       /*
+        * Wait for the frequency synth to settle (synth goes on
+        * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
+        * Value is in 100ns increments.
+        */
+       synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_CCK(chan)) {
+               synthDelay = (4 * synthDelay) / 22;
+       } else {
+               synthDelay /= 10;
+       }
+
+       /* Activate the PHY (includes baseband activate and synthesizer on) */
+       OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+       /*
+        * There is an issue if the AP starts the calibration before
+        * the base band timeout completes.  This could result in the
+        * rx_clear false triggering.  As a workaround we add delay an
+        * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
+        * does not happen.
+        */
+       if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+               OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
+       } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+               OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
+       } else {
+               OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
+       }
+
+       /*
+        * The udelay method is not reliable with notebooks.
+        * Need to check to see if the baseband is ready
+        */
+       testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL);
+       /* Selects the Tx hold */
+       OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD);
+       i = 0;
+       while ((i++ < 20) &&
+              (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */               OS_DELAY(200);
+       OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg);
+
+       /* Calibrate the AGC and start a NF calculation */
+       OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                 OS_REG_READ(ah, AR_PHY_AGC_CONTROL)
+               | AR_PHY_AGC_CONTROL_CAL
+               | AR_PHY_AGC_CONTROL_NF);
+
+       if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) {
+               /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
+               OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+                       AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+                       INIT_IQCAL_LOG_COUNT_MAX);
+               OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
+                       AR_PHY_TIMING_CTRL4_DO_IQCAL);
+               ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
+       } else
+               ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
+
+       /* Setup compression registers */
+       ar5212SetCompRegs(ah);
+
+       /* Set 1:1 QCU to DCU mapping for all queues */
+       for (i = 0; i < AR_NUM_DCU; i++)
+               OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+       ahp->ah_intrTxqs = 0;
+       for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
+               ar5212ResetTxQueue(ah, i);
+
+       /*
+        * Setup interrupt handling.  Note that ar5212ResetTxQueue
+        * manipulates the secondary IMR's as queues are enabled
+        * and disabled.  This is done with RMW ops to insure the
+        * settings we make here are preserved.
+        */
+       ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN
+                       | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN
+                       | AR_IMR_HIUERR
+                       ;
+       if (opmode == HAL_M_HOSTAP)
+               ahp->ah_maskReg |= AR_IMR_MIB;
+       OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
+       /* Enable bus errors that are OR'd to set the HIUERR bit */
+       OS_REG_WRITE(ah, AR_IMR_S2,
+               OS_REG_READ(ah, AR_IMR_S2)
+               | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);
+
+       if (AH_PRIVATE(ah)->ah_rfkillEnabled)
+               ar5212EnableRfKill(ah);
+
+       if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: offset calibration failed to complete in 1ms;"
+                   " noisy environment?\n", __func__);
+       }
+
+       /*
+        * Set clocks back to 32kHz if they had been using refClk, then
+        * use an external 32kHz crystal when sleeping, if one exists.
+        */
+       ar5312SetupClock(ah, opmode);
+
+       /*
+        * Writing to AR_BEACON will start timers. Hence it should
+        * be the last register to be written. Do not reset tsf, do
+        * not enable beacons at this point, but preserve other values
+        * like beaconInterval.
+        */
+       OS_REG_WRITE(ah, AR_BEACON,
+               (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));
+
+       /* XXX Setup post reset EAR additions */
+
+       /*  QoS support */
+       if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE ||
+           (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
+            AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) {
+               OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);      /* XXX magic */
+               OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);        /* XXX magic */
+       }
+
+       /* Turn on NOACK Support for QoS packets */
+       OS_REG_WRITE(ah, AR_NOACK,
+                    SM(2, AR_NOACK_2BIT_VALUE) |
+                    SM(5, AR_NOACK_BIT_OFFSET) |
+                    SM(0, AR_NOACK_BYTE_OFFSET));
+
+       /* Restore user-specified settings */
+       if (ahp->ah_miscMode != 0)
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+       if (ahp->ah_slottime != (u_int) -1)
+               ar5212SetSlotTime(ah, ahp->ah_slottime);
+       if (ahp->ah_acktimeout != (u_int) -1)
+               ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
+       if (ahp->ah_ctstimeout != (u_int) -1)
+               ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
+       if (ahp->ah_sifstime != (u_int) -1)
+               ar5212SetSifsTime(ah, ahp->ah_sifstime);
+       if (AH_PRIVATE(ah)->ah_diagreg != 0)
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+
+       AH_PRIVATE(ah)->ah_opmode = opmode;     /* record operating mode */
+
+       if (bChannelChange) {
+               if (!(ichan->privFlags & CHANNEL_DFS))
+                       ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+               chan->channelFlags = ichan->channelFlags;
+               chan->privFlags = ichan->privFlags;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
+
+       OS_MARK(ah, AH_MARK_RESET_DONE, 0);
+
+       return AH_TRUE;
+bad:
+       OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
+       if (*status)
+               *status = ecode;
+       return AH_FALSE;
+#undef FAIL
+#undef N
+}
+
+/*
+ * Places the PHY and Radio chips into reset.  A full reset
+ * must be called to leave this state.  The PCI/MAC/PCU are
+ * not placed into reset as we must receive interrupt to
+ * re-enable the hardware.
+ */
+HAL_BOOL
+ar5312PhyDisable(struct ath_hal *ah)
+{
+    return ar5312SetResetReg(ah, AR_RC_BB);
+}
+
+/*
+ * Places all of hardware into reset
+ */
+HAL_BOOL
+ar5312Disable(struct ath_hal *ah)
+{
+       if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+       /*
+        * Reset the HW - PCI must be reset after the rest of the
+        * device has been reset.
+        */
+       return ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB);
+}
+
+/*
+ * Places the hardware into reset and then pulls it out of reset
+ *
+ * TODO: Only write the PLL if we're changing to or from CCK mode
+ *
+ * WARNING: The order of the PLL and mode registers must be correct.
+ */
+HAL_BOOL
+ar5312ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+
+       OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0);
+
+       /*
+        * Reset the HW
+        */
+       if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
+                   __func__);
+               return AH_FALSE;
+       }
+
+       /* Bring out of sleep mode (AGAIN) */
+       if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n",
+                   __func__);
+               return AH_FALSE;
+       }
+
+       /* Clear warm reset register */
+       if (!ar5312SetResetReg(ah, 0)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
+                   __func__);
+               return AH_FALSE;
+       }
+
+       /*
+        * Perform warm reset before the mode/PLL/turbo registers
+        * are changed in order to deactivate the radio.  Mode changes
+        * with an active radio can result in corrupted shifts to the
+        * radio device.
+        */
+
+       /*
+        * Set CCK and Turbo modes correctly.
+        */
+       if (chan != AH_NULL) {          /* NB: can be null during attach */
+               uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;
+
+               if (IS_RAD5112_ANY(ah)) {
+                       rfMode = AR_PHY_MODE_AR5112;
+                       if (!IS_5315(ah)) {
+                               if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) {
+                                       phyPLL = AR_PHY_PLL_CTL_44_5312;
+                               } else {
+                                       if (IS_CHAN_HALF_RATE(chan)) {
+                                               phyPLL = AR_PHY_PLL_CTL_40_5312_HALF;
+                                       } else if (IS_CHAN_QUARTER_RATE(chan)) {
+                                               phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER;
+                                       } else {
+                                               phyPLL = AR_PHY_PLL_CTL_40_5312;
+                                       }
+                               }
+                       } else {
+                               if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))
+                                       phyPLL = AR_PHY_PLL_CTL_44_5112;
+                               else
+                                       phyPLL = AR_PHY_PLL_CTL_40_5112;
+                               if (IS_CHAN_HALF_RATE(chan))
+                                       phyPLL |= AR_PHY_PLL_CTL_HALF;
+                               else if (IS_CHAN_QUARTER_RATE(chan))
+                                       phyPLL |= AR_PHY_PLL_CTL_QUARTER;
+                       }
+               } else {
+                       rfMode = AR_PHY_MODE_AR5111;
+                       if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))
+                               phyPLL = AR_PHY_PLL_CTL_44;
+                       else
+                               phyPLL = AR_PHY_PLL_CTL_40;
+                       if (IS_CHAN_HALF_RATE(chan))
+                               phyPLL = AR_PHY_PLL_CTL_HALF;
+                       else if (IS_CHAN_QUARTER_RATE(chan))
+                               phyPLL = AR_PHY_PLL_CTL_QUARTER;
+               }
+               if (IS_CHAN_OFDM(chan) && (IS_CHAN_CCK(chan) ||
+                                          IS_CHAN_G(chan)))
+                       rfMode |= AR_PHY_MODE_DYNAMIC;
+               else if (IS_CHAN_OFDM(chan))
+                       rfMode |= AR_PHY_MODE_OFDM;
+               else
+                       rfMode |= AR_PHY_MODE_CCK;
+               if (IS_CHAN_5GHZ(chan))
+                       rfMode |= AR_PHY_MODE_RF5GHZ;
+               else
+                       rfMode |= AR_PHY_MODE_RF2GHZ;
+               turbo = IS_CHAN_TURBO(chan) ?
+                       (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;
+               curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);
+               /*
+                * PLL, Mode, and Turbo values must be written in the correct
+                * order to ensure:
+                * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
+                *   mode bit is set
+                * - Turbo cannot be set at the same time as CCK or DYNAMIC
+                */
+               if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) {
+                       OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
+                       OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
+                       if (curPhyPLL != phyPLL) {
+                               OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
+                               /* Wait for the PLL to settle */
+                               OS_DELAY(PLL_SETTLE_DELAY);
+                       }
+               } else {
+                       if (curPhyPLL != phyPLL) {
+                               OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
+                               /* Wait for the PLL to settle */
+                               OS_DELAY(PLL_SETTLE_DELAY);
+                       }
+                       OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
+                       OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
+               }
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Write the given reset bit mask into the reset register
+ */
+static HAL_BOOL
+ar5312SetResetReg(struct ath_hal *ah, uint32_t resetMask)
+{
+       uint32_t mask = resetMask ? resetMask : ~0;
+       HAL_BOOL rt;
+
+        if ((rt = ar5312MacReset(ah, mask)) == AH_FALSE) {
+               return rt;
+       }
+        if ((resetMask & AR_RC_MAC) == 0) {
+               if (isBigEndian()) {
+                       /*
+                        * Set CFG, little-endian for register
+                        * and descriptor accesses.
+                        */
+#ifdef AH_NEED_DESC_SWAP
+                       mask = INIT_CONFIG_STATUS | AR_CFG_SWRD;
+#else
+                       mask = INIT_CONFIG_STATUS |
+                                AR_CFG_SWTD | AR_CFG_SWRD;
+#endif
+                       OS_REG_WRITE(ah, AR_CFG, mask);
+               } else
+                       OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
+       }
+       return rt;
+}
+
+/*
+ * ar5312MacReset resets (and then un-resets) the specified
+ * wireless components.
+ * Note: The RCMask cannot be zero on entering from ar5312SetResetReg.
+ */
+
+HAL_BOOL
+ar5312MacReset(struct ath_hal *ah, unsigned int RCMask)
+{
+       int wlanNum = AR5312_UNIT(ah);
+       uint32_t resetBB, resetBits, regMask;
+       uint32_t reg;
+
+       if (RCMask == 0)
+               return(AH_FALSE);
+#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317 )
+           if (IS_5315(ah)) {
+                       switch(wlanNum) {
+                       case 0:
+                               resetBB = AR5315_RC_BB0_CRES | AR5315_RC_WBB0_RES;
+                               /* Warm and cold reset bits for wbb */
+                               resetBits = AR5315_RC_WMAC0_RES;
+                               break;
+                       case 1:
+                               resetBB = AR5315_RC_BB1_CRES | AR5315_RC_WBB1_RES;
+                               /* Warm and cold reset bits for wbb */
+                               resetBits = AR5315_RC_WMAC1_RES;
+                               break;
+                       default:
+                               return(AH_FALSE);
+                       }
+                       regMask = ~(resetBB | resetBits);
+
+                       /* read before */
+                       reg = OS_REG_READ(ah,
+                                                         (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5315_RESET));
+
+                       if (RCMask == AR_RC_BB) {
+                               /* Put baseband in reset */
+                               reg |= resetBB;    /* Cold and warm reset the baseband bits */
+                       } else {
+                               /*
+                                * Reset the MAC and baseband.  This is a bit different than
+                                * the PCI version, but holding in reset causes problems.
+                                */
+                               reg &= regMask;
+                               reg |= (resetBits | resetBB) ;
+                       }
+                       OS_REG_WRITE(ah,
+                                                (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET),
+                                                reg);
+                       /* read after */
+                       OS_REG_READ(ah,
+                                               (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5315_RESET));
+                       OS_DELAY(100);
+
+                       /* Bring MAC and baseband out of reset */
+                       reg &= regMask;
+                       /* read before */
+                       OS_REG_READ(ah,
+                                               (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET));
+                       OS_REG_WRITE(ah,
+                                                (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET),
+                                                reg);
+                       /* read after */
+                       OS_REG_READ(ah,
+                                               (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET));
+
+
+               }
+        else
+#endif
+               {
+
+                       switch(wlanNum) {
+                       case 0:
+                               resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES;
+                               /* Warm and cold reset bits for wbb */
+                               resetBits = AR5312_RC_WMAC0_RES;
+                               break;
+                       case 1:
+                               resetBB = AR5312_RC_BB1_CRES | AR5312_RC_WBB1_RES;
+                               /* Warm and cold reset bits for wbb */
+                               resetBits = AR5312_RC_WMAC1_RES;
+                               break;
+                       default:
+                               return(AH_FALSE);
+                       }
+                       regMask = ~(resetBB | resetBits);
+
+                       /* read before */
+                       reg = OS_REG_READ(ah,
+                                                         (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5312_RESET));
+
+                       if (RCMask == AR_RC_BB) {
+                               /* Put baseband in reset */
+                               reg |= resetBB;    /* Cold and warm reset the baseband bits */
+                       } else {
+                               /*
+                                * Reset the MAC and baseband.  This is a bit different than
+                                * the PCI version, but holding in reset causes problems.
+                                */
+                               reg &= regMask;
+                               reg |= (resetBits | resetBB) ;
+                       }
+                       OS_REG_WRITE(ah,
+                                                (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET),
+                                                reg);
+                       /* read after */
+                       OS_REG_READ(ah,
+                                               (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5312_RESET));
+                       OS_DELAY(100);
+
+                       /* Bring MAC and baseband out of reset */
+                       reg &= regMask;
+                       /* read before */
+                       OS_REG_READ(ah,
+                                               (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET));
+                       OS_REG_WRITE(ah,
+                                                (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET),
+                                                reg);
+                       /* read after */
+                       OS_REG_READ(ah,
+                                               (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET));
+               }
+       return(AH_TRUE);
+}
+
+#endif /* AH_SUPPORT_AR5312 */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312phy.h        2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312phy.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5312PHY_H_
+#define _DEV_ATH_AR5312PHY_H_
+
+#include "ar5212/ar5212phy.h"
+
+/* PHY registers */
+
+#define AR_PHY_PLL_CTL_44_5312  0x14d6          /* 44 MHz for 11b, 11g */
+#define AR_PHY_PLL_CTL_40_5312  0x14d4          /* 40 MHz for 11a, turbos */
+#define AR_PHY_PLL_CTL_40_5312_HALF  0x15d4    /* 40 MHz for 11a, turbos (Half)*/
+#define AR_PHY_PLL_CTL_40_5312_QUARTER  0x16d4 /* 40 MHz for 11a, turbos (Quarter)*/
+
+#endif /* _DEV_ATH_AR5312PHY_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5312reg.h        2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5312reg.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5312REG_H_
+#define _DEV_ATH_AR5312REG_H_
+
+#include "ar5212/ar5212reg.h"
+/*
+ * Definitions for the Atheros 5312 chipset.
+ */
+
+/* Register base addresses for modules which are not wmac modules */
+/* 531X has a fixed memory map */
+
+
+#define REG_WRITE(_reg,_val)           *((volatile uint32_t *)(_reg)) = (_val);
+#define REG_READ(_reg)         *((volatile uint32_t *)(_reg))
+/*
+ * PCI-MAC Configuration registers (AR2315+)
+ */
+#define AR5315_RSTIMER_BASE 0xb1000000  /* Address for reset/timer registers */
+#define AR5315_GPIO_BASE    0xb1000000  /* Address for GPIO registers */
+#define AR5315_WLAN0            0xb0000000
+
+#define AR5315_RESET   0x0004      /* Offset of reset control register */
+#define AR5315_SREV    0x0014      /* Offset of reset control register */
+#define AR5315_ENDIAN_CTL  0x000c  /* offset of the endian control register */
+#define AR5315_CONFIG_WLAN     0x00000002      /* WLAN byteswap */
+
+#define AR5315_REV_MAJ                     0x00f0
+#define AR5315_REV_MIN                     0x000f
+
+#define AR5315_GPIODIR      0x0098      /* GPIO direction register */
+#define AR5315_GPIODO       0x0090      /* GPIO data output access reg */
+#define AR5315_GPIODI       0x0088      /* GPIO data input access reg*/
+#define AR5315_GPIOINT      0x00a0      /* GPIO interrupt control */
+
+#define AR5315_GPIODIR_M(x) (1 << (x))  /* mask for i/o */
+#define AR5315_GPIODIR_O(x) (1 << (x))  /* output */
+#define AR5315_GPIODIR_I(x) 0           /* input */
+
+#define AR5315_GPIOINT_S    0
+#define AR5315_GPIOINT_M    0x3F
+#define AR5315_GPIOINTLVL_S 6
+#define AR5315_GPIOINTLVL_M (3 << AR5315_GPIOINTLVL_S)
+
+#define AR5315_WREV         (-0xefbfe0)      /* Revision ID register offset */
+#define AR5315_WREV_S       0           /* Shift for WMAC revision info */
+#define AR5315_WREV_ID      0x000000FF  /* Mask for WMAC revision info */
+#define AR5315_WREV_ID_S    4           /* Shift for WMAC Rev ID */
+#define AR5315_WREV_REVISION 0x0000000F /* Mask for WMAN Revsion version */
+
+#define AR5315_RC_BB0_CRES   0x00000002  /* Cold reset to WMAC0 & WBB0 */
+#define AR5315_RC_BB1_CRES   0x00000200  /* Cold reset to WMAC1 & WBB1n */
+#define AR5315_RC_WMAC0_RES  0x00000001  /* Warm reset to WMAC 0 */
+#define AR5315_RC_WBB0_RES  0x00000002  /* Warm reset to WBB0 */
+#define AR5315_RC_WMAC1_RES  0x00020000  /* Warm reset to WMAC1 */
+#define AR5315_RC_WBB1_RES   0x00040000  /* Warm reset to WBB */
+
+/*
+ * PCI-MAC Configuration registers (AR5312)
+ */
+#define AR5312_RSTIMER_BASE 0xbc003000  /* Address for reset/timer registers */
+#define AR5312_GPIO_BASE    0xbc002000  /* Address for GPIO registers */
+#define AR5312_WLAN0            0xb8000000
+#define AR5312_WLAN1            0xb8500000
+
+#define AR5312_RESET   0x0020      /* Offset of reset control register */
+#define        AR5312_PCICFG   0x00B0      /* MAC/PCI configuration reg (LEDs) */
+
+#define AR5312_PCICFG_LEDMODE  0x0000001c      /* LED Mode mask */
+#define AR5312_PCICFG_LEDMODE_S  2     /* LED Mode shift */
+#define AR5312_PCICFG_LEDMOD0  0       /* Blnk prop to Tx and filtered Rx */
+#define AR5312_PCICFG_LEDMOD1  1       /* Blnk prop to all Tx and Rx */
+#define AR5312_PCICFG_LEDMOD2  2       /* DEBG flash */
+#define AR5312_PCICFG_LEDMOD3  3       /* BLNK Randomly */
+
+#define        AR5312_PCICFG_LEDSEL   0x000000e0 /* LED Throughput select */
+#define AR5312_PCICFG_LEDSEL_S 5
+#define AR5312_PCICFG_LEDSEL0  0       /* See blink rate table on p. 143 */
+#define AR5312_PCICFG_LEDSEL1  1       /* of AR5212 data sheet */
+#define AR5312_PCICFG_LEDSEL2  2
+#define AR5312_PCICFG_LEDSEL3  3
+#define AR5312_PCICFG_LEDSEL4  4
+#define AR5312_PCICFG_LEDSEL5  5
+#define AR5312_PCICFG_LEDSEL6  6
+#define AR5312_PCICFG_LEDSEL7  7
+
+#define AR5312_PCICFG_LEDSBR   0x00000100 /* Slow blink rate if no
+                                            activity. 0 = blink @ lowest
+                                            rate */
+
+#undef AR_GPIOCR
+#undef AR_GPIODO                    /* Undefine the 5212 defs */
+#undef AR_GPIODI
+
+#define AR5312_GPIOCR       0x0008      /* GPIO Control register */
+#define AR5312_GPIODO       0x0000      /* GPIO data output access reg */
+#define AR5312_GPIODI       0x0004      /* GPIO data input access reg*/
+/* NB: AR5312 uses AR5212 defines for GPIOCR definitions */
+
+#define AR5312_WREV         0x0090      /* Revision ID register offset */
+#define AR5312_WREV_S       8           /* Shift for WMAC revision info */
+#define AR5312_WREV_ID      0x000000FF  /* Mask for WMAC revision info */
+#define AR5312_WREV_ID_S    4           /* Shift for WMAC Rev ID */
+#define AR5312_WREV_REVISION 0x0000000F /* Mask for WMAN Revsion version */
+
+#define AR5312_RC_BB0_CRES   0x00000004  /* Cold reset to WMAC0 & WBB0 */
+#define AR5312_RC_BB1_CRES   0x00000200  /* Cold reset to WMAC1 & WBB1n */
+#define AR5312_RC_WMAC0_RES  0x00002000  /* Warm reset to WMAC 0 */
+#define AR5312_RC_WBB0_RES  0x00004000  /* Warm reset to WBB0 */
+#define AR5312_RC_WMAC1_RES  0x00020000  /* Warm reset to WMAC1 */
+#define AR5312_RC_WBB1_RES   0x00040000  /* Warm reset to WBB */
+
+
+#define AR_RAD2112_SREV_MAJOR   0x40    /* 2112 Major Rev */
+
+enum AR5312PowerMode {
+    AR5312_POWER_MODE_FORCE_SLEEP  = 0,
+    AR5312_POWER_MODE_FORCE_WAKE   = 1,
+    AR5312_POWER_MODE_NORMAL       = 2,
+};
+
+#endif /* _DEV_AR5312REG_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5312/ar5315_gpio.c      2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5315_gpio.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#if (AH_SUPPORT_2316 || AH_SUPPORT_2317)
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5312/ar5312.h"
+#include "ar5312/ar5312reg.h"
+#include "ar5312/ar5312phy.h"
+
+#define        AR_NUM_GPIO     7               /* 6 GPIO pins */
+#define        AR5315_GPIOD_MASK       0x0000007F      /* GPIO data reg r/w mask */
+
+/*
+ * Configure GPIO Output lines
+ */
+HAL_BOOL
+ar5315GpioCfgOutput(struct ath_hal *ah, uint32_t gpio)
+{
+       uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODIR,
+                 (OS_REG_READ(ah, gpioOffset+AR5315_GPIODIR) &~ AR5315_GPIODIR_M(gpio))
+               | AR5315_GPIODIR_O(gpio));
+
+       return AH_TRUE;
+}
+
+/*
+ * Configure GPIO Input lines
+ */
+HAL_BOOL
+ar5315GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
+{
+       uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODIR,
+                 (OS_REG_READ(ah, gpioOffset+AR5315_GPIODIR) &~ AR5315_GPIODIR_M(gpio))
+               | AR5315_GPIODIR_I(gpio));
+
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - set output lines
+ */
+HAL_BOOL
+ar5315GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
+{
+       uint32_t reg;
+        uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       reg =  OS_REG_READ(ah, gpioOffset+AR5315_GPIODO);
+       reg &= ~(1 << gpio);
+       reg |= (val&1) << gpio;
+
+       OS_REG_WRITE(ah, gpioOffset+AR5315_GPIODO, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - get input lines
+ */
+uint32_t
+ar5315GpioGet(struct ath_hal *ah, uint32_t gpio)
+{
+       uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       if (gpio < AR_NUM_GPIO) {
+               uint32_t val = OS_REG_READ(ah, gpioOffset+AR5315_GPIODI);
+               val = ((val & AR5315_GPIOD_MASK) >> gpio) & 0x1;
+               return val;
+       } else  {
+               return 0xffffffff;
+       }
+}
+
+/*
+ * Set the GPIO Interrupt
+ */
+void
+ar5315GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
+{
+       uint32_t val;
+       uint32_t gpioOffset = (AR5315_GPIO_BASE - ((uint32_t) ah->ah_sh));
+
+       /* XXX bounds check gpio */
+       val = OS_REG_READ(ah, gpioOffset+AR5315_GPIOINT);
+       val &= ~(AR5315_GPIOINT_M | AR5315_GPIOINTLVL_M);
+       val |= gpio << AR5315_GPIOINT_S;
+       if (ilevel)
+               val |= 2 << AR5315_GPIOINTLVL_S;        /* interrupt on pin high */
+       else
+               val |= 1 << AR5315_GPIOINTLVL_S;        /* interrupt on pin low */
+
+       /* Don't need to change anything for low level interrupt. */
+       OS_REG_WRITE(ah, gpioOffset+AR5315_GPIOINT, val);
+
+       /* Change the interrupt mask. */
+       (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO);
+}
+
+
+#endif /* AH_SUPPORT_2316 || AH_SUPPORT_2317 */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar2316.c   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar2316.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#include "ah_eeprom_v3.h"
+
+#define AH_5212_2316
+#include "ar5212/ar5212.ini"
+
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+
+typedef        RAW_DATA_STRUCT_2413 RAW_DATA_STRUCT_2316;
+typedef RAW_DATA_PER_CHANNEL_2413 RAW_DATA_PER_CHANNEL_2316;
+#define PWR_TABLE_SIZE_2316 PWR_TABLE_SIZE_2413
+
+struct ar2316State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[PWR_TABLE_SIZE_2316];
+
+       uint32_t        Bank1Data[N(ar5212Bank1_2316)];
+       uint32_t        Bank2Data[N(ar5212Bank2_2316)];
+       uint32_t        Bank3Data[N(ar5212Bank3_2316)];
+       uint32_t        Bank6Data[N(ar5212Bank6_2316)];
+       uint32_t        Bank7Data[N(ar5212Bank7_2316)];
+
+       /*
+        * Private state for reduced stack usage.
+        */
+       /* filled out Vpd table for all pdGains (chanL) */
+       uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (chanR) */
+       uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (interpolated) */
+       uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+};
+#define        AR2316(ah)      ((struct ar2316State *) AH5212(ah)->ah_rfHal)
+
+extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+               uint32_t numBits, uint32_t firstBit, uint32_t column);
+
+static void
+ar2316WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int regWrites)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2316, modesIndex, regWrites);
+       HAL_INI_WRITE_ARRAY(ah, ar5212Common_2316, 1, regWrites);
+       HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2316, freqIndex, regWrites);
+
+       /* For AP51 */
+        if (!ahp->ah_cwCalRequire) {
+               OS_REG_WRITE(ah, 0xa358, (OS_REG_READ(ah, 0xa358) & ~0x2));
+        } else {
+               ahp->ah_cwCalRequire = AH_FALSE;
+        }
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar2316SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t channelSel  = 0;
+       uint32_t bModeSynth  = 0;
+       uint32_t aModeRefSel = 0;
+       uint32_t reg32       = 0;
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       if (chan->channel < 4800) {
+               uint32_t txctl;
+
+               if (((chan->channel - 2192) % 5) == 0) {
+                       channelSel = ((chan->channel - 672) * 2 - 3040)/10;
+                       bModeSynth = 0;
+               } else if (((chan->channel - 2224) % 5) == 0) {
+                       channelSel = ((chan->channel - 704) * 2 - 3040) / 10;
+                       bModeSynth = 1;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid channel %u MHz\n",
+                           __func__, chan->channel);
+                       return AH_FALSE;
+               }
+
+               channelSel = (channelSel << 2) & 0xff;
+               channelSel = ath_hal_reverseBits(channelSel, 8);
+
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (chan->channel == 2484) {
+                       /* Enable channel spreading for channel 14 */
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+       } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 20 << 2), 8);
+               aModeRefSel = ath_hal_reverseBits(3, 2);
+       } else if ((chan->channel % 10) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 10 << 1), 8);
+               aModeRefSel = ath_hal_reverseBits(2, 2);
+       } else if ((chan->channel % 5) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       (chan->channel - 4800) / 5, 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
+                   __func__, chan->channel);
+               return AH_FALSE;
+       }
+
+       reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) |
+                       (1 << 12) | 0x1;
+       OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff);
+
+       reg32 >>= 8;
+       OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f);
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar2316SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+#define        RF_BANK_SETUP(_priv, _ix, _col) do {                                \
+       int i;                                                              \
+       for (i = 0; i < N(ar5212Bank##_ix##_2316); i++)                     \
+               (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2316[i][_col];\
+} while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t ob2GHz = 0, db2GHz = 0;
+       struct ar2316State *priv = AR2316(ah);
+       int regWrites = 0;
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+           "%s: chan 0x%x flag 0x%x modesIndex 0x%x\n",
+           __func__, chan->channel, chan->channelFlags, modesIndex);
+
+       HALASSERT(priv != AH_NULL);
+
+       /* Setup rf parameters */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_B:
+               ob2GHz = ee->ee_obFor24;
+               db2GHz = ee->ee_dbFor24;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               ob2GHz = ee->ee_obFor24g;
+               db2GHz = ee->ee_dbFor24g;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /* Bank 1 Write */
+       RF_BANK_SETUP(priv, 1, 1);
+
+       /* Bank 2 Write */
+       RF_BANK_SETUP(priv, 2, modesIndex);
+
+       /* Bank 3 Write */
+       RF_BANK_SETUP(priv, 3, modesIndex);
+
+       /* Bank 6 Write */
+       RF_BANK_SETUP(priv, 6, modesIndex);
+
+       ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz,   3, 178, 0);
+       ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz,   3, 175, 0);
+
+       /* Bank 7 Setup */
+       RF_BANK_SETUP(priv, 7, modesIndex);
+
+       /* Write Analog registers */
+       HAL_INI_WRITE_BANK(ah, ar5212Bank1_2316, priv->Bank1Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank2_2316, priv->Bank2Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank3_2316, priv->Bank3Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank6_2316, priv->Bank6Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank7_2316, priv->Bank7Data, regWrites);
+
+       /* Now that we have reprogrammed rfgain value, clear the flag. */
+       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+
+       return AH_TRUE;
+#undef RF_BANK_SETUP
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar2316GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar2316State *priv = AR2316(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Return indices surrounding the value in sorted integer lists.
+ *
+ * NB: the input list is assumed to be sorted in ascending order
+ */
+static void
+GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize,
+                          uint32_t *vlo, uint32_t *vhi)
+{
+       int16_t target = v;
+       const int16_t *ep = lp+listSize;
+       const int16_t *tp;
+
+       /*
+        * Check first and last elements for out-of-bounds conditions.
+        */
+       if (target < lp[0]) {
+               *vlo = *vhi = 0;
+               return;
+       }
+       if (target >= ep[-1]) {
+               *vlo = *vhi = listSize - 1;
+               return;
+       }
+
+       /* look for value being near or between 2 values in list */
+       for (tp = lp; tp < ep; tp++) {
+               /*
+                * If value is close to the current value of the list
+                * then target is not between values, it is one of the values
+                */
+               if (*tp == target) {
+                       *vlo = *vhi = tp - (const int16_t *) lp;
+                       return;
+               }
+               /*
+                * Look for value being between current value and next value
+                * if so return these 2 values
+                */
+               if (target < tp[1]) {
+                       *vlo = tp - (const int16_t *) lp;
+                       *vhi = *vlo + 1;
+                       return;
+               }
+       }
+}
+
+/*
+ * Fill the Vpdlist for indices Pmax-Pmin
+ */
+static HAL_BOOL
+ar2316FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t  Pmax,
+                  const int16_t *pwrList, const int16_t *VpdList,
+                  uint16_t numIntercepts, uint16_t retVpdList[][64])
+{
+       uint16_t ii, jj, kk;
+       int16_t currPwr = (int16_t)(2*Pmin);
+       /* since Pmin is pwr*2 and pwrList is 4*pwr */
+       uint32_t  idxL = 0, idxR = 0;
+
+       ii = 0;
+       jj = 0;
+
+       if (numIntercepts < 2)
+               return AH_FALSE;
+
+       while (ii <= (uint16_t)(Pmax - Pmin)) {
+               GetLowerUpperIndex(currPwr, pwrList, numIntercepts,
+                                        &(idxL), &(idxR));
+               if (idxR < 1)
+                       idxR = 1;                       /* extrapolate below */
+               if (idxL == (uint32_t)(numIntercepts - 1))
+                       idxL = numIntercepts - 2;       /* extrapolate above */
+               if (pwrList[idxL] == pwrList[idxR])
+                       kk = VpdList[idxL];
+               else
+                       kk = (uint16_t)
+                               (((currPwr - pwrList[idxL])*VpdList[idxR]+
+                                 (pwrList[idxR] - currPwr)*VpdList[idxL])/
+                                (pwrList[idxR] - pwrList[idxL]));
+               retVpdList[pdGainIdx][ii] = kk;
+               ii++;
+               currPwr += 2;                           /* half dB steps */
+       }
+
+       return AH_TRUE;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+static int16_t
+interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+       int16_t targetLeft, int16_t targetRight)
+{
+       int16_t rv;
+
+       if (srcRight != srcLeft) {
+               rv = ((target - srcLeft)*targetRight +
+                     (srcRight - target)*targetLeft) / (srcRight - srcLeft);
+       } else {
+               rv = targetLeft;
+       }
+       return rv;
+}
+
+/*
+ * Uses the data points read from EEPROM to reconstruct the pdadc power table
+ * Called by ar2316SetPowerTable()
+ */
+static int
+ar2316getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel,
+               const RAW_DATA_STRUCT_2316 *pRawDataset,
+               uint16_t pdGainOverlap_t2,
+               int16_t  *pMinCalPower, uint16_t pPdGainBoundaries[],
+               uint16_t pPdGainValues[], uint16_t pPDADCValues[])
+{
+       struct ar2316State *priv = AR2316(ah);
+#define        VpdTable_L      priv->vpdTable_L
+#define        VpdTable_R      priv->vpdTable_R
+#define        VpdTable_I      priv->vpdTable_I
+       uint32_t ii, jj, kk;
+       int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */
+       uint32_t idxL = 0, idxR = 0;
+       uint32_t numPdGainsUsed = 0;
+       /*
+        * If desired to support -ve power levels in future, just
+        * change pwr_I_0 to signed 5-bits.
+        */
+       int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on. */
+       int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on */
+       uint16_t numVpd = 0;
+       uint16_t Vpd_step;
+       int16_t tmpVal ;
+       uint32_t sizeCurrVpdTable, maxIndex, tgtIndex;
+
+       /* Get upper lower index */
+       GetLowerUpperIndex(channel, pRawDataset->pChannels,
+                                pRawDataset->numChannels, &(idxL), &(idxR));
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain;
+                       Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0];
+                       if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) {
+                               Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0];
+                       }
+                       Pmin_t2[numPdGainsUsed] = (int16_t)
+                               (Pmin_t2[numPdGainsUsed] / 2);
+                       Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1])
+                               Pmax_t2[numPdGainsUsed] =
+                                       pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2);
+                       ar2316FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L
+                                          );
+                       ar2316FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R
+                                          );
+                       for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) {
+                               VpdTable_I[numPdGainsUsed][kk] =
+                                       interpolate_signed(
+                                                          channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR],
+                                                          (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]);
+                       }
+                       /* fill VpdTable_I for this pdGain */
+                       numPdGainsUsed++;
+               }
+               /* if this pdGain is used */
+       }
+
+       *pMinCalPower = Pmin_t2[0];
+       kk = 0; /* index for the final table */
+       for (ii = 0; ii < numPdGainsUsed; ii++) {
+               if (ii == (numPdGainsUsed - 1))
+                       pPdGainBoundaries[ii] = Pmax_t2[ii] +
+                               PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB;
+               else
+                       pPdGainBoundaries[ii] = (uint16_t)
+                               ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 );
+               if (pPdGainBoundaries[ii] > 63) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: clamp pPdGainBoundaries[%d] %d\n",
+                           __func__, ii, pPdGainBoundaries[ii]);/*XXX*/
+                       pPdGainBoundaries[ii] = 63;
+               }
+
+               /* Find starting index for this pdGain */
+               if (ii == 0)
+                       ss = 0; /* for the first pdGain, start from index 0 */
+               else
+                       ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) -
+                               pdGainOverlap_t2;
+               Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                *-ve ss indicates need to extrapolate data below for this pdGain
+                */
+               while (ss < 0) {
+                       tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step);
+                       pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal);
+                       ss++;
+               }
+
+               sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii];
+               tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii];
+               maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
+
+               while (ss < (int16_t)maxIndex)
+                       pPDADCValues[kk++] = VpdTable_I[ii][ss++];
+
+               Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] -
+                                      VpdTable_I[ii][sizeCurrVpdTable-2]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                * for last gain, pdGainBoundary == Pmax_t2, so will
+                * have to extrapolate
+                */
+               if (tgtIndex > maxIndex) {      /* need to extrapolate above */
+                       while(ss < (int16_t)tgtIndex) {
+                               tmpVal = (uint16_t)
+                                       (VpdTable_I[ii][sizeCurrVpdTable-1] +
+                                        (ss-maxIndex)*Vpd_step);
+                               pPDADCValues[kk++] = (tmpVal > 127) ?
+                                       127 : tmpVal;
+                               ss++;
+                       }
+               }                               /* extrapolated above */
+       }                                       /* for all pdGainUsed */
+
+       while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) {
+               pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1];
+               ii++;
+       }
+       while (kk < 128) {
+               pPDADCValues[kk] = pPDADCValues[kk-1];
+               kk++;
+       }
+
+       return numPdGainsUsed;
+#undef VpdTable_L
+#undef VpdTable_R
+#undef VpdTable_I
+}
+
+static HAL_BOOL
+ar2316SetPowerTable(struct ath_hal *ah,
+       int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t *rfXpdGain)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2316 *pRawDataset = AH_NULL;
+       uint16_t pdGainOverlap_t2;
+       int16_t minCalPower2316_t2;
+       uint16_t *pdadcValues = ahp->ah_pcdacTable;
+       uint16_t gainBoundaries[4];
+       uint32_t reg32, regoffset;
+       int i, numPdGainsUsed;
+#ifndef AH_USE_INIPDGAIN
+       uint32_t tpcrg1;
+#endif
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n",
+           __func__, chan->channel,chan->channelFlags);
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__);
+               return AH_FALSE;
+       }
+
+       pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5),
+                                         AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
+
+       numPdGainsUsed = ar2316getGainBoundariesAndPdadcsForPowers(ah,
+               chan->channel, pRawDataset, pdGainOverlap_t2,
+               &minCalPower2316_t2,gainBoundaries, rfXpdGain, pdadcValues);
+       HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3);
+
+#ifdef AH_USE_INIPDGAIN
+       /*
+        * Use pd_gains curve from eeprom; Atheros always uses
+        * the default curve from the ini file but some vendors
+        * (e.g. Zcomax) want to override this curve and not
+        * honoring their settings results in tx power 5dBm low.
+        */
+       OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                        (pRawDataset->pDataPerChannel[0].numPdGains - 1));
+#else
+       tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1);
+       tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN)
+                 | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN);
+       switch (numPdGainsUsed) {
+       case 3:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3;
+               tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3);
+               /* fall thru... */
+       case 2:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2;
+               tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2);
+               /* fall thru... */
+       case 1:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1;
+               tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1);
+               break;
+       }
+#ifdef AH_DEBUG
+       if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1))
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default "
+                   "pd_gains (default 0x%x, calculated 0x%x)\n",
+                   __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1);
+#endif
+       OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1);
+#endif
+
+       /*
+        * Note the pdadc table may not start at 0 dBm power, could be
+        * negative or greater than 0.  Need to offset the power
+        * values by the amount of minPower for griffin
+        */
+       if (minCalPower2316_t2 != 0)
+               ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2316_t2);
+       else
+               ahp->ah_txPowerIndexOffset = 0;
+
+       /* Finally, write the power values into the baseband power table */
+       regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */
+       for (i = 0; i < 32; i++) {
+               reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0)  |
+                       ((pdadcValues[4*i + 1] & 0xFF) << 8)  |
+                       ((pdadcValues[4*i + 2] & 0xFF) << 16) |
+                       ((pdadcValues[4*i + 3] & 0xFF) << 24) ;
+               OS_REG_WRITE(ah, regoffset, reg32);
+               regoffset += 4;
+       }
+
+       OS_REG_WRITE(ah, AR_PHY_TPCRG5,
+                    SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                    SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
+                    SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
+                    SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
+                    SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+
+       return AH_TRUE;
+}
+
+static int16_t
+ar2316GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2316 *data)
+{
+       uint32_t ii,jj;
+       uint16_t Pmin=0,numVpd;
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = data->pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       Pmin = data->pDataPerPDGain[jj].pwr_t4[0];
+                       return(Pmin);
+               }
+       }
+       return(Pmin);
+}
+
+static int16_t
+ar2316GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2316 *data)
+{
+       uint32_t ii;
+       uint16_t Pmax=0,numVpd;
+
+       for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               /* work forwards cuase lowest pdGain for highest power */
+               numVpd = data->pDataPerPDGain[ii].numVpd;
+               if (numVpd > 0) {
+                       Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1];
+                       return(Pmax);
+               }
+       }
+       return(Pmax);
+}
+
+static HAL_BOOL
+ar2316GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan,
+       int16_t *maxPow, int16_t *minPow)
+{
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2316 *pRawDataset = AH_NULL;
+       const RAW_DATA_PER_CHANNEL_2316 *data=AH_NULL;
+       uint16_t numChannels;
+       int totalD,totalF, totalMin,last, i;
+
+       *maxPow = 0;
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else
+               return(AH_FALSE);
+
+       numChannels = pRawDataset->numChannels;
+       data = pRawDataset->pDataPerChannel;
+
+       /* Make sure the channel is in the range of the TP values
+        *  (freq piers)
+        */
+       if (numChannels < 1)
+               return(AH_FALSE);
+
+       if ((chan->channel < data[0].channelValue) ||
+           (chan->channel > data[numChannels-1].channelValue)) {
+               if (chan->channel < data[0].channelValue) {
+                       *maxPow = ar2316GetMaxPower(ah, &data[0]);
+                       *minPow = ar2316GetMinPower(ah, &data[0]);
+                       return(AH_TRUE);
+               } else {
+                       *maxPow = ar2316GetMaxPower(ah, &data[numChannels - 1]);
+                       *minPow = ar2316GetMinPower(ah, &data[numChannels - 1]);
+                       return(AH_TRUE);
+               }
+       }
+
+       /* Linearly interpolate the power value now */
+       for (last=0,i=0; (i<numChannels) && (chan->channel > data[i].channelValue);
+            last = i++);
+       totalD = data[i].channelValue - data[last].channelValue;
+       if (totalD > 0) {
+               totalF = ar2316GetMaxPower(ah, &data[i]) - ar2316GetMaxPower(ah, &data[last]);
+               *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) +
+                                    ar2316GetMaxPower(ah, &data[last])*totalD)/totalD);
+               totalMin = ar2316GetMinPower(ah, &data[i]) - ar2316GetMinPower(ah, &data[last]);
+               *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) +
+                                    ar2316GetMinPower(ah, &data[last])*totalD)/totalD);
+               return(AH_TRUE);
+       } else {
+               if (chan->channel == data[i].channelValue) {
+                       *maxPow = ar2316GetMaxPower(ah, &data[i]);
+                       *minPow = ar2316GetMinPower(ah, &data[i]);
+                       return(AH_TRUE);
+               } else
+                       return(AH_FALSE);
+       }
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar2316RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for private state.
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+static HAL_BOOL
+ar2316RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar2316State *priv;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar2316State));
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar2316RfDetach;
+       priv->base.writeRegs            = ar2316WriteRegs;
+       priv->base.getRfBank            = ar2316GetRfBank;
+       priv->base.setChannel           = ar2316SetChannel;
+       priv->base.setRfRegs            = ar2316SetRfRegs;
+       priv->base.setPowerTable        = ar2316SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar2316GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar5212GetNfAdjust;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+
+       ahp->ah_cwCalRequire = AH_TRUE;         /* force initial cal */
+
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+ar2316Probe(struct ath_hal *ah)
+{
+       return IS_2316(ah);
+}
+AH_RF(RF2316, ar2316Probe, ar2316RfAttach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar2317.c   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,745 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar2317.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_devid.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#include "ah_eeprom_v3.h"
+
+#define AH_5212_2317
+#include "ar5212/ar5212.ini"
+
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+
+typedef        RAW_DATA_STRUCT_2413 RAW_DATA_STRUCT_2317;
+typedef RAW_DATA_PER_CHANNEL_2413 RAW_DATA_PER_CHANNEL_2317;
+#define PWR_TABLE_SIZE_2317 PWR_TABLE_SIZE_2413
+
+struct ar2317State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[PWR_TABLE_SIZE_2317];
+
+       uint32_t        Bank1Data[N(ar5212Bank1_2317)];
+       uint32_t        Bank2Data[N(ar5212Bank2_2317)];
+       uint32_t        Bank3Data[N(ar5212Bank3_2317)];
+       uint32_t        Bank6Data[N(ar5212Bank6_2317)];
+       uint32_t        Bank7Data[N(ar5212Bank7_2317)];
+
+       /*
+        * Private state for reduced stack usage.
+        */
+       /* filled out Vpd table for all pdGains (chanL) */
+       uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (chanR) */
+       uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (interpolated) */
+       uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+};
+#define        AR2317(ah)      ((struct ar2317State *) AH5212(ah)->ah_rfHal)
+
+extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+               uint32_t numBits, uint32_t firstBit, uint32_t column);
+
+static void
+ar2317WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int writes)
+{
+       HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2317, modesIndex, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212Common_2317, 1, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2317, freqIndex, writes);
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar2317SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t channelSel  = 0;
+       uint32_t bModeSynth  = 0;
+       uint32_t aModeRefSel = 0;
+       uint32_t reg32       = 0;
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       if (chan->channel < 4800) {
+               uint32_t txctl;
+               channelSel = chan->channel - 2272 ;
+               channelSel = ath_hal_reverseBits(channelSel, 8);
+
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (chan->channel == 2484) {
+                       /* Enable channel spreading for channel 14 */
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+       } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 20 << 2), 8);
+               aModeRefSel = ath_hal_reverseBits(3, 2);
+       } else if ((chan->channel % 10) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 10 << 1), 8);
+               aModeRefSel = ath_hal_reverseBits(2, 2);
+       } else if ((chan->channel % 5) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       (chan->channel - 4800) / 5, 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
+                   __func__, chan->channel);
+               return AH_FALSE;
+       }
+
+       reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) |
+                       (1 << 12) | 0x1;
+       OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff);
+
+       reg32 >>= 8;
+       OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f);
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar2317SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+#define        RF_BANK_SETUP(_priv, _ix, _col) do {                                \
+       int i;                                                              \
+       for (i = 0; i < N(ar5212Bank##_ix##_2317); i++)                     \
+               (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2317[i][_col];\
+} while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t ob2GHz = 0, db2GHz = 0;
+       struct ar2317State *priv = AR2317(ah);
+       int regWrites = 0;
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+           "%s: chan 0x%x flag 0x%x modesIndex 0x%x\n",
+           __func__, chan->channel, chan->channelFlags, modesIndex);
+
+       HALASSERT(priv);
+
+       /* Setup rf parameters */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_B:
+               ob2GHz = ee->ee_obFor24;
+               db2GHz = ee->ee_dbFor24;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               ob2GHz = ee->ee_obFor24g;
+               db2GHz = ee->ee_dbFor24g;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /* Bank 1 Write */
+       RF_BANK_SETUP(priv, 1, 1);
+
+       /* Bank 2 Write */
+       RF_BANK_SETUP(priv, 2, modesIndex);
+
+       /* Bank 3 Write */
+       RF_BANK_SETUP(priv, 3, modesIndex);
+
+       /* Bank 6 Write */
+       RF_BANK_SETUP(priv, 6, modesIndex);
+
+       ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz,   3, 193, 0);
+       ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz,   3, 190, 0);
+
+       /* Bank 7 Setup */
+       RF_BANK_SETUP(priv, 7, modesIndex);
+
+       /* Write Analog registers */
+       HAL_INI_WRITE_BANK(ah, ar5212Bank1_2317, priv->Bank1Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank2_2317, priv->Bank2Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank3_2317, priv->Bank3Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank6_2317, priv->Bank6Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank7_2317, priv->Bank7Data, regWrites);
+       /* Now that we have reprogrammed rfgain value, clear the flag. */
+       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+
+       return AH_TRUE;
+#undef RF_BANK_SETUP
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar2317GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar2317State *priv = AR2317(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Return indices surrounding the value in sorted integer lists.
+ *
+ * NB: the input list is assumed to be sorted in ascending order
+ */
+static void
+GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize,
+                          uint32_t *vlo, uint32_t *vhi)
+{
+       int16_t target = v;
+       const int16_t *ep = lp+listSize;
+       const int16_t *tp;
+
+       /*
+        * Check first and last elements for out-of-bounds conditions.
+        */
+       if (target < lp[0]) {
+               *vlo = *vhi = 0;
+               return;
+       }
+       if (target >= ep[-1]) {
+               *vlo = *vhi = listSize - 1;
+               return;
+       }
+
+       /* look for value being near or between 2 values in list */
+       for (tp = lp; tp < ep; tp++) {
+               /*
+                * If value is close to the current value of the list
+                * then target is not between values, it is one of the values
+                */
+               if (*tp == target) {
+                       *vlo = *vhi = tp - (const int16_t *) lp;
+                       return;
+               }
+               /*
+                * Look for value being between current value and next value
+                * if so return these 2 values
+                */
+               if (target < tp[1]) {
+                       *vlo = tp - (const int16_t *) lp;
+                       *vhi = *vlo + 1;
+                       return;
+               }
+       }
+}
+
+/*
+ * Fill the Vpdlist for indices Pmax-Pmin
+ */
+static HAL_BOOL
+ar2317FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t  Pmax,
+                  const int16_t *pwrList, const int16_t *VpdList,
+                  uint16_t numIntercepts, uint16_t retVpdList[][64])
+{
+       uint16_t ii, jj, kk;
+       int16_t currPwr = (int16_t)(2*Pmin);
+       /* since Pmin is pwr*2 and pwrList is 4*pwr */
+       uint32_t  idxL = 0, idxR = 0;
+
+       ii = 0;
+       jj = 0;
+
+       if (numIntercepts < 2)
+               return AH_FALSE;
+
+       while (ii <= (uint16_t)(Pmax - Pmin)) {
+               GetLowerUpperIndex(currPwr, pwrList, numIntercepts,
+                                        &(idxL), &(idxR));
+               if (idxR < 1)
+                       idxR = 1;                       /* extrapolate below */
+               if (idxL == (uint32_t)(numIntercepts - 1))
+                       idxL = numIntercepts - 2;       /* extrapolate above */
+               if (pwrList[idxL] == pwrList[idxR])
+                       kk = VpdList[idxL];
+               else
+                       kk = (uint16_t)
+                               (((currPwr - pwrList[idxL])*VpdList[idxR]+
+                                 (pwrList[idxR] - currPwr)*VpdList[idxL])/
+                                (pwrList[idxR] - pwrList[idxL]));
+               retVpdList[pdGainIdx][ii] = kk;
+               ii++;
+               currPwr += 2;                           /* half dB steps */
+       }
+
+       return AH_TRUE;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+static int16_t
+interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+       int16_t targetLeft, int16_t targetRight)
+{
+       int16_t rv;
+
+       if (srcRight != srcLeft) {
+               rv = ((target - srcLeft)*targetRight +
+                     (srcRight - target)*targetLeft) / (srcRight - srcLeft);
+       } else {
+               rv = targetLeft;
+       }
+       return rv;
+}
+
+/*
+ * Uses the data points read from EEPROM to reconstruct the pdadc power table
+ * Called by ar2317SetPowerTable()
+ */
+static int
+ar2317getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel,
+               const RAW_DATA_STRUCT_2317 *pRawDataset,
+               uint16_t pdGainOverlap_t2,
+               int16_t  *pMinCalPower, uint16_t pPdGainBoundaries[],
+               uint16_t pPdGainValues[], uint16_t pPDADCValues[])
+{
+       struct ar2317State *priv = AR2317(ah);
+#define        VpdTable_L      priv->vpdTable_L
+#define        VpdTable_R      priv->vpdTable_R
+#define        VpdTable_I      priv->vpdTable_I
+       /* XXX excessive stack usage? */
+       uint32_t ii, jj, kk;
+       int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */
+       uint32_t idxL = 0, idxR = 0;
+       uint32_t numPdGainsUsed = 0;
+       /*
+        * If desired to support -ve power levels in future, just
+        * change pwr_I_0 to signed 5-bits.
+        */
+       int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on. */
+       int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on */
+       uint16_t numVpd = 0;
+       uint16_t Vpd_step;
+       int16_t tmpVal ;
+       uint32_t sizeCurrVpdTable, maxIndex, tgtIndex;
+
+       /* Get upper lower index */
+       GetLowerUpperIndex(channel, pRawDataset->pChannels,
+                                pRawDataset->numChannels, &(idxL), &(idxR));
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain;
+                       Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0];
+                       if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) {
+                               Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0];
+                       }
+                       Pmin_t2[numPdGainsUsed] = (int16_t)
+                               (Pmin_t2[numPdGainsUsed] / 2);
+                       Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1])
+                               Pmax_t2[numPdGainsUsed] =
+                                       pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2);
+                       ar2317FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L
+                                          );
+                       ar2317FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R
+                                          );
+                       for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) {
+                               VpdTable_I[numPdGainsUsed][kk] =
+                                       interpolate_signed(
+                                                          channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR],
+                                                          (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]);
+                       }
+                       /* fill VpdTable_I for this pdGain */
+                       numPdGainsUsed++;
+               }
+               /* if this pdGain is used */
+       }
+
+       *pMinCalPower = Pmin_t2[0];
+       kk = 0; /* index for the final table */
+       for (ii = 0; ii < numPdGainsUsed; ii++) {
+               if (ii == (numPdGainsUsed - 1))
+                       pPdGainBoundaries[ii] = Pmax_t2[ii] +
+                               PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB;
+               else
+                       pPdGainBoundaries[ii] = (uint16_t)
+                               ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 );
+               if (pPdGainBoundaries[ii] > 63) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: clamp pPdGainBoundaries[%d] %d\n",
+                          __func__, ii, pPdGainBoundaries[ii]);/*XXX*/
+                       pPdGainBoundaries[ii] = 63;
+               }
+
+               /* Find starting index for this pdGain */
+               if (ii == 0)
+                       ss = 0; /* for the first pdGain, start from index 0 */
+               else
+                       ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) -
+                               pdGainOverlap_t2;
+               Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                *-ve ss indicates need to extrapolate data below for this pdGain
+                */
+               while (ss < 0) {
+                       tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step);
+                       pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal);
+                       ss++;
+               }
+
+               sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii];
+               tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii];
+               maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
+
+               while (ss < (int16_t)maxIndex)
+                       pPDADCValues[kk++] = VpdTable_I[ii][ss++];
+
+               Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] -
+                                      VpdTable_I[ii][sizeCurrVpdTable-2]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                * for last gain, pdGainBoundary == Pmax_t2, so will
+                * have to extrapolate
+                */
+               if (tgtIndex > maxIndex) {      /* need to extrapolate above */
+                       while(ss < (int16_t)tgtIndex) {
+                               tmpVal = (uint16_t)
+                                       (VpdTable_I[ii][sizeCurrVpdTable-1] +
+                                        (ss-maxIndex)*Vpd_step);
+                               pPDADCValues[kk++] = (tmpVal > 127) ?
+                                       127 : tmpVal;
+                               ss++;
+                       }
+               }                               /* extrapolated above */
+       }                                       /* for all pdGainUsed */
+
+       while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) {
+               pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1];
+               ii++;
+       }
+       while (kk < 128) {
+               pPDADCValues[kk] = pPDADCValues[kk-1];
+               kk++;
+       }
+
+       return numPdGainsUsed;
+#undef VpdTable_L
+#undef VpdTable_R
+#undef VpdTable_I
+}
+
+static HAL_BOOL
+ar2317SetPowerTable(struct ath_hal *ah,
+       int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t *rfXpdGain)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2317 *pRawDataset = AH_NULL;
+       uint16_t pdGainOverlap_t2;
+       int16_t minCalPower2317_t2;
+       uint16_t *pdadcValues = ahp->ah_pcdacTable;
+       uint16_t gainBoundaries[4];
+       uint32_t reg32, regoffset;
+       int i, numPdGainsUsed;
+#ifndef AH_USE_INIPDGAIN
+       uint32_t tpcrg1;
+#endif
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n",
+           __func__, chan->channel,chan->channelFlags);
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__);
+               return AH_FALSE;
+       }
+
+       pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5),
+                                         AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
+
+       numPdGainsUsed = ar2317getGainBoundariesAndPdadcsForPowers(ah,
+               chan->channel, pRawDataset, pdGainOverlap_t2,
+               &minCalPower2317_t2,gainBoundaries, rfXpdGain, pdadcValues);
+       HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3);
+
+#ifdef AH_USE_INIPDGAIN
+       /*
+        * Use pd_gains curve from eeprom; Atheros always uses
+        * the default curve from the ini file but some vendors
+        * (e.g. Zcomax) want to override this curve and not
+        * honoring their settings results in tx power 5dBm low.
+        */
+       OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                        (pRawDataset->pDataPerChannel[0].numPdGains - 1));
+#else
+       tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1);
+       tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN)
+                 | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN);
+       switch (numPdGainsUsed) {
+       case 3:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3;
+               tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3);
+               /* fall thru... */
+       case 2:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2;
+               tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2);
+               /* fall thru... */
+       case 1:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1;
+               tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1);
+               break;
+       }
+#ifdef AH_DEBUG
+       if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1))
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default "
+                   "pd_gains (default 0x%x, calculated 0x%x)\n",
+                   __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1);
+#endif
+       OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1);
+#endif
+
+       /*
+        * Note the pdadc table may not start at 0 dBm power, could be
+        * negative or greater than 0.  Need to offset the power
+        * values by the amount of minPower for griffin
+        */
+       if (minCalPower2317_t2 != 0)
+               ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2317_t2);
+       else
+               ahp->ah_txPowerIndexOffset = 0;
+
+       /* Finally, write the power values into the baseband power table */
+       regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */
+       for (i = 0; i < 32; i++) {
+               reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0)  |
+                       ((pdadcValues[4*i + 1] & 0xFF) << 8)  |
+                       ((pdadcValues[4*i + 2] & 0xFF) << 16) |
+                       ((pdadcValues[4*i + 3] & 0xFF) << 24) ;
+               OS_REG_WRITE(ah, regoffset, reg32);
+               regoffset += 4;
+       }
+
+       OS_REG_WRITE(ah, AR_PHY_TPCRG5,
+                    SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                    SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
+                    SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
+                    SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
+                    SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+
+       return AH_TRUE;
+}
+
+static int16_t
+ar2317GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2317 *data)
+{
+       uint32_t ii,jj;
+       uint16_t Pmin=0,numVpd;
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = data->pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       Pmin = data->pDataPerPDGain[jj].pwr_t4[0];
+                       return(Pmin);
+               }
+       }
+       return(Pmin);
+}
+
+static int16_t
+ar2317GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2317 *data)
+{
+       uint32_t ii;
+       uint16_t Pmax=0,numVpd;
+       uint16_t vpdmax;
+
+       for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               /* work forwards cuase lowest pdGain for highest power */
+               numVpd = data->pDataPerPDGain[ii].numVpd;
+               if (numVpd > 0) {
+                       Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1];
+                       vpdmax = data->pDataPerPDGain[ii].Vpd[numVpd-1];
+                       return(Pmax);
+               }
+       }
+       return(Pmax);
+}
+
+static HAL_BOOL
+ar2317GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan,
+       int16_t *maxPow, int16_t *minPow)
+{
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2317 *pRawDataset = AH_NULL;
+       const RAW_DATA_PER_CHANNEL_2317 *data=AH_NULL;
+       uint16_t numChannels;
+       int totalD,totalF, totalMin,last, i;
+
+       *maxPow = 0;
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else
+               return(AH_FALSE);
+
+       numChannels = pRawDataset->numChannels;
+       data = pRawDataset->pDataPerChannel;
+
+       /* Make sure the channel is in the range of the TP values
+        *  (freq piers)
+        */
+       if (numChannels < 1)
+               return(AH_FALSE);
+
+       if ((chan->channel < data[0].channelValue) ||
+           (chan->channel > data[numChannels-1].channelValue)) {
+               if (chan->channel < data[0].channelValue) {
+                       *maxPow = ar2317GetMaxPower(ah, &data[0]);
+                       *minPow = ar2317GetMinPower(ah, &data[0]);
+                       return(AH_TRUE);
+               } else {
+                       *maxPow = ar2317GetMaxPower(ah, &data[numChannels - 1]);
+                       *minPow = ar2317GetMinPower(ah, &data[numChannels - 1]);
+                       return(AH_TRUE);
+               }
+       }
+
+       /* Linearly interpolate the power value now */
+       for (last=0,i=0; (i<numChannels) && (chan->channel > data[i].channelValue);
+            last = i++);
+       totalD = data[i].channelValue - data[last].channelValue;
+       if (totalD > 0) {
+               totalF = ar2317GetMaxPower(ah, &data[i]) - ar2317GetMaxPower(ah, &data[last]);
+               *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) +
+                                    ar2317GetMaxPower(ah, &data[last])*totalD)/totalD);
+               totalMin = ar2317GetMinPower(ah, &data[i]) - ar2317GetMinPower(ah, &data[last]);
+               *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) +
+                                    ar2317GetMinPower(ah, &data[last])*totalD)/totalD);
+               return(AH_TRUE);
+       } else {
+               if (chan->channel == data[i].channelValue) {
+                       *maxPow = ar2317GetMaxPower(ah, &data[i]);
+                       *minPow = ar2317GetMinPower(ah, &data[i]);
+                       return(AH_TRUE);
+               } else
+                       return(AH_FALSE);
+       }
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar2317RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for analog bank scratch buffers
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+static HAL_BOOL
+ar2317RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar2317State *priv;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar2317State));
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar2317RfDetach;
+       priv->base.writeRegs            = ar2317WriteRegs;
+       priv->base.getRfBank            = ar2317GetRfBank;
+       priv->base.setChannel           = ar2317SetChannel;
+       priv->base.setRfRegs            = ar2317SetRfRegs;
+       priv->base.setPowerTable        = ar2317SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar2317GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar5212GetNfAdjust;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+ar2317Probe(struct ath_hal *ah)
+{
+       return IS_2317(ah);
+}
+AH_RF(RF2317, ar2317Probe, ar2317RfAttach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar2413.c   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,759 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar2413.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#include "ah_eeprom_v3.h"
+
+#define AH_5212_2413
+#include "ar5212/ar5212.ini"
+
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+
+struct ar2413State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[PWR_TABLE_SIZE_2413];
+
+       uint32_t        Bank1Data[N(ar5212Bank1_2413)];
+       uint32_t        Bank2Data[N(ar5212Bank2_2413)];
+       uint32_t        Bank3Data[N(ar5212Bank3_2413)];
+       uint32_t        Bank6Data[N(ar5212Bank6_2413)];
+       uint32_t        Bank7Data[N(ar5212Bank7_2413)];
+
+       /*
+        * Private state for reduced stack usage.
+        */
+       /* filled out Vpd table for all pdGains (chanL) */
+       uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (chanR) */
+       uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (interpolated) */
+       uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+};
+#define        AR2413(ah)      ((struct ar2413State *) AH5212(ah)->ah_rfHal)
+
+extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+               uint32_t numBits, uint32_t firstBit, uint32_t column);
+
+static void
+ar2413WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int writes)
+{
+       HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2413, modesIndex, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212Common_2413, 1, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2413, freqIndex, writes);
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar2413SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t channelSel  = 0;
+       uint32_t bModeSynth  = 0;
+       uint32_t aModeRefSel = 0;
+       uint32_t reg32       = 0;
+       uint16_t freq;
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       if (chan->channel < 4800) {
+               uint32_t txctl;
+
+               if (((chan->channel - 2192) % 5) == 0) {
+                       channelSel = ((chan->channel - 672) * 2 - 3040)/10;
+                       bModeSynth = 0;
+               } else if (((chan->channel - 2224) % 5) == 0) {
+                       channelSel = ((chan->channel - 704) * 2 - 3040) / 10;
+                       bModeSynth = 1;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid channel %u MHz\n",
+                           __func__, chan->channel);
+                       return AH_FALSE;
+               }
+
+               channelSel = (channelSel << 2) & 0xff;
+               channelSel = ath_hal_reverseBits(channelSel, 8);
+
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (chan->channel == 2484) {
+                       /* Enable channel spreading for channel 14 */
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+       } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) {
+               freq = chan->channel - 2; /* Align to even 5MHz raster */
+               channelSel = ath_hal_reverseBits(
+                       (uint32_t)(((freq - 4800)*10)/25 + 1), 8);
+               aModeRefSel = ath_hal_reverseBits(0, 2);
+       } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 20 << 2), 8);
+               aModeRefSel = ath_hal_reverseBits(3, 2);
+       } else if ((chan->channel % 10) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 10 << 1), 8);
+               aModeRefSel = ath_hal_reverseBits(2, 2);
+       } else if ((chan->channel % 5) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       (chan->channel - 4800) / 5, 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
+                   __func__, chan->channel);
+               return AH_FALSE;
+       }
+
+       reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) |
+                       (1 << 12) | 0x1;
+       OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff);
+
+       reg32 >>= 8;
+       OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f);
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+
+       return AH_TRUE;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar2413SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+#define        RF_BANK_SETUP(_priv, _ix, _col) do {                                \
+       int i;                                                              \
+       for (i = 0; i < N(ar5212Bank##_ix##_2413); i++)                     \
+               (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2413[i][_col];\
+} while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t ob2GHz = 0, db2GHz = 0;
+       struct ar2413State *priv = AR2413(ah);
+       int regWrites = 0;
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+           "%s: chan 0x%x flag 0x%x modesIndex 0x%x\n",
+           __func__, chan->channel, chan->channelFlags, modesIndex);
+
+       HALASSERT(priv);
+
+       /* Setup rf parameters */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_B:
+               ob2GHz = ee->ee_obFor24;
+               db2GHz = ee->ee_dbFor24;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               ob2GHz = ee->ee_obFor24g;
+               db2GHz = ee->ee_dbFor24g;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /* Bank 1 Write */
+       RF_BANK_SETUP(priv, 1, 1);
+
+       /* Bank 2 Write */
+       RF_BANK_SETUP(priv, 2, modesIndex);
+
+       /* Bank 3 Write */
+       RF_BANK_SETUP(priv, 3, modesIndex);
+
+       /* Bank 6 Write */
+       RF_BANK_SETUP(priv, 6, modesIndex);
+
+       ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz,   3, 168, 0);
+       ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz,   3, 165, 0);
+
+       /* Bank 7 Setup */
+       RF_BANK_SETUP(priv, 7, modesIndex);
+
+       /* Write Analog registers */
+       HAL_INI_WRITE_BANK(ah, ar5212Bank1_2413, priv->Bank1Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank2_2413, priv->Bank2Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank3_2413, priv->Bank3Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank6_2413, priv->Bank6Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank7_2413, priv->Bank7Data, regWrites);
+
+       /* Now that we have reprogrammed rfgain value, clear the flag. */
+       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+
+       return AH_TRUE;
+#undef RF_BANK_SETUP
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar2413GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar2413State *priv = AR2413(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Return indices surrounding the value in sorted integer lists.
+ *
+ * NB: the input list is assumed to be sorted in ascending order
+ */
+static void
+GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize,
+                          uint32_t *vlo, uint32_t *vhi)
+{
+       int16_t target = v;
+       const uint16_t *ep = lp+listSize;
+       const uint16_t *tp;
+
+       /*
+        * Check first and last elements for out-of-bounds conditions.
+        */
+       if (target < lp[0]) {
+               *vlo = *vhi = 0;
+               return;
+       }
+       if (target >= ep[-1]) {
+               *vlo = *vhi = listSize - 1;
+               return;
+       }
+
+       /* look for value being near or between 2 values in list */
+       for (tp = lp; tp < ep; tp++) {
+               /*
+                * If value is close to the current value of the list
+                * then target is not between values, it is one of the values
+                */
+               if (*tp == target) {
+                       *vlo = *vhi = tp - (const uint16_t *) lp;
+                       return;
+               }
+               /*
+                * Look for value being between current value and next value
+                * if so return these 2 values
+                */
+               if (target < tp[1]) {
+                       *vlo = tp - (const uint16_t *) lp;
+                       *vhi = *vlo + 1;
+                       return;
+               }
+       }
+}
+
+/*
+ * Fill the Vpdlist for indices Pmax-Pmin
+ */
+static HAL_BOOL
+ar2413FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t  Pmax,
+                  const int16_t *pwrList, const uint16_t *VpdList,
+                  uint16_t numIntercepts, uint16_t retVpdList[][64])
+{
+       uint16_t ii, jj, kk;
+       int16_t currPwr = (int16_t)(2*Pmin);
+       /* since Pmin is pwr*2 and pwrList is 4*pwr */
+       uint32_t  idxL = 0, idxR = 0;
+
+       ii = 0;
+       jj = 0;
+
+       if (numIntercepts < 2)
+               return AH_FALSE;
+
+       while (ii <= (uint16_t)(Pmax - Pmin)) {
+               GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList,
+                                  numIntercepts, &(idxL), &(idxR));
+               if (idxR < 1)
+                       idxR = 1;                       /* extrapolate below */
+               if (idxL == (uint32_t)(numIntercepts - 1))
+                       idxL = numIntercepts - 2;       /* extrapolate above */
+               if (pwrList[idxL] == pwrList[idxR])
+                       kk = VpdList[idxL];
+               else
+                       kk = (uint16_t)
+                               (((currPwr - pwrList[idxL])*VpdList[idxR]+
+                                 (pwrList[idxR] - currPwr)*VpdList[idxL])/
+                                (pwrList[idxR] - pwrList[idxL]));
+               retVpdList[pdGainIdx][ii] = kk;
+               ii++;
+               currPwr += 2;                           /* half dB steps */
+       }
+
+       return AH_TRUE;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+static int16_t
+interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+       int16_t targetLeft, int16_t targetRight)
+{
+       int16_t rv;
+
+       if (srcRight != srcLeft) {
+               rv = ((target - srcLeft)*targetRight +
+                     (srcRight - target)*targetLeft) / (srcRight - srcLeft);
+       } else {
+               rv = targetLeft;
+       }
+       return rv;
+}
+
+/*
+ * Uses the data points read from EEPROM to reconstruct the pdadc power table
+ * Called by ar2413SetPowerTable()
+ */
+static int
+ar2413getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel,
+               const RAW_DATA_STRUCT_2413 *pRawDataset,
+               uint16_t pdGainOverlap_t2,
+               int16_t  *pMinCalPower, uint16_t pPdGainBoundaries[],
+               uint16_t pPdGainValues[], uint16_t pPDADCValues[])
+{
+       struct ar2413State *priv = AR2413(ah);
+#define        VpdTable_L      priv->vpdTable_L
+#define        VpdTable_R      priv->vpdTable_R
+#define        VpdTable_I      priv->vpdTable_I
+       uint32_t ii, jj, kk;
+       int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */
+       uint32_t idxL = 0, idxR = 0;
+       uint32_t numPdGainsUsed = 0;
+       /*
+        * If desired to support -ve power levels in future, just
+        * change pwr_I_0 to signed 5-bits.
+        */
+       int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on. */
+       int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on */
+       uint16_t numVpd = 0;
+       uint16_t Vpd_step;
+       int16_t tmpVal ;
+       uint32_t sizeCurrVpdTable, maxIndex, tgtIndex;
+
+       /* Get upper lower index */
+       GetLowerUpperIndex(channel, pRawDataset->pChannels,
+                                pRawDataset->numChannels, &(idxL), &(idxR));
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain;
+                       Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0];
+                       if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) {
+                               Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0];
+                       }
+                       Pmin_t2[numPdGainsUsed] = (int16_t)
+                               (Pmin_t2[numPdGainsUsed] / 2);
+                       Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1])
+                               Pmax_t2[numPdGainsUsed] =
+                                       pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2);
+                       ar2413FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L
+                                          );
+                       ar2413FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R
+                                          );
+                       for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) {
+                               VpdTable_I[numPdGainsUsed][kk] =
+                                       interpolate_signed(
+                                                          channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR],
+                                                          (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]);
+                       }
+                       /* fill VpdTable_I for this pdGain */
+                       numPdGainsUsed++;
+               }
+               /* if this pdGain is used */
+       }
+
+       *pMinCalPower = Pmin_t2[0];
+       kk = 0; /* index for the final table */
+       for (ii = 0; ii < numPdGainsUsed; ii++) {
+               if (ii == (numPdGainsUsed - 1))
+                       pPdGainBoundaries[ii] = Pmax_t2[ii] +
+                               PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB;
+               else
+                       pPdGainBoundaries[ii] = (uint16_t)
+                               ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 );
+               if (pPdGainBoundaries[ii] > 63) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: clamp pPdGainBoundaries[%d] %d\n",
+                           __func__, ii, pPdGainBoundaries[ii]);/*XXX*/
+                       pPdGainBoundaries[ii] = 63;
+               }
+
+               /* Find starting index for this pdGain */
+               if (ii == 0)
+                       ss = 0; /* for the first pdGain, start from index 0 */
+               else
+                       ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) -
+                               pdGainOverlap_t2;
+               Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                *-ve ss indicates need to extrapolate data below for this pdGain
+                */
+               while (ss < 0) {
+                       tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step);
+                       pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal);
+                       ss++;
+               }
+
+               sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii];
+               tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii];
+               maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
+
+               while (ss < (int16_t)maxIndex)
+                       pPDADCValues[kk++] = VpdTable_I[ii][ss++];
+
+               Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] -
+                                      VpdTable_I[ii][sizeCurrVpdTable-2]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                * for last gain, pdGainBoundary == Pmax_t2, so will
+                * have to extrapolate
+                */
+               if (tgtIndex > maxIndex) {      /* need to extrapolate above */
+                       while(ss < (int16_t)tgtIndex) {
+                               tmpVal = (uint16_t)
+                                       (VpdTable_I[ii][sizeCurrVpdTable-1] +
+                                        (ss-maxIndex)*Vpd_step);
+                               pPDADCValues[kk++] = (tmpVal > 127) ?
+                                       127 : tmpVal;
+                               ss++;
+                       }
+               }                               /* extrapolated above */
+       }                                       /* for all pdGainUsed */
+
+       while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) {
+               pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1];
+               ii++;
+       }
+       while (kk < 128) {
+               pPDADCValues[kk] = pPDADCValues[kk-1];
+               kk++;
+       }
+
+       return numPdGainsUsed;
+#undef VpdTable_L
+#undef VpdTable_R
+#undef VpdTable_I
+}
+
+static HAL_BOOL
+ar2413SetPowerTable(struct ath_hal *ah,
+       int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t *rfXpdGain)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL;
+       uint16_t pdGainOverlap_t2;
+       int16_t minCalPower2413_t2;
+       uint16_t *pdadcValues = ahp->ah_pcdacTable;
+       uint16_t gainBoundaries[4];
+       uint32_t reg32, regoffset;
+       int i, numPdGainsUsed;
+#ifndef AH_USE_INIPDGAIN
+       uint32_t tpcrg1;
+#endif
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n",
+           __func__, chan->channel,chan->channelFlags);
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__);
+               return AH_FALSE;
+       }
+
+       pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5),
+                                         AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
+
+       numPdGainsUsed = ar2413getGainBoundariesAndPdadcsForPowers(ah,
+               chan->channel, pRawDataset, pdGainOverlap_t2,
+               &minCalPower2413_t2,gainBoundaries, rfXpdGain, pdadcValues);
+       HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3);
+
+#ifdef AH_USE_INIPDGAIN
+       /*
+        * Use pd_gains curve from eeprom; Atheros always uses
+        * the default curve from the ini file but some vendors
+        * (e.g. Zcomax) want to override this curve and not
+        * honoring their settings results in tx power 5dBm low.
+        */
+       OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                        (pRawDataset->pDataPerChannel[0].numPdGains - 1));
+#else
+       tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1);
+       tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN)
+                 | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN);
+       switch (numPdGainsUsed) {
+       case 3:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3;
+               tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3);
+               /* fall thru... */
+       case 2:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2;
+               tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2);
+               /* fall thru... */
+       case 1:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1;
+               tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1);
+               break;
+       }
+#ifdef AH_DEBUG
+       if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1))
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default "
+                   "pd_gains (default 0x%x, calculated 0x%x)\n",
+                   __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1);
+#endif
+       OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1);
+#endif
+
+       /*
+        * Note the pdadc table may not start at 0 dBm power, could be
+        * negative or greater than 0.  Need to offset the power
+        * values by the amount of minPower for griffin
+        */
+       if (minCalPower2413_t2 != 0)
+               ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2413_t2);
+       else
+               ahp->ah_txPowerIndexOffset = 0;
+
+       /* Finally, write the power values into the baseband power table */
+       regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */
+       for (i = 0; i < 32; i++) {
+               reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0)  |
+                       ((pdadcValues[4*i + 1] & 0xFF) << 8)  |
+                       ((pdadcValues[4*i + 2] & 0xFF) << 16) |
+                       ((pdadcValues[4*i + 3] & 0xFF) << 24) ;
+               OS_REG_WRITE(ah, regoffset, reg32);
+               regoffset += 4;
+       }
+
+       OS_REG_WRITE(ah, AR_PHY_TPCRG5,
+                    SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                    SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
+                    SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
+                    SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
+                    SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+
+       return AH_TRUE;
+}
+
+static int16_t
+ar2413GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data)
+{
+       uint32_t ii,jj;
+       uint16_t Pmin=0,numVpd;
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = data->pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       Pmin = data->pDataPerPDGain[jj].pwr_t4[0];
+                       return(Pmin);
+               }
+       }
+       return(Pmin);
+}
+
+static int16_t
+ar2413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data)
+{
+       uint32_t ii;
+       uint16_t Pmax=0,numVpd;
+
+       for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               /* work forwards cuase lowest pdGain for highest power */
+               numVpd = data->pDataPerPDGain[ii].numVpd;
+               if (numVpd > 0) {
+                       Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1];
+                       return(Pmax);
+               }
+       }
+       return(Pmax);
+}
+
+static HAL_BOOL
+ar2413GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan,
+       int16_t *maxPow, int16_t *minPow)
+{
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL;
+       const RAW_DATA_PER_CHANNEL_2413 *data = AH_NULL;
+       uint16_t numChannels;
+       int totalD,totalF, totalMin,last, i;
+
+       *maxPow = 0;
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else
+               return(AH_FALSE);
+
+       numChannels = pRawDataset->numChannels;
+       data = pRawDataset->pDataPerChannel;
+
+       /* Make sure the channel is in the range of the TP values
+        *  (freq piers)
+        */
+       if (numChannels < 1)
+               return(AH_FALSE);
+
+       if ((chan->channel < data[0].channelValue) ||
+           (chan->channel > data[numChannels-1].channelValue)) {
+               if (chan->channel < data[0].channelValue) {
+                       *maxPow = ar2413GetMaxPower(ah, &data[0]);
+                       *minPow = ar2413GetMinPower(ah, &data[0]);
+                       return(AH_TRUE);
+               } else {
+                       *maxPow = ar2413GetMaxPower(ah, &data[numChannels - 1]);
+                       *minPow = ar2413GetMinPower(ah, &data[numChannels - 1]);
+                       return(AH_TRUE);
+               }
+       }
+
+       /* Linearly interpolate the power value now */
+       for (last=0,i=0; (i<numChannels) && (chan->channel > data[i].channelValue);
+            last = i++);
+       totalD = data[i].channelValue - data[last].channelValue;
+       if (totalD > 0) {
+               totalF = ar2413GetMaxPower(ah, &data[i]) - ar2413GetMaxPower(ah, &data[last]);
+               *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) +
+                                    ar2413GetMaxPower(ah, &data[last])*totalD)/totalD);
+               totalMin = ar2413GetMinPower(ah, &data[i]) - ar2413GetMinPower(ah, &data[last]);
+               *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) +
+                                    ar2413GetMinPower(ah, &data[last])*totalD)/totalD);
+               return(AH_TRUE);
+       } else {
+               if (chan->channel == data[i].channelValue) {
+                       *maxPow = ar2413GetMaxPower(ah, &data[i]);
+                       *minPow = ar2413GetMinPower(ah, &data[i]);
+                       return(AH_TRUE);
+               } else
+                       return(AH_FALSE);
+       }
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar2413RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for analog bank scratch buffers
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+static HAL_BOOL
+ar2413RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar2413State *priv;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar2413State));
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar2413RfDetach;
+       priv->base.writeRegs            = ar2413WriteRegs;
+       priv->base.getRfBank            = ar2413GetRfBank;
+       priv->base.setChannel           = ar2413SetChannel;
+       priv->base.setRfRegs            = ar2413SetRfRegs;
+       priv->base.setPowerTable        = ar2413SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar2413GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar5212GetNfAdjust;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+ar2413Probe(struct ath_hal *ah)
+{
+       return IS_2413(ah);
+}
+AH_RF(RF2413, ar2413Probe, ar2413RfAttach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar2425.c   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,722 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar2425.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#include "ah_eeprom_v3.h"
+
+#define AH_5212_2425
+#define AH_5212_2417
+#include "ar5212/ar5212.ini"
+
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+
+struct ar2425State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[PWR_TABLE_SIZE_2413];
+
+       uint32_t        Bank1Data[N(ar5212Bank1_2425)];
+       uint32_t        Bank2Data[N(ar5212Bank2_2425)];
+       uint32_t        Bank3Data[N(ar5212Bank3_2425)];
+       uint32_t        Bank6Data[N(ar5212Bank6_2425)]; /* 2417 is same size */
+       uint32_t        Bank7Data[N(ar5212Bank7_2425)];
+};
+#define        AR2425(ah)      ((struct ar2425State *) AH5212(ah)->ah_rfHal)
+
+extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+               uint32_t numBits, uint32_t firstBit, uint32_t column);
+
+static void
+ar2425WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int writes)
+{
+       HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2425, modesIndex, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212Common_2425, 1, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2425, freqIndex, writes);
+#if 0
+       /*
+        * for SWAN similar to Condor
+        * Bit 0 enables link to go to L1 when MAC goes to sleep.
+        * Bit 3 enables the loop back the link down to reset.
+        */
+       if (IS_PCIE(ah) && ath_hal_pcieL1SKPEnable) {
+               OS_REG_WRITE(ah, AR_PCIE_PMC,
+                   AR_PCIE_PMC_ENA_L1 | AR_PCIE_PMC_ENA_RESET);
+       }
+       /*
+        * for Standby issue in Swan/Condor.
+        * Bit 9 (MAC_WOW_PWR_STATE_MASK_D2)to be set to avoid skips
+        *      before last Training Sequence 2 (TS2)
+        * Bit 8 (MAC_WOW_PWR_STATE_MASK_D1)to be unset to assert
+        *      Power Reset along with PCI Reset
+        */
+       OS_REG_SET_BIT(ah, AR_PCIE_PMC, MAC_WOW_PWR_STATE_MASK_D2);
+#endif
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar2425SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t channelSel  = 0;
+       uint32_t bModeSynth  = 0;
+       uint32_t aModeRefSel = 0;
+       uint32_t reg32       = 0;
+       uint16_t freq;
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       if (chan->channel < 4800) {
+               uint32_t txctl;
+
+        channelSel = chan->channel - 2272;
+        channelSel = ath_hal_reverseBits(channelSel, 8);
+
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+        if (chan->channel == 2484) {
+                       // Enable channel spreading for channel 14
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+
+       } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) {
+               freq = chan->channel - 2; /* Align to even 5MHz raster */
+               channelSel = ath_hal_reverseBits(
+                       (uint32_t)(((freq - 4800)*10)/25 + 1), 8);
+               aModeRefSel = ath_hal_reverseBits(0, 2);
+       } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 20 << 2), 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else if ((chan->channel % 10) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 10 << 1), 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else if ((chan->channel % 5) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       (chan->channel - 4800) / 5, 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
+                   __func__, chan->channel);
+               return AH_FALSE;
+       }
+
+       reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) |
+                       (1 << 12) | 0x1;
+       OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff);
+
+       reg32 >>= 8;
+       OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f);
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar2425SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+#define        RF_BANK_SETUP(_priv, _ix, _col) do {                                \
+       int i;                                                              \
+       for (i = 0; i < N(ar5212Bank##_ix##_2425); i++)                     \
+               (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2425[i][_col];\
+} while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       struct ar2425State *priv = AR2425(ah);
+       uint16_t ob2GHz = 0, db2GHz = 0;
+       int regWrites = 0;
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+           "==>%s:chan 0x%x flag 0x%x modesIndex 0x%x\n",
+           __func__, chan->channel, chan->channelFlags, modesIndex);
+
+       HALASSERT(priv);
+
+       /* Setup rf parameters */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_B:
+               ob2GHz = ee->ee_obFor24;
+               db2GHz = ee->ee_dbFor24;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               ob2GHz = ee->ee_obFor24g;
+               db2GHz = ee->ee_dbFor24g;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                       __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /* Bank 1 Write */
+       RF_BANK_SETUP(priv, 1, 1);
+
+       /* Bank 2 Write */
+       RF_BANK_SETUP(priv, 2, modesIndex);
+
+       /* Bank 3 Write */
+       RF_BANK_SETUP(priv, 3, modesIndex);
+
+       /* Bank 6 Write */
+       RF_BANK_SETUP(priv, 6, modesIndex);
+
+        ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 193, 0);
+        ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 190, 0);
+
+       /* Bank 7 Setup */
+       RF_BANK_SETUP(priv, 7, modesIndex);
+
+       /* Write Analog registers */
+       HAL_INI_WRITE_BANK(ah, ar5212Bank1_2425, priv->Bank1Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank2_2425, priv->Bank2Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank3_2425, priv->Bank3Data, regWrites);
+       if (IS_2417(ah)) {
+               HALASSERT(N(ar5212Bank6_2425) == N(ar5212Bank6_2417));
+               HAL_INI_WRITE_BANK(ah, ar5212Bank6_2417, priv->Bank6Data,
+                   regWrites);
+       } else
+               HAL_INI_WRITE_BANK(ah, ar5212Bank6_2425, priv->Bank6Data,
+                   regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank7_2425, priv->Bank7Data, regWrites);
+
+       /* Now that we have reprogrammed rfgain value, clear the flag. */
+       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM, "<==%s\n", __func__);
+       return AH_TRUE;
+#undef RF_BANK_SETUP
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar2425GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar2425State *priv = AR2425(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Return indices surrounding the value in sorted integer lists.
+ *
+ * NB: the input list is assumed to be sorted in ascending order
+ */
+static void
+GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize,
+                          uint32_t *vlo, uint32_t *vhi)
+{
+       int16_t target = v;
+       const uint16_t *ep = lp+listSize;
+       const uint16_t *tp;
+
+       /*
+        * Check first and last elements for out-of-bounds conditions.
+        */
+       if (target < lp[0]) {
+               *vlo = *vhi = 0;
+               return;
+       }
+       if (target >= ep[-1]) {
+               *vlo = *vhi = listSize - 1;
+               return;
+       }
+
+       /* look for value being near or between 2 values in list */
+       for (tp = lp; tp < ep; tp++) {
+               /*
+                * If value is close to the current value of the list
+                * then target is not between values, it is one of the values
+                */
+               if (*tp == target) {
+                       *vlo = *vhi = tp - (const uint16_t *) lp;
+                       return;
+               }
+               /*
+                * Look for value being between current value and next value
+                * if so return these 2 values
+                */
+               if (target < tp[1]) {
+                       *vlo = tp - (const uint16_t *) lp;
+                       *vhi = *vlo + 1;
+                       return;
+               }
+       }
+}
+
+/*
+ * Fill the Vpdlist for indices Pmax-Pmin
+ */
+static HAL_BOOL
+ar2425FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t  Pmax,
+                  const int16_t *pwrList, const uint16_t *VpdList,
+                  uint16_t numIntercepts,
+                  uint16_t retVpdList[][64])
+{
+       uint16_t ii, jj, kk;
+       int16_t currPwr = (int16_t)(2*Pmin);
+       /* since Pmin is pwr*2 and pwrList is 4*pwr */
+       uint32_t  idxL = 0, idxR = 0;
+
+       ii = 0;
+       jj = 0;
+
+       if (numIntercepts < 2)
+               return AH_FALSE;
+
+       while (ii <= (uint16_t)(Pmax - Pmin)) {
+               GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList,
+                                  numIntercepts, &(idxL), &(idxR));
+               if (idxR < 1)
+                       idxR = 1;                       /* extrapolate below */
+               if (idxL == (uint32_t)(numIntercepts - 1))
+                       idxL = numIntercepts - 2;       /* extrapolate above */
+               if (pwrList[idxL] == pwrList[idxR])
+                       kk = VpdList[idxL];
+               else
+                       kk = (uint16_t)
+                               (((currPwr - pwrList[idxL])*VpdList[idxR]+
+                                 (pwrList[idxR] - currPwr)*VpdList[idxL])/
+                                (pwrList[idxR] - pwrList[idxL]));
+               retVpdList[pdGainIdx][ii] = kk;
+               ii++;
+               currPwr += 2;                           /* half dB steps */
+       }
+
+       return AH_TRUE;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+static int16_t
+interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+       int16_t targetLeft, int16_t targetRight)
+{
+       int16_t rv;
+
+       if (srcRight != srcLeft) {
+               rv = ((target - srcLeft)*targetRight +
+                     (srcRight - target)*targetLeft) / (srcRight - srcLeft);
+       } else {
+               rv = targetLeft;
+       }
+       return rv;
+}
+
+/*
+ * Uses the data points read from EEPROM to reconstruct the pdadc power table
+ * Called by ar2425SetPowerTable()
+ */
+static void
+ar2425getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel,
+               const RAW_DATA_STRUCT_2413 *pRawDataset,
+               uint16_t pdGainOverlap_t2,
+               int16_t  *pMinCalPower, uint16_t pPdGainBoundaries[],
+               uint16_t pPdGainValues[], uint16_t pPDADCValues[])
+{
+    /* Note the items statically allocated below are to reduce stack usage */
+       uint32_t ii, jj, kk;
+       int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */
+       uint32_t idxL = 0, idxR = 0;
+       uint32_t numPdGainsUsed = 0;
+        static uint16_t VpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (chanL) */
+        static uint16_t VpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (chanR) */
+        static uint16_t VpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (interpolated) */
+       /*
+        * If desired to support -ve power levels in future, just
+        * change pwr_I_0 to signed 5-bits.
+        */
+        static int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on. */
+        static int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on */
+       uint16_t numVpd = 0;
+       uint16_t Vpd_step;
+       int16_t tmpVal ;
+       uint32_t sizeCurrVpdTable, maxIndex, tgtIndex;
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM, "==>%s:\n", __func__);
+
+       /* Get upper lower index */
+       GetLowerUpperIndex(channel, pRawDataset->pChannels,
+                                pRawDataset->numChannels, &(idxL), &(idxR));
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain;
+                       Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0];
+                       if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) {
+                               Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0];
+                       }
+                       Pmin_t2[numPdGainsUsed] = (int16_t)
+                               (Pmin_t2[numPdGainsUsed] / 2);
+                       Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1])
+                               Pmax_t2[numPdGainsUsed] =
+                                       pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2);
+                       ar2425FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L
+                                          );
+                       ar2425FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R
+                                          );
+                       for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) {
+                               VpdTable_I[numPdGainsUsed][kk] =
+                                       interpolate_signed(
+                                                          channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR],
+                                                          (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]);
+                       }
+                       /* fill VpdTable_I for this pdGain */
+                       numPdGainsUsed++;
+               }
+               /* if this pdGain is used */
+       }
+
+       *pMinCalPower = Pmin_t2[0];
+       kk = 0; /* index for the final table */
+       for (ii = 0; ii < numPdGainsUsed; ii++) {
+               if (ii == (numPdGainsUsed - 1))
+                       pPdGainBoundaries[ii] = Pmax_t2[ii] +
+                               PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB;
+               else
+                       pPdGainBoundaries[ii] = (uint16_t)
+                               ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 );
+
+               /* Find starting index for this pdGain */
+               if (ii == 0)
+                       ss = 0; /* for the first pdGain, start from index 0 */
+               else
+                       ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) -
+                               pdGainOverlap_t2;
+               Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                *-ve ss indicates need to extrapolate data below for this pdGain
+                */
+               while (ss < 0) {
+                       tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step);
+                       pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal);
+                       ss++;
+               }
+
+               sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii];
+               tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii];
+               maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
+
+               while (ss < (int16_t)maxIndex)
+                       pPDADCValues[kk++] = VpdTable_I[ii][ss++];
+
+               Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] -
+                                      VpdTable_I[ii][sizeCurrVpdTable-2]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                * for last gain, pdGainBoundary == Pmax_t2, so will
+                * have to extrapolate
+                */
+               if (tgtIndex > maxIndex) {      /* need to extrapolate above */
+                       while(ss < (int16_t)tgtIndex) {
+                               tmpVal = (uint16_t)
+                                       (VpdTable_I[ii][sizeCurrVpdTable-1] +
+                                        (ss-maxIndex)*Vpd_step);
+                               pPDADCValues[kk++] = (tmpVal > 127) ?
+                                       127 : tmpVal;
+                               ss++;
+                       }
+               }                               /* extrapolated above */
+       }                                       /* for all pdGainUsed */
+
+       while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) {
+               pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1];
+               ii++;
+       }
+       while (kk < 128) {
+               pPDADCValues[kk] = pPDADCValues[kk-1];
+               kk++;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM, "<==%s\n", __func__);
+}
+
+
+/* Same as 2413 set power table */
+static HAL_BOOL
+ar2425SetPowerTable(struct ath_hal *ah,
+       int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t *rfXpdGain)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL;
+       uint16_t pdGainOverlap_t2;
+       int16_t minCalPower2413_t2;
+       uint16_t *pdadcValues = ahp->ah_pcdacTable;
+       uint16_t gainBoundaries[4];
+       uint32_t i, reg32, regoffset;
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s:chan 0x%x flag 0x%x\n",
+           __func__, chan->channel,chan->channelFlags);
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s:illegal mode\n", __func__);
+               return AH_FALSE;
+       }
+
+       pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5),
+                                         AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
+
+       ar2425getGainBoundariesAndPdadcsForPowers(ah, chan->channel,
+               pRawDataset, pdGainOverlap_t2,&minCalPower2413_t2,gainBoundaries,
+               rfXpdGain, pdadcValues);
+
+       OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                        (pRawDataset->pDataPerChannel[0].numPdGains - 1));
+
+       /*
+        * Note the pdadc table may not start at 0 dBm power, could be
+        * negative or greater than 0.  Need to offset the power
+        * values by the amount of minPower for griffin
+        */
+       if (minCalPower2413_t2 != 0)
+               ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2413_t2);
+       else
+               ahp->ah_txPowerIndexOffset = 0;
+
+       /* Finally, write the power values into the baseband power table */
+       regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */
+       for (i = 0; i < 32; i++) {
+               reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0)  |
+                       ((pdadcValues[4*i + 1] & 0xFF) << 8)  |
+                       ((pdadcValues[4*i + 2] & 0xFF) << 16) |
+                       ((pdadcValues[4*i + 3] & 0xFF) << 24) ;
+               OS_REG_WRITE(ah, regoffset, reg32);
+               regoffset += 4;
+       }
+
+       OS_REG_WRITE(ah, AR_PHY_TPCRG5,
+                    SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                    SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
+                    SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
+                    SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
+                    SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+
+       return AH_TRUE;
+}
+
+static int16_t
+ar2425GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data)
+{
+       uint32_t ii,jj;
+       uint16_t Pmin=0,numVpd;
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = data->pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       Pmin = data->pDataPerPDGain[jj].pwr_t4[0];
+                       return(Pmin);
+               }
+       }
+       return(Pmin);
+}
+
+static int16_t
+ar2425GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data)
+{
+       uint32_t ii;
+       uint16_t Pmax=0,numVpd;
+
+       for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               /* work forwards cuase lowest pdGain for highest power */
+               numVpd = data->pDataPerPDGain[ii].numVpd;
+               if (numVpd > 0) {
+                       Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1];
+                       return(Pmax);
+               }
+       }
+       return(Pmax);
+}
+
+static
+HAL_BOOL
+ar2425GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan,
+                                    int16_t *maxPow, int16_t *minPow)
+{
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL;
+       const RAW_DATA_PER_CHANNEL_2413 *data = AH_NULL;
+       uint16_t numChannels;
+       int totalD,totalF, totalMin,last, i;
+
+       *maxPow = 0;
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else
+               return(AH_FALSE);
+
+       numChannels = pRawDataset->numChannels;
+       data = pRawDataset->pDataPerChannel;
+
+       /* Make sure the channel is in the range of the TP values
+        *  (freq piers)
+        */
+       if (numChannels < 1)
+               return(AH_FALSE);
+
+       if ((chan->channel < data[0].channelValue) ||
+           (chan->channel > data[numChannels-1].channelValue)) {
+               if (chan->channel < data[0].channelValue) {
+                       *maxPow = ar2425GetMaxPower(ah, &data[0]);
+                       *minPow = ar2425GetMinPower(ah, &data[0]);
+                       return(AH_TRUE);
+               } else {
+                       *maxPow = ar2425GetMaxPower(ah, &data[numChannels - 1]);
+                       *minPow = ar2425GetMinPower(ah, &data[numChannels - 1]);
+                       return(AH_TRUE);
+               }
+       }
+
+       /* Linearly interpolate the power value now */
+       for (last=0,i=0; (i<numChannels) && (chan->channel > data[i].channelValue);
+            last = i++);
+       totalD = data[i].channelValue - data[last].channelValue;
+       if (totalD > 0) {
+               totalF = ar2425GetMaxPower(ah, &data[i]) - ar2425GetMaxPower(ah, &data[last]);
+               *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) +
+                                    ar2425GetMaxPower(ah, &data[last])*totalD)/totalD);
+               totalMin = ar2425GetMinPower(ah, &data[i]) - ar2425GetMinPower(ah, &data[last]);
+               *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) +
+                                    ar2425GetMinPower(ah, &data[last])*totalD)/totalD);
+               return(AH_TRUE);
+       } else {
+               if (chan->channel == data[i].channelValue) {
+                       *maxPow = ar2425GetMaxPower(ah, &data[i]);
+                       *minPow = ar2425GetMinPower(ah, &data[i]);
+                       return(AH_TRUE);
+               } else
+                       return(AH_FALSE);
+       }
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar2425RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for analog bank scratch buffers
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+static HAL_BOOL
+ar2425RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar2425State *priv;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar2425State));
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar2425RfDetach;
+       priv->base.writeRegs            = ar2425WriteRegs;
+       priv->base.getRfBank            = ar2425GetRfBank;
+       priv->base.setChannel           = ar2425SetChannel;
+       priv->base.setRfRegs            = ar2425SetRfRegs;
+       priv->base.setPowerTable        = ar2425SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar2425GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar5212GetNfAdjust;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+ar2425Probe(struct ath_hal *ah)
+{
+       return IS_2425(ah) || IS_2417(ah);
+}
+AH_RF(RF2425, ar2425Probe, ar2425RfAttach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5111.c   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,711 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5111.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ah_eeprom_v3.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#define AH_5212_5111
+#include "ar5212/ar5212.ini"
+
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+
+struct ar5111State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[PWR_TABLE_SIZE];
+
+       uint32_t        Bank0Data[N(ar5212Bank0_5111)];
+       uint32_t        Bank1Data[N(ar5212Bank1_5111)];
+       uint32_t        Bank2Data[N(ar5212Bank2_5111)];
+       uint32_t        Bank3Data[N(ar5212Bank3_5111)];
+       uint32_t        Bank6Data[N(ar5212Bank6_5111)];
+       uint32_t        Bank7Data[N(ar5212Bank7_5111)];
+};
+#define        AR5111(ah)      ((struct ar5111State *) AH5212(ah)->ah_rfHal)
+
+static uint16_t ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue,
+               const PCDACS_EEPROM *pSrcStruct);
+static HAL_BOOL ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue,
+               const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue);
+static void ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel,
+               const PCDACS_EEPROM *pSrcStruct,
+               uint16_t *pLowerPcdac, uint16_t *pUpperPcdac);
+
+extern void ar5212GetLowerUpperValues(uint16_t value,
+               const uint16_t *pList, uint16_t listSize,
+               uint16_t *pLowerValue, uint16_t *pUpperValue);
+extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+               uint32_t numBits, uint32_t firstBit, uint32_t column);
+
+static void
+ar5111WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int writes)
+{
+       HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5111, modesIndex, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212Common_5111, 1, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5111, freqIndex, writes);
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar5111SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+#define CI_2GHZ_INDEX_CORRECTION 19
+       uint32_t refClk, reg32, data2111;
+       int16_t chan5111, chanIEEE;
+
+       /*
+        * Structure to hold 11b tuning information for 5111/2111
+        * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12
+        */
+       typedef struct {
+               uint32_t        refClkSel;      /* reference clock, 1 for 16 MHz */
+               uint32_t        channelSelect;  /* P[7:4]S[3:0] bits */
+               uint16_t        channel5111;    /* 11a channel for 5111 */
+       } CHAN_INFO_2GHZ;
+
+       static const CHAN_INFO_2GHZ chan2GHzData[] = {
+               { 1, 0x46, 96  },       /* 2312 -19 */
+               { 1, 0x46, 97  },       /* 2317 -18 */
+               { 1, 0x46, 98  },       /* 2322 -17 */
+               { 1, 0x46, 99  },       /* 2327 -16 */
+               { 1, 0x46, 100 },       /* 2332 -15 */
+               { 1, 0x46, 101 },       /* 2337 -14 */
+               { 1, 0x46, 102 },       /* 2342 -13 */
+               { 1, 0x46, 103 },       /* 2347 -12 */
+               { 1, 0x46, 104 },       /* 2352 -11 */
+               { 1, 0x46, 105 },       /* 2357 -10 */
+               { 1, 0x46, 106 },       /* 2362  -9 */
+               { 1, 0x46, 107 },       /* 2367  -8 */
+               { 1, 0x46, 108 },       /* 2372  -7 */
+               /* index -6 to 0 are pad to make this a nolookup table */
+               { 1, 0x46, 116 },       /*       -6 */
+               { 1, 0x46, 116 },       /*       -5 */
+               { 1, 0x46, 116 },       /*       -4 */
+               { 1, 0x46, 116 },       /*       -3 */
+               { 1, 0x46, 116 },       /*       -2 */
+               { 1, 0x46, 116 },       /*       -1 */
+               { 1, 0x46, 116 },       /*        0 */
+               { 1, 0x46, 116 },       /* 2412   1 */
+               { 1, 0x46, 117 },       /* 2417   2 */
+               { 1, 0x46, 118 },       /* 2422   3 */
+               { 1, 0x46, 119 },       /* 2427   4 */
+               { 1, 0x46, 120 },       /* 2432   5 */
+               { 1, 0x46, 121 },       /* 2437   6 */
+               { 1, 0x46, 122 },       /* 2442   7 */
+               { 1, 0x46, 123 },       /* 2447   8 */
+               { 1, 0x46, 124 },       /* 2452   9 */
+               { 1, 0x46, 125 },       /* 2457  10 */
+               { 1, 0x46, 126 },       /* 2462  11 */
+               { 1, 0x46, 127 },       /* 2467  12 */
+               { 1, 0x46, 128 },       /* 2472  13 */
+               { 1, 0x44, 124 },       /* 2484  14 */
+               { 1, 0x46, 136 },       /* 2512  15 */
+               { 1, 0x46, 140 },       /* 2532  16 */
+               { 1, 0x46, 144 },       /* 2552  17 */
+               { 1, 0x46, 148 },       /* 2572  18 */
+               { 1, 0x46, 152 },       /* 2592  19 */
+               { 1, 0x46, 156 },       /* 2612  20 */
+               { 1, 0x46, 160 },       /* 2632  21 */
+               { 1, 0x46, 164 },       /* 2652  22 */
+               { 1, 0x46, 168 },       /* 2672  23 */
+               { 1, 0x46, 172 },       /* 2692  24 */
+               { 1, 0x46, 176 },       /* 2712  25 */
+               { 1, 0x46, 180 }        /* 2732  26 */
+       };
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags);
+       if (IS_CHAN_2GHZ(chan)) {
+               const CHAN_INFO_2GHZ* ci =
+                       &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION];
+               uint32_t txctl;
+
+               data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff)
+                               << 5)
+                        | (ci->refClkSel << 4);
+               chan5111 = ci->channel5111;
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (chan->channel == 2484) {
+                       /* Enable channel spreading for channel 14 */
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+       } else {
+               chan5111 = chanIEEE;    /* no conversion needed */
+               data2111 = 0;
+       }
+
+       /* Rest of the code is common for 5 GHz and 2.4 GHz. */
+       if (chan5111 >= 145 || (chan5111 & 0x1)) {
+               reg32  = ath_hal_reverseBits(chan5111 - 24, 8) & 0xff;
+               refClk = 1;
+       } else {
+               reg32  = ath_hal_reverseBits(((chan5111 - 24)/2), 8) & 0xff;
+               refClk = 0;
+       }
+
+       reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1;
+       OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff));
+       reg32 >>= 8;
+       OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff));
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+#undef CI_2GHZ_INDEX_CORRECTION
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar5111GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar5111State *priv = AR5111(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 0: return priv->Bank0Data;
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar5111SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI;
+       uint16_t tempOB, tempDB;
+       uint32_t ob2GHz, db2GHz, rfReg[N(ar5212Bank6_5111)];
+       int i, regWrites = 0;
+
+       /* Setup rf parameters */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+       case CHANNEL_T:
+               if (4000 < chan->channel && chan->channel < 5260) {
+                       tempOB = ee->ee_ob1;
+                       tempDB = ee->ee_db1;
+               } else if (5260 <= chan->channel && chan->channel < 5500) {
+                       tempOB = ee->ee_ob2;
+                       tempDB = ee->ee_db2;
+               } else if (5500 <= chan->channel && chan->channel < 5725) {
+                       tempOB = ee->ee_ob3;
+                       tempDB = ee->ee_db3;
+               } else if (chan->channel >= 5725) {
+                       tempOB = ee->ee_ob4;
+                       tempDB = ee->ee_db4;
+               } else {
+                       /* XXX when does this happen??? */
+                       tempOB = tempDB = 0;
+               }
+               ob2GHz = db2GHz = 0;
+
+               rfXpdGainFixed = ee->ee_xgain[headerInfo11A];
+               rfPloSel = ee->ee_xpd[headerInfo11A];
+               rfPwdXpd = !ee->ee_xpd[headerInfo11A];
+               gainI = ee->ee_gainI[headerInfo11A];
+               break;
+       case CHANNEL_B:
+               tempOB = ee->ee_obFor24;
+               tempDB = ee->ee_dbFor24;
+               ob2GHz = ee->ee_ob2GHz[0];
+               db2GHz = ee->ee_db2GHz[0];
+
+               rfXpdGainFixed = ee->ee_xgain[headerInfo11B];
+               rfPloSel = ee->ee_xpd[headerInfo11B];
+               rfPwdXpd = !ee->ee_xpd[headerInfo11B];
+               gainI = ee->ee_gainI[headerInfo11B];
+               break;
+       case CHANNEL_G:
+               tempOB = ee->ee_obFor24g;
+               tempDB = ee->ee_dbFor24g;
+               ob2GHz = ee->ee_ob2GHz[1];
+               db2GHz = ee->ee_db2GHz[1];
+
+               rfXpdGainFixed = ee->ee_xgain[headerInfo11G];
+               rfPloSel = ee->ee_xpd[headerInfo11G];
+               rfPwdXpd = !ee->ee_xpd[headerInfo11G];
+               gainI = ee->ee_gainI[headerInfo11G];
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       HALASSERT(1 <= tempOB && tempOB <= 5);
+       HALASSERT(1 <= tempDB && tempDB <= 5);
+
+       /* Bank 0 Write */
+       for (i = 0; i < N(ar5212Bank0_5111); i++)
+               rfReg[i] = ar5212Bank0_5111[i][modesIndex];
+       if (IS_CHAN_2GHZ(chan)) {
+               ar5212ModifyRfBuffer(rfReg, ob2GHz, 3, 119, 0);
+               ar5212ModifyRfBuffer(rfReg, db2GHz, 3, 122, 0);
+       }
+       HAL_INI_WRITE_BANK(ah, ar5212Bank0_5111, rfReg, regWrites);
+
+       /* Bank 1 Write */
+       HAL_INI_WRITE_ARRAY(ah, ar5212Bank1_5111, 1, regWrites);
+
+       /* Bank 2 Write */
+       HAL_INI_WRITE_ARRAY(ah, ar5212Bank2_5111, modesIndex, regWrites);
+
+       /* Bank 3 Write */
+       HAL_INI_WRITE_ARRAY(ah, ar5212Bank3_5111, modesIndex, regWrites);
+
+       /* Bank 6 Write */
+       for (i = 0; i < N(ar5212Bank6_5111); i++)
+               rfReg[i] = ar5212Bank6_5111[i][modesIndex];
+       if (IS_CHAN_A(chan)) {          /* NB: CHANNEL_A | CHANNEL_T */
+               ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd84, 1, 51, 3);
+               ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd90, 1, 45, 3);
+       }
+       ar5212ModifyRfBuffer(rfReg, rfPwdXpd, 1, 95, 0);
+       ar5212ModifyRfBuffer(rfReg, rfXpdGainFixed, 4, 96, 0);
+       /* Set 5212 OB & DB */
+       ar5212ModifyRfBuffer(rfReg, tempOB, 3, 104, 0);
+       ar5212ModifyRfBuffer(rfReg, tempDB, 3, 107, 0);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank6_5111, rfReg, regWrites);
+
+       /* Bank 7 Write */
+       for (i = 0; i < N(ar5212Bank7_5111); i++)
+               rfReg[i] = ar5212Bank7_5111[i][modesIndex];
+       ar5212ModifyRfBuffer(rfReg, gainI, 6, 29, 0);
+       ar5212ModifyRfBuffer(rfReg, rfPloSel, 1, 4, 0);
+
+       if (IS_CHAN_QUARTER_RATE(chan) || IS_CHAN_HALF_RATE(chan)) {
+               uint32_t        rfWaitI, rfWaitS, rfMaxTime;
+
+               rfWaitS = 0x1f;
+               rfWaitI = (IS_CHAN_HALF_RATE(chan)) ?  0x10 : 0x1f;
+               rfMaxTime = 3;
+               ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0);
+               ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0);
+               ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0);
+
+       }
+
+       HAL_INI_WRITE_BANK(ah, ar5212Bank7_5111, rfReg, regWrites);
+
+       /* Now that we have reprogrammed rfgain value, clear the flag. */
+       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+
+       return AH_TRUE;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+static uint16_t
+interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+       uint16_t targetLeft, uint16_t targetRight)
+{
+       uint16_t rv;
+       int16_t lRatio;
+
+       /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */
+       if ((targetLeft * targetRight) == 0)
+               return 0;
+
+       if (srcRight != srcLeft) {
+               /*
+                * Note the ratio always need to be scaled,
+                * since it will be a fraction.
+                */
+               lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft);
+               if (lRatio < 0) {
+                   /* Return as Left target if value would be negative */
+                   rv = targetLeft;
+               } else if (lRatio > EEP_SCALE) {
+                   /* Return as Right target if Ratio is greater than 100% (SCALE) */
+                   rv = targetRight;
+               } else {
+                       rv = (lRatio * targetRight + (EEP_SCALE - lRatio) *
+                                       targetLeft) / EEP_SCALE;
+               }
+       } else {
+               rv = targetLeft;
+       }
+       return rv;
+}
+
+/*
+ * Read the transmit power levels from the structures taken from EEPROM
+ * Interpolate read transmit power values for this channel
+ * Organize the transmit power values into a table for writing into the hardware
+ */
+static HAL_BOOL
+ar5111SetPowerTable(struct ath_hal *ah,
+       int16_t *pMinPower, int16_t *pMaxPower, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t *rfXpdGain)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       FULL_PCDAC_STRUCT pcdacStruct;
+       int i, j;
+
+       uint16_t     *pPcdacValues;
+       int16_t      *pScaledUpDbm;
+       int16_t      minScaledPwr;
+       int16_t      maxScaledPwr;
+       int16_t      pwr;
+       uint16_t     pcdacMin = 0;
+       uint16_t     pcdacMax = PCDAC_STOP;
+       uint16_t     pcdacTableIndex;
+       uint16_t     scaledPcdac;
+       PCDACS_EEPROM *pSrcStruct;
+       PCDACS_EEPROM eepromPcdacs;
+
+       /* setup the pcdac struct to point to the correct info, based on mode */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+       case CHANNEL_T:
+               eepromPcdacs.numChannels     = ee->ee_numChannels11a;
+               eepromPcdacs.pChannelList    = ee->ee_channels11a;
+               eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a;
+               break;
+       case CHANNEL_B:
+               eepromPcdacs.numChannels     = ee->ee_numChannels2_4;
+               eepromPcdacs.pChannelList    = ee->ee_channels11b;
+               eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               eepromPcdacs.numChannels     = ee->ee_numChannels2_4;
+               eepromPcdacs.pChannelList    = ee->ee_channels11g;
+               eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       pSrcStruct = &eepromPcdacs;
+
+       OS_MEMZERO(&pcdacStruct, sizeof(pcdacStruct));
+       pPcdacValues = pcdacStruct.PcdacValues;
+       pScaledUpDbm = pcdacStruct.PwrValues;
+
+       /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */
+       for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++)
+               pPcdacValues[j] = i;
+
+       pcdacStruct.numPcdacValues = j;
+       pcdacStruct.pcdacMin = PCDAC_START;
+       pcdacStruct.pcdacMax = PCDAC_STOP;
+
+       /* Fill out the power values for this channel */
+       for (j = 0; j < pcdacStruct.numPcdacValues; j++ )
+               pScaledUpDbm[j] = ar5212GetScaledPower(chan->channel,
+                       pPcdacValues[j], pSrcStruct);
+
+       /* Now scale the pcdac values to fit in the 64 entry power table */
+       minScaledPwr = pScaledUpDbm[0];
+       maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1];
+
+       /* find minimum and make monotonic */
+       for (j = 0; j < pcdacStruct.numPcdacValues; j++) {
+               if (minScaledPwr >= pScaledUpDbm[j]) {
+                       minScaledPwr = pScaledUpDbm[j];
+                       pcdacMin = j;
+               }
+               /*
+                * Make the full_hsh monotonically increasing otherwise
+                * interpolation algorithm will get fooled gotta start
+                * working from the top, hence i = 63 - j.
+                */
+               i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j);
+               if (i == 0)
+                       break;
+               if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) {
+                       /*
+                        * It could be a glitch, so make the power for
+                        * this pcdac the same as the power from the
+                        * next highest pcdac.
+                        */
+                       pScaledUpDbm[i - 1] = pScaledUpDbm[i];
+               }
+       }
+
+       for (j = 0; j < pcdacStruct.numPcdacValues; j++)
+               if (maxScaledPwr < pScaledUpDbm[j]) {
+                       maxScaledPwr = pScaledUpDbm[j];
+                       pcdacMax = j;
+               }
+
+       /* Find the first power level with a pcdac */
+       pwr = (uint16_t)(PWR_STEP *
+               ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN);
+
+       /* Write all the first pcdac entries based off the pcdacMin */
+       pcdacTableIndex = 0;
+       for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++) {
+               HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE);
+               ahp->ah_pcdacTable[pcdacTableIndex++] = pcdacMin;
+       }
+
+       i = 0;
+       while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] &&
+           pcdacTableIndex < PWR_TABLE_SIZE) {
+               pwr += PWR_STEP;
+               /* stop if dbM > max_power_possible */
+               while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] &&
+                      (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0)
+                       i++;
+               /* scale by 2 and add 1 to enable round up or down as needed */
+               scaledPcdac = (uint16_t)(interpolate(pwr,
+                       pScaledUpDbm[i], pScaledUpDbm[i + 1],
+                       (uint16_t)(pPcdacValues[i] * 2),
+                       (uint16_t)(pPcdacValues[i + 1] * 2)) + 1);
+
+               HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE);
+               ahp->ah_pcdacTable[pcdacTableIndex] = scaledPcdac / 2;
+               if (ahp->ah_pcdacTable[pcdacTableIndex] > pcdacMax)
+                       ahp->ah_pcdacTable[pcdacTableIndex] = pcdacMax;
+               pcdacTableIndex++;
+       }
+
+       /* Write all the last pcdac entries based off the last valid pcdac */
+       while (pcdacTableIndex < PWR_TABLE_SIZE) {
+               ahp->ah_pcdacTable[pcdacTableIndex] =
+                       ahp->ah_pcdacTable[pcdacTableIndex - 1];
+               pcdacTableIndex++;
+       }
+
+       /* No power table adjustment for 5111 */
+       ahp->ah_txPowerIndexOffset = 0;
+
+       return AH_TRUE;
+}
+
+/*
+ * Get or interpolate the pcdac value from the calibrated data.
+ */
+static uint16_t
+ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue,
+       const PCDACS_EEPROM *pSrcStruct)
+{
+       uint16_t powerValue;
+       uint16_t lFreq, rFreq;          /* left and right frequency values */
+       uint16_t llPcdac, ulPcdac;      /* lower and upper left pcdac values */
+       uint16_t lrPcdac, urPcdac;      /* lower and upper right pcdac values */
+       uint16_t lPwr = 0, uPwr = 0;            /* lower and upper temp pwr values */
+       uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */
+
+       if (ar5212FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue)) {
+               /* value was copied from srcStruct */
+               return powerValue;
+       }
+
+       ar5212GetLowerUpperValues(channel,
+               pSrcStruct->pChannelList, pSrcStruct->numChannels,
+               &lFreq, &rFreq);
+       ar5212GetLowerUpperPcdacs(pcdacValue,
+               lFreq, pSrcStruct, &llPcdac, &ulPcdac);
+       ar5212GetLowerUpperPcdacs(pcdacValue,
+               rFreq, pSrcStruct, &lrPcdac, &urPcdac);
+
+       /* get the power index for the pcdac value */
+       ar5212FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr);
+       ar5212FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr);
+       lScaledPwr = interpolate(pcdacValue, llPcdac, ulPcdac, lPwr, uPwr);
+
+       ar5212FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr);
+       ar5212FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr);
+       rScaledPwr = interpolate(pcdacValue, lrPcdac, urPcdac, lPwr, uPwr);
+
+       return interpolate(channel, lFreq, rFreq, lScaledPwr, rScaledPwr);
+}
+
+/*
+ * Find the value from the calibrated source data struct
+ */
+static HAL_BOOL
+ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue,
+       const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue)
+{
+       const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel;
+       int i;
+
+       for (i = 0; i < pSrcStruct->numChannels; i++ ) {
+               if (pChannelData->channelValue == channel) {
+                       const uint16_t* pPcdac = pChannelData->PcdacValues;
+                       int j;
+
+                       for (j = 0; j < pChannelData->numPcdacValues; j++ ) {
+                               if (*pPcdac == pcdacValue) {
+                                       *powerValue = pChannelData->PwrValues[j];
+                                       return AH_TRUE;
+                               }
+                               pPcdac++;
+                       }
+               }
+               pChannelData++;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Get the upper and lower pcdac given the channel and the pcdac
+ * used in the search
+ */
+static void
+ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel,
+       const PCDACS_EEPROM *pSrcStruct,
+       uint16_t *pLowerPcdac, uint16_t *pUpperPcdac)
+{
+       const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel;
+       int i;
+
+       /* Find the channel information */
+       for (i = 0; i < pSrcStruct->numChannels; i++) {
+               if (pChannelData->channelValue == channel)
+                       break;
+               pChannelData++;
+       }
+       ar5212GetLowerUpperValues(pcdac, pChannelData->PcdacValues,
+                     pChannelData->numPcdacValues,
+                     pLowerPcdac, pUpperPcdac);
+}
+
+static HAL_BOOL
+ar5111GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan,
+       int16_t *maxPow, int16_t *minPow)
+{
+       /* XXX - Get 5111 power limits! */
+       /* NB: caller will cope */
+       return AH_FALSE;
+}
+
+/*
+ * Adjust NF based on statistical values for 5GHz frequencies.
+ */
+static int16_t
+ar5111GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
+{
+       static const struct {
+               uint16_t freqLow;
+               int16_t   adjust;
+       } adjust5111[] = {
+               { 5790, 6 },    /* NB: ordered high -> low */
+               { 5730, 4 },
+               { 5690, 3 },
+               { 5660, 2 },
+               { 5610, 1 },
+               { 5530, 0 },
+               { 5450, 0 },
+               { 5379, 1 },
+               { 5209, 3 },
+               { 3000, 5 },
+               {    0, 0 },
+       };
+       int i;
+
+       for (i = 0; c->channel <= adjust5111[i].freqLow; i++)
+               ;
+       return adjust5111[i].adjust;
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar5111RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for analog bank scratch buffers
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+static HAL_BOOL
+ar5111RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5111State *priv;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar5111State));
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar5111RfDetach;
+       priv->base.writeRegs            = ar5111WriteRegs;
+       priv->base.getRfBank            = ar5111GetRfBank;
+       priv->base.setChannel           = ar5111SetChannel;
+       priv->base.setRfRegs            = ar5111SetRfRegs;
+       priv->base.setPowerTable        = ar5111SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar5111GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar5111GetNfAdjust;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+ar5111Probe(struct ath_hal *ah)
+{
+       return IS_RAD5111(ah);
+}
+AH_RF(RF5111, ar5111Probe, ar5111RfAttach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5112.c   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5112.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ah_eeprom_v3.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#define AH_5212_5112
+#include "ar5212/ar5212.ini"
+
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+
+struct ar5112State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[PWR_TABLE_SIZE];
+
+       uint32_t        Bank1Data[N(ar5212Bank1_5112)];
+       uint32_t        Bank2Data[N(ar5212Bank2_5112)];
+       uint32_t        Bank3Data[N(ar5212Bank3_5112)];
+       uint32_t        Bank6Data[N(ar5212Bank6_5112)];
+       uint32_t        Bank7Data[N(ar5212Bank7_5112)];
+};
+#define        AR5112(ah)      ((struct ar5112State *) AH5212(ah)->ah_rfHal)
+
+static void ar5212GetLowerUpperIndex(uint16_t v,
+               uint16_t *lp, uint16_t listSize,
+               uint32_t *vlo, uint32_t *vhi);
+static HAL_BOOL getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs,
+               int16_t *power, int16_t maxPower, int16_t *retVals);
+static int16_t getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4,
+               uint16_t retVals[]);
+static int16_t getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4,
+               int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid);
+static int16_t interpolate_signed(uint16_t target,
+               uint16_t srcLeft, uint16_t srcRight,
+               int16_t targetLeft, int16_t targetRight);
+
+extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+               uint32_t numBits, uint32_t firstBit, uint32_t column);
+
+static void
+ar5112WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int writes)
+{
+       HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5112, modesIndex, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212Common_5112, 1, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5112, freqIndex, writes);
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar5112SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t channelSel  = 0;
+       uint32_t bModeSynth  = 0;
+       uint32_t aModeRefSel = 0;
+       uint32_t reg32       = 0;
+       uint16_t freq;
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       if (chan->channel < 4800) {
+               uint32_t txctl;
+
+               if (((chan->channel - 2192) % 5) == 0) {
+                       channelSel = ((chan->channel - 672) * 2 - 3040)/10;
+                       bModeSynth = 0;
+               } else if (((chan->channel - 2224) % 5) == 0) {
+                       channelSel = ((chan->channel - 704) * 2 - 3040) / 10;
+                       bModeSynth = 1;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid channel %u MHz\n",
+                           __func__, chan->channel);
+                       return AH_FALSE;
+               }
+
+               channelSel = (channelSel << 2) & 0xff;
+               channelSel = ath_hal_reverseBits(channelSel, 8);
+
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (chan->channel == 2484) {
+                       /* Enable channel spreading for channel 14 */
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+       } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) {
+               freq = chan->channel - 2; /* Align to even 5MHz raster */
+               channelSel = ath_hal_reverseBits(
+                       (uint32_t)(((freq - 4800)*10)/25 + 1), 8);
+               aModeRefSel = ath_hal_reverseBits(0, 2);
+       } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 20 << 2), 8);
+               aModeRefSel = ath_hal_reverseBits(3, 2);
+       } else if ((chan->channel % 10) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 10 << 1), 8);
+               aModeRefSel = ath_hal_reverseBits(2, 2);
+       } else if ((chan->channel % 5) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       (chan->channel - 4800) / 5, 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
+                   __func__, chan->channel);
+               return AH_FALSE;
+       }
+
+       reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) |
+                       (1 << 12) | 0x1;
+       OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff);
+
+       reg32 >>= 8;
+       OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f);
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar5112GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar5112State *priv = AR5112(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar5112SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+#define        RF_BANK_SETUP(_priv, _ix, _col) do {                                \
+       int i;                                                              \
+       for (i = 0; i < N(ar5212Bank##_ix##_5112); i++)                     \
+               (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5112[i][_col];\
+} while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t rfXpdSel, gainI;
+       uint16_t ob5GHz = 0, db5GHz = 0;
+       uint16_t ob2GHz = 0, db2GHz = 0;
+       struct ar5112State *priv = AR5112(ah);
+       GAIN_VALUES *gv = &ahp->ah_gainValues;
+       int regWrites = 0;
+
+       HALASSERT(priv);
+
+       /* Setup rf parameters */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+       case CHANNEL_T:
+               if (chan->channel > 4000 && chan->channel < 5260) {
+                       ob5GHz = ee->ee_ob1;
+                       db5GHz = ee->ee_db1;
+               } else if (chan->channel >= 5260 && chan->channel < 5500) {
+                       ob5GHz = ee->ee_ob2;
+                       db5GHz = ee->ee_db2;
+               } else if (chan->channel >= 5500 && chan->channel < 5725) {
+                       ob5GHz = ee->ee_ob3;
+                       db5GHz = ee->ee_db3;
+               } else if (chan->channel >= 5725) {
+                       ob5GHz = ee->ee_ob4;
+                       db5GHz = ee->ee_db4;
+               } else {
+                       /* XXX else */
+               }
+               rfXpdSel = ee->ee_xpd[headerInfo11A];
+               gainI = ee->ee_gainI[headerInfo11A];
+               break;
+       case CHANNEL_B:
+               ob2GHz = ee->ee_ob2GHz[0];
+               db2GHz = ee->ee_db2GHz[0];
+               rfXpdSel = ee->ee_xpd[headerInfo11B];
+               gainI = ee->ee_gainI[headerInfo11B];
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               ob2GHz = ee->ee_ob2GHz[1];
+               db2GHz = ee->ee_ob2GHz[1];
+               rfXpdSel = ee->ee_xpd[headerInfo11G];
+               gainI = ee->ee_gainI[headerInfo11G];
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /* Setup Bank 1 Write */
+       RF_BANK_SETUP(priv, 1, 1);
+
+       /* Setup Bank 2 Write */
+       RF_BANK_SETUP(priv, 2, modesIndex);
+
+       /* Setup Bank 3 Write */
+       RF_BANK_SETUP(priv, 3, modesIndex);
+
+       /* Setup Bank 6 Write */
+       RF_BANK_SETUP(priv, 6, modesIndex);
+
+       ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdSel,     1, 302, 0);
+
+       ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdGain[0], 2, 270, 0);
+       ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdGain[1], 2, 257, 0);
+
+       if (IS_CHAN_OFDM(chan)) {
+               ar5212ModifyRfBuffer(priv->Bank6Data,
+                       gv->currStep->paramVal[GP_PWD_138], 1, 168, 3);
+               ar5212ModifyRfBuffer(priv->Bank6Data,
+                       gv->currStep->paramVal[GP_PWD_137], 1, 169, 3);
+               ar5212ModifyRfBuffer(priv->Bank6Data,
+                       gv->currStep->paramVal[GP_PWD_136], 1, 170, 3);
+               ar5212ModifyRfBuffer(priv->Bank6Data,
+                       gv->currStep->paramVal[GP_PWD_132], 1, 174, 3);
+               ar5212ModifyRfBuffer(priv->Bank6Data,
+                       gv->currStep->paramVal[GP_PWD_131], 1, 175, 3);
+               ar5212ModifyRfBuffer(priv->Bank6Data,
+                       gv->currStep->paramVal[GP_PWD_130], 1, 176, 3);
+       }
+
+       /* Only the 5 or 2 GHz OB/DB need to be set for a mode */
+       if (IS_CHAN_2GHZ(chan)) {
+               ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 287, 0);
+               ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 290, 0);
+       } else {
+               ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 279, 0);
+               ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 282, 0);
+       }
+
+       /* Lower synth voltage for X112 Rev 2.0 only */
+       if (IS_RADX112_REV2(ah)) {
+               /* Non-Reversed analyg registers - so values are pre-reversed */
+               ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 90, 2);
+               ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 92, 2);
+               ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 94, 2);
+               ar5212ModifyRfBuffer(priv->Bank6Data, 2, 1, 254, 2);
+       }
+
+    /* Decrease Power Consumption for 5312/5213 and up */
+    if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
+        ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 281, 1);
+        ar5212ModifyRfBuffer(priv->Bank6Data, 1, 2, 1, 3);
+        ar5212ModifyRfBuffer(priv->Bank6Data, 1, 2, 3, 3);
+        ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 139, 3);
+        ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 140, 3);
+    }
+
+       /* Setup Bank 7 Setup */
+       RF_BANK_SETUP(priv, 7, modesIndex);
+       if (IS_CHAN_OFDM(chan))
+               ar5212ModifyRfBuffer(priv->Bank7Data,
+                       gv->currStep->paramVal[GP_MIXGAIN_OVR], 2, 37, 0);
+
+       ar5212ModifyRfBuffer(priv->Bank7Data, gainI, 6, 14, 0);
+
+       /* Adjust params for Derby TX power control */
+       if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) {
+               uint32_t        rfDelay, rfPeriod;
+
+               rfDelay = 0xf;
+               rfPeriod = (IS_CHAN_HALF_RATE(chan)) ?  0x8 : 0xf;
+               ar5212ModifyRfBuffer(priv->Bank7Data, rfDelay, 4, 58, 0);
+               ar5212ModifyRfBuffer(priv->Bank7Data, rfPeriod, 4, 70, 0);
+       }
+
+#ifdef notyet
+       /* Analog registers are setup - EAR can modify */
+       if (ar5212IsEarEngaged(pDev, chan))
+               uint32_t modifier;
+               ar5212EarModify(pDev, EAR_LC_RF_WRITE, chan, &modifier);
+#endif
+       /* Write Analog registers */
+       HAL_INI_WRITE_BANK(ah, ar5212Bank1_5112, priv->Bank1Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank2_5112, priv->Bank2Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank3_5112, priv->Bank3Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank6_5112, priv->Bank6Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank7_5112, priv->Bank7Data, regWrites);
+
+       /* Now that we have reprogrammed rfgain value, clear the flag. */
+       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+       return AH_TRUE;
+#undef RF_BANK_SETUP
+}
+
+/*
+ * Read the transmit power levels from the structures taken from EEPROM
+ * Interpolate read transmit power values for this channel
+ * Organize the transmit power values into a table for writing into the hardware
+ */
+static HAL_BOOL
+ar5112SetPowerTable(struct ath_hal *ah,
+       int16_t *pPowerMin, int16_t *pPowerMax, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t *rfXpdGain)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint32_t numXpdGain = IS_RADX112_REV2(ah) ? 2 : 1;
+       uint32_t    xpdGainMask = 0;
+       int16_t     powerMid, *pPowerMid = &powerMid;
+
+       const EXPN_DATA_PER_CHANNEL_5112 *pRawCh;
+       const EEPROM_POWER_EXPN_5112     *pPowerExpn = AH_NULL;
+
+       uint32_t    ii, jj, kk;
+       int16_t     minPwr_t4, maxPwr_t4, Pmin, Pmid;
+
+       uint32_t    chan_idx_L = 0, chan_idx_R = 0;
+       uint16_t    chan_L, chan_R;
+
+       int16_t     pwr_table0[64];
+       int16_t     pwr_table1[64];
+       uint16_t    pcdacs[10];
+       int16_t     powers[10];
+       uint16_t    numPcd;
+       int16_t     powTableLXPD[2][64];
+       int16_t     powTableHXPD[2][64];
+       int16_t     tmpPowerTable[64];
+       uint16_t    xgainList[2];
+       uint16_t    xpdMask;
+
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+       case CHANNEL_T:
+               pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11A];
+               xpdGainMask = ee->ee_xgain[headerInfo11A];
+               break;
+       case CHANNEL_B:
+               pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11B];
+               xpdGainMask = ee->ee_xgain[headerInfo11B];
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11G];
+               xpdGainMask = ee->ee_xgain[headerInfo11G];
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown channel flags 0x%x\n",
+                   __func__, chan->channelFlags & CHANNEL_ALL);
+               return AH_FALSE;
+       }
+
+       if ((xpdGainMask & pPowerExpn->xpdMask) < 1) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: desired xpdGainMask 0x%x not supported by "
+                   "calibrated xpdMask 0x%x\n", __func__,
+                   xpdGainMask, pPowerExpn->xpdMask);
+               return AH_FALSE;
+       }
+
+       maxPwr_t4 = (int16_t)(2*(*pPowerMax));  /* pwr_t2 -> pwr_t4 */
+       minPwr_t4 = (int16_t)(2*(*pPowerMin));  /* pwr_t2 -> pwr_t4 */
+
+       xgainList[0] = 0xDEAD;
+       xgainList[1] = 0xDEAD;
+
+       kk = 0;
+       xpdMask = pPowerExpn->xpdMask;
+       for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) {
+               if (((xpdMask >> jj) & 1) > 0) {
+                       if (kk > 1) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "A maximum of 2 xpdGains supported"
+                                   "in pExpnPower data\n");
+                               return AH_FALSE;
+                       }
+                       xgainList[kk++] = (uint16_t)jj;
+               }
+       }
+
+       ar5212GetLowerUpperIndex(chan->channel, &pPowerExpn->pChannels[0],
+               pPowerExpn->numChannels, &chan_idx_L, &chan_idx_R);
+
+       kk = 0;
+       for (ii = chan_idx_L; ii <= chan_idx_R; ii++) {
+               pRawCh = &(pPowerExpn->pDataPerChannel[ii]);
+               if (xgainList[1] == 0xDEAD) {
+                       jj = xgainList[0];
+                       numPcd = pRawCh->pDataPerXPD[jj].numPcdacs;
+                       OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0],
+                               numPcd * sizeof(uint16_t));
+                       OS_MEMCPY(&powers[0], &pRawCh->pDataPerXPD[jj].pwr_t4[0],
+                               numPcd * sizeof(int16_t));
+                       if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0],
+                               pRawCh->maxPower_t4, &tmpPowerTable[0])) {
+                               return AH_FALSE;
+                       }
+                       OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0],
+                               64*sizeof(int16_t));
+               } else {
+                       jj = xgainList[0];
+                       numPcd = pRawCh->pDataPerXPD[jj].numPcdacs;
+                       OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0],
+                               numPcd*sizeof(uint16_t));
+                       OS_MEMCPY(&powers[0],
+                               &pRawCh->pDataPerXPD[jj].pwr_t4[0],
+                               numPcd*sizeof(int16_t));
+                       if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0],
+                               pRawCh->maxPower_t4, &tmpPowerTable[0])) {
+                               return AH_FALSE;
+                       }
+                       OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0],
+                               64 * sizeof(int16_t));
+
+                       jj = xgainList[1];
+                       numPcd = pRawCh->pDataPerXPD[jj].numPcdacs;
+                       OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0],
+                               numPcd * sizeof(uint16_t));
+                       OS_MEMCPY(&powers[0],
+                               &pRawCh->pDataPerXPD[jj].pwr_t4[0],
+                               numPcd * sizeof(int16_t));
+                       if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0],
+                               pRawCh->maxPower_t4, &tmpPowerTable[0])) {
+                               return AH_FALSE;
+                       }
+                       OS_MEMCPY(&powTableHXPD[kk][0], &tmpPowerTable[0],
+                               64 * sizeof(int16_t));
+               }
+               kk++;
+       }
+
+       chan_L = pPowerExpn->pChannels[chan_idx_L];
+       chan_R = pPowerExpn->pChannels[chan_idx_R];
+       kk = chan_idx_R - chan_idx_L;
+
+       if (xgainList[1] == 0xDEAD) {
+               for (jj = 0; jj < 64; jj++) {
+                       pwr_table0[jj] = interpolate_signed(
+                               chan->channel, chan_L, chan_R,
+                               powTableLXPD[0][jj], powTableLXPD[kk][jj]);
+               }
+               Pmin = getPminAndPcdacTableFromPowerTable(&pwr_table0[0],
+                               ahp->ah_pcdacTable);
+               *pPowerMin = (int16_t) (Pmin / 2);
+               *pPowerMid = (int16_t) (pwr_table0[63] / 2);
+               *pPowerMax = (int16_t) (pwr_table0[63] / 2);
+               rfXpdGain[0] = xgainList[0];
+               rfXpdGain[1] = rfXpdGain[0];
+       } else {
+               for (jj = 0; jj < 64; jj++) {
+                       pwr_table0[jj] = interpolate_signed(
+                               chan->channel, chan_L, chan_R,
+                               powTableLXPD[0][jj], powTableLXPD[kk][jj]);
+                       pwr_table1[jj] = interpolate_signed(
+                               chan->channel, chan_L, chan_R,
+                               powTableHXPD[0][jj], powTableHXPD[kk][jj]);
+               }
+               if (numXpdGain == 2) {
+                       Pmin = getPminAndPcdacTableFromTwoPowerTables(
+                               &pwr_table0[0], &pwr_table1[0],
+                               ahp->ah_pcdacTable, &Pmid);
+                       *pPowerMin = (int16_t) (Pmin / 2);
+                       *pPowerMid = (int16_t) (Pmid / 2);
+                       *pPowerMax = (int16_t) (pwr_table0[63] / 2);
+                       rfXpdGain[0] = xgainList[0];
+                       rfXpdGain[1] = xgainList[1];
+               } else if (minPwr_t4 <= pwr_table1[63] &&
+                          maxPwr_t4 <= pwr_table1[63]) {
+                       Pmin = getPminAndPcdacTableFromPowerTable(
+                               &pwr_table1[0], ahp->ah_pcdacTable);
+                       rfXpdGain[0] = xgainList[1];
+                       rfXpdGain[1] = rfXpdGain[0];
+                       *pPowerMin = (int16_t) (Pmin / 2);
+                       *pPowerMid = (int16_t) (pwr_table1[63] / 2);
+                       *pPowerMax = (int16_t) (pwr_table1[63] / 2);
+               } else {
+                       Pmin = getPminAndPcdacTableFromPowerTable(
+                               &pwr_table0[0], ahp->ah_pcdacTable);
+                       rfXpdGain[0] = xgainList[0];
+                       rfXpdGain[1] = rfXpdGain[0];
+                       *pPowerMin = (int16_t) (Pmin/2);
+                       *pPowerMid = (int16_t) (pwr_table0[63] / 2);
+                       *pPowerMax = (int16_t) (pwr_table0[63] / 2);
+               }
+       }
+
+       /*
+        * Move 5112 rates to match power tables where the max
+        * power table entry corresponds with maxPower.
+        */
+       HALASSERT(*pPowerMax <= PCDAC_STOP);
+       ahp->ah_txPowerIndexOffset = PCDAC_STOP - *pPowerMax;
+
+       return AH_TRUE;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+static int16_t
+interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+       int16_t targetLeft, int16_t targetRight)
+{
+       int16_t rv;
+
+       if (srcRight != srcLeft) {
+               rv = ((target - srcLeft)*targetRight +
+                     (srcRight - target)*targetLeft) / (srcRight - srcLeft);
+       } else {
+               rv = targetLeft;
+       }
+       return rv;
+}
+
+/*
+ * Return indices surrounding the value in sorted integer lists.
+ *
+ * NB: the input list is assumed to be sorted in ascending order
+ */
+static void
+ar5212GetLowerUpperIndex(uint16_t v, uint16_t *lp, uint16_t listSize,
+                          uint32_t *vlo, uint32_t *vhi)
+{
+       uint32_t target = v;
+       uint16_t *ep = lp+listSize;
+       uint16_t *tp;
+
+       /*
+        * Check first and last elements for out-of-bounds conditions.
+        */
+       if (target < lp[0]) {
+               *vlo = *vhi = 0;
+               return;
+       }
+       if (target >= ep[-1]) {
+               *vlo = *vhi = listSize - 1;
+               return;
+       }
+
+       /* look for value being near or between 2 values in list */
+       for (tp = lp; tp < ep; tp++) {
+               /*
+                * If value is close to the current value of the list
+                * then target is not between values, it is one of the values
+                */
+               if (*tp == target) {
+                       *vlo = *vhi = tp - lp;
+                       return;
+               }
+               /*
+                * Look for value being between current value and next value
+                * if so return these 2 values
+                */
+               if (target < tp[1]) {
+                       *vlo = tp - lp;
+                       *vhi = *vlo + 1;
+                       return;
+               }
+       }
+}
+
+static HAL_BOOL
+getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, int16_t *power, int16_t maxPower, int16_t *retVals)
+{
+       uint16_t    ii;
+       uint16_t    idxL = 0;
+       uint16_t    idxR = 1;
+
+       if (numPcdacs < 2) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                    "%s: at least 2 pcdac values needed [%d]\n",
+                    __func__, numPcdacs);
+               return AH_FALSE;
+       }
+       for (ii = 0; ii < 64; ii++) {
+               if (ii>pcdacs[idxR] && idxR < numPcdacs-1) {
+                       idxL++;
+                       idxR++;
+               }
+               retVals[ii] = interpolate_signed(ii,
+                       pcdacs[idxL], pcdacs[idxR], power[idxL], power[idxR]);
+               if (retVals[ii] >= maxPower) {
+                       while (ii < 64)
+                               retVals[ii++] = maxPower;
+               }
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Takes a single calibration curve and creates a power table.
+ * Adjusts the new power table so the max power is relative
+ * to the maximum index in the power table.
+ *
+ * WARNING: rates must be adjusted for this relative power table
+ */
+static int16_t
+getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, uint16_t retVals[])
+{
+    int16_t ii, jj, jjMax;
+    int16_t pMin, currPower, pMax;
+
+    /* If the spread is > 31.5dB, keep the upper 31.5dB range */
+    if ((pwrTableT4[63] - pwrTableT4[0]) > 126) {
+        pMin = pwrTableT4[63] - 126;
+    } else {
+        pMin = pwrTableT4[0];
+    }
+
+    pMax = pwrTableT4[63];
+    jjMax = 63;
+
+    /* Search for highest pcdac 0.25dB below maxPower */
+    while ((pwrTableT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)) {
+        jjMax--;
+    }
+
+    jj = jjMax;
+    currPower = pMax;
+    for (ii = 63; ii >= 0; ii--) {
+        while ((jj < 64) && (jj > 0) && (pwrTableT4[jj] >= currPower)) {
+            jj--;
+        }
+        if (jj == 0) {
+            while (ii >= 0) {
+                retVals[ii] = retVals[ii + 1];
+                ii--;
+            }
+            break;
+        }
+        retVals[ii] = jj;
+        currPower -= 2;  // corresponds to a 0.5dB step
+    }
+    return pMin;
+}
+
+/*
+ * Combines the XPD curves from two calibration sets into a single
+ * power table and adjusts the power table so the max power is relative
+ * to the maximum index in the power table
+ *
+ * WARNING: rates must be adjusted for this relative power table
+ */
+static int16_t
+getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4,
+       int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid)
+{
+    int16_t     ii, jj, jjMax;
+    int16_t     pMin, pMax, currPower;
+    int16_t     *pwrTableT4;
+    uint16_t    msbFlag = 0x40;  // turns on the 7th bit of the pcdac
+
+    /* If the spread is > 31.5dB, keep the upper 31.5dB range */
+    if ((pwrTableLXpdT4[63] - pwrTableHXpdT4[0]) > 126) {
+        pMin = pwrTableLXpdT4[63] - 126;
+    } else {
+        pMin = pwrTableHXpdT4[0];
+    }
+
+    pMax = pwrTableLXpdT4[63];
+    jjMax = 63;
+    /* Search for highest pcdac 0.25dB below maxPower */
+    while ((pwrTableLXpdT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)){
+        jjMax--;
+    }
+
+    *pMid = pwrTableHXpdT4[63];
+    jj = jjMax;
+    ii = 63;
+    currPower = pMax;
+    pwrTableT4 = &(pwrTableLXpdT4[0]);
+    while (ii >= 0) {
+        if ((currPower <= *pMid) || ( (jj == 0) && (msbFlag == 0x40))){
+            msbFlag = 0x00;
+            pwrTableT4 = &(pwrTableHXpdT4[0]);
+            jj = 63;
+        }
+        while ((jj > 0) && (pwrTableT4[jj] >= currPower)) {
+            jj--;
+        }
+        if ((jj == 0) && (msbFlag == 0x00)) {
+            while (ii >= 0) {
+                retVals[ii] = retVals[ii+1];
+                ii--;
+            }
+            break;
+        }
+        retVals[ii] = jj | msbFlag;
+        currPower -= 2;  // corresponds to a 0.5dB step
+        ii--;
+    }
+    return pMin;
+}
+
+static int16_t
+ar5112GetMinPower(struct ath_hal *ah, const EXPN_DATA_PER_CHANNEL_5112 *data)
+{
+       int i, minIndex;
+       int16_t minGain,minPwr,minPcdac,retVal;
+
+       /* Assume NUM_POINTS_XPD0 > 0 */
+       minGain = data->pDataPerXPD[0].xpd_gain;
+       for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) {
+               if (data->pDataPerXPD[i].xpd_gain < minGain) {
+                       minIndex = i;
+                       minGain = data->pDataPerXPD[i].xpd_gain;
+               }
+       }
+       minPwr = data->pDataPerXPD[minIndex].pwr_t4[0];
+       minPcdac = data->pDataPerXPD[minIndex].pcdac[0];
+       for (i=1; i<NUM_POINTS_XPD0; i++) {
+               if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) {
+                       minPwr = data->pDataPerXPD[minIndex].pwr_t4[i];
+                       minPcdac = data->pDataPerXPD[minIndex].pcdac[i];
+               }
+       }
+       retVal = minPwr - (minPcdac*2);
+       return(retVal);
+}
+
+static HAL_BOOL
+ar5112GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan,
+       int16_t *maxPow, int16_t *minPow)
+{
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       int numChannels=0,i,last;
+       int totalD, totalF,totalMin;
+       const EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL;
+       const EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL;
+
+       *maxPow = 0;
+       if (IS_CHAN_A(chan)) {
+               powerArray = ee->ee_modePowerArray5112;
+               data = powerArray[headerInfo11A].pDataPerChannel;
+               numChannels = powerArray[headerInfo11A].numChannels;
+       } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) {
+               /* XXX - is this correct? Should we also use the same power for turbo G? */
+               powerArray = ee->ee_modePowerArray5112;
+               data = powerArray[headerInfo11G].pDataPerChannel;
+               numChannels = powerArray[headerInfo11G].numChannels;
+       } else if (IS_CHAN_B(chan)) {
+               powerArray = ee->ee_modePowerArray5112;
+               data = powerArray[headerInfo11B].pDataPerChannel;
+               numChannels = powerArray[headerInfo11B].numChannels;
+       } else {
+               return (AH_TRUE);
+       }
+       /* Make sure the channel is in the range of the TP values
+        *  (freq piers)
+        */
+       if (numChannels < 1)
+               return(AH_FALSE);
+
+       if ((chan->channel < data[0].channelValue) ||
+           (chan->channel > data[numChannels-1].channelValue)) {
+               if (chan->channel < data[0].channelValue) {
+                       *maxPow = data[0].maxPower_t4;
+                       *minPow = ar5112GetMinPower(ah, &data[0]);
+                       return(AH_TRUE);
+               } else {
+                       *maxPow = data[numChannels - 1].maxPower_t4;
+                       *minPow = ar5112GetMinPower(ah, &data[numChannels - 1]);
+                       return(AH_TRUE);
+               }
+       }
+
+       /* Linearly interpolate the power value now */
+       for (last=0,i=0;
+            (i<numChannels) && (chan->channel > data[i].channelValue);
+            last=i++);
+       totalD = data[i].channelValue - data[last].channelValue;
+       if (totalD > 0) {
+               totalF = data[i].maxPower_t4 - data[last].maxPower_t4;
+               *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD);
+
+               totalMin = ar5112GetMinPower(ah,&data[i]) - ar5112GetMinPower(ah, &data[last]);
+               *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar5112GetMinPower(ah, &data[last])*totalD)/totalD);
+               return (AH_TRUE);
+       } else {
+               if (chan->channel == data[i].channelValue) {
+                       *maxPow = data[i].maxPower_t4;
+                       *minPow = ar5112GetMinPower(ah, &data[i]);
+                       return(AH_TRUE);
+               } else
+                       return(AH_FALSE);
+       }
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar5112RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for analog bank scratch buffers
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+static HAL_BOOL
+ar5112RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5112State *priv;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar5112State));
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar5112RfDetach;
+       priv->base.writeRegs            = ar5112WriteRegs;
+       priv->base.getRfBank            = ar5112GetRfBank;
+       priv->base.setChannel           = ar5112SetChannel;
+       priv->base.setRfRegs            = ar5112SetRfRegs;
+       priv->base.setPowerTable        = ar5112SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar5112GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar5212GetNfAdjust;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+ar5112Probe(struct ath_hal *ah)
+{
+       return IS_RAD5112(ah);
+}
+AH_RF(RF5112, ar5112Probe, ar5112RfAttach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212.h   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AR5212_H_
+#define _ATH_AR5212_H_
+
+#include "ah_eeprom.h"
+
+#define        AR5212_MAGIC    0x19541014
+
+/* DCU Transmit Filter macros */
+#define CALC_MMR(dcu, idx) \
+       ( (4 * dcu) + (idx < 32 ? 0 : (idx < 64 ? 1 : (idx < 96 ? 2 : 3))) )
+#define TXBLK_FROM_MMR(mmr) \
+       (AR_D_TXBLK_BASE + ((mmr & 0x1f) << 6) + ((mmr & 0x20) >> 3))
+#define CALC_TXBLK_ADDR(dcu, idx)      (TXBLK_FROM_MMR(CALC_MMR(dcu, idx)))
+#define CALC_TXBLK_VALUE(idx)          (1 << (idx & 0x1f))
+
+/* MAC register values */
+
+#define INIT_INTERRUPT_MASK \
+       ( AR_IMR_TXERR  | AR_IMR_TXOK | AR_IMR_RXORN | \
+         AR_IMR_RXERR  | AR_IMR_RXOK | AR_IMR_TXURN | \
+         AR_IMR_HIUERR )
+#define INIT_BEACON_CONTROL \
+       ((INIT_RESET_TSF << 24)  | (INIT_BEACON_EN << 23) | \
+         (INIT_TIM_OFFSET << 16) | INIT_BEACON_PERIOD)
+
+#define INIT_CONFIG_STATUS     0x00000000
+#define INIT_RSSI_THR          0x00000781      /* Missed beacon counter initialized to 0x7 (max is 0xff) */
+#define INIT_IQCAL_LOG_COUNT_MAX       0xF
+#define INIT_BCON_CNTRL_REG    0x00000000
+
+#define INIT_USEC              40
+#define HALF_RATE_USEC         19 /* ((40 / 2) - 1 ) */
+#define QUARTER_RATE_USEC      9  /* ((40 / 4) - 1 ) */
+
+#define RX_NON_FULL_RATE_LATENCY       63
+#define TX_HALF_RATE_LATENCY           108
+#define TX_QUARTER_RATE_LATENCY                216
+
+#define IFS_SLOT_FULL_RATE     0x168 /* 9 us half, 40 MHz core clock (9*40) */
+#define IFS_SLOT_HALF_RATE     0x104 /* 13 us half, 20 MHz core clock (13*20) */
+#define IFS_SLOT_QUARTER_RATE  0xD2 /* 21 us quarter, 10 MHz core clock (21*10) */
+#define IFS_EIFS_FULL_RATE     0xE60 /* (74 + (2 * 9)) * 40MHz core clock */
+#define IFS_EIFS_HALF_RATE     0xDAC /* (149 + (2 * 13)) * 20MHz core clock */
+#define IFS_EIFS_QUARTER_RATE  0xD48 /* (298 + (2 * 21)) * 10MHz core clock */
+
+#define ACK_CTS_TIMEOUT_11A    0x3E8 /* ACK timeout in 11a core clocks */
+
+/* Tx frame start to tx data start delay */
+#define TX_FRAME_D_START_HALF_RATE     0xc
+#define TX_FRAME_D_START_QUARTER_RATE  0xd
+
+/*
+ * Various fifo fill before Tx start, in 64-byte units
+ * i.e. put the frame in the air while still DMAing
+ */
+#define MIN_TX_FIFO_THRESHOLD  0x1
+#define MAX_TX_FIFO_THRESHOLD  ((IEEE80211_MAX_LEN / 64) + 1)
+#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD
+
+#define        HAL_DECOMP_MASK_SIZE    128     /* 1 byte per key */
+
+/*
+ * Gain support.
+ */
+#define        NUM_CORNER_FIX_BITS             4
+#define        NUM_CORNER_FIX_BITS_5112        7
+#define        DYN_ADJ_UP_MARGIN               15
+#define        DYN_ADJ_LO_MARGIN               20
+#define        PHY_PROBE_CCK_CORRECTION        5
+#define        CCK_OFDM_GAIN_DELTA             15
+
+enum GAIN_PARAMS {
+       GP_TXCLIP,
+       GP_PD90,
+       GP_PD84,
+       GP_GSEL,
+};
+
+enum GAIN_PARAMS_5112 {
+       GP_MIXGAIN_OVR,
+       GP_PWD_138,
+       GP_PWD_137,
+       GP_PWD_136,
+       GP_PWD_132,
+       GP_PWD_131,
+       GP_PWD_130,
+};
+
+typedef struct _gainOptStep {
+       int16_t paramVal[NUM_CORNER_FIX_BITS_5112];
+       int32_t stepGain;
+       int8_t  stepName[16];
+} GAIN_OPTIMIZATION_STEP;
+
+typedef struct {
+       uint32_t        numStepsInLadder;
+       uint32_t        defaultStepNum;
+       GAIN_OPTIMIZATION_STEP optStep[10];
+} GAIN_OPTIMIZATION_LADDER;
+
+typedef struct {
+       uint32_t        currStepNum;
+       uint32_t        currGain;
+       uint32_t        targetGain;
+       uint32_t        loTrig;
+       uint32_t        hiTrig;
+       uint32_t        gainFCorrection;
+       uint32_t        active;
+       const GAIN_OPTIMIZATION_STEP *currStep;
+} GAIN_VALUES;
+
+/* RF HAL structures */
+typedef struct RfHalFuncs {
+       void      *priv;                /* private state */
+
+       void      (*rfDetach)(struct ath_hal *ah);
+       void      (*writeRegs)(struct ath_hal *,
+                       u_int modeIndex, u_int freqIndex, int regWrites);
+       uint32_t *(*getRfBank)(struct ath_hal *ah, int bank);
+       HAL_BOOL  (*setChannel)(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+       HAL_BOOL  (*setRfRegs)(struct ath_hal *,
+                     HAL_CHANNEL_INTERNAL *, uint16_t modesIndex,
+                     uint16_t *rfXpdGain);
+       HAL_BOOL  (*setPowerTable)(struct ath_hal *ah,
+                     int16_t *minPower, int16_t *maxPower,
+                     HAL_CHANNEL_INTERNAL *, uint16_t *rfXpdGain);
+       HAL_BOOL  (*getChannelMaxMinPower)(struct ath_hal *ah, HAL_CHANNEL *,
+                     int16_t *maxPow, int16_t *minPow);
+       int16_t   (*getNfAdjust)(struct ath_hal *, const HAL_CHANNEL_INTERNAL*);
+} RF_HAL_FUNCS;
+
+struct ar5212AniParams {
+       int             maxNoiseImmunityLevel;  /* [0..4] */
+       int             totalSizeDesired[5];
+       int             coarseHigh[5];
+       int             coarseLow[5];
+       int             firpwr[5];
+
+       int             maxSpurImmunityLevel;   /* [0..7] */
+       int             cycPwrThr1[8];
+
+       int             maxFirstepLevel;        /* [0..2] */
+       int             firstep[3];
+
+       uint32_t        ofdmTrigHigh;
+       uint32_t        ofdmTrigLow;
+       uint32_t        cckTrigHigh;
+       uint32_t        cckTrigLow;
+       int32_t         rssiThrLow;
+       uint32_t        rssiThrHigh;
+
+       int             period;                 /* update listen period */
+
+       /* NB: intentionally ordered so data exported to user space is first */
+       uint32_t        ofdmPhyErrBase; /* Base value for ofdm err counter */
+       uint32_t        cckPhyErrBase;  /* Base value for cck err counters */
+};
+
+/*
+ * Per-channel ANI state private to the driver.
+ */
+struct ar5212AniState {
+       uint8_t         noiseImmunityLevel;
+       uint8_t         spurImmunityLevel;
+       uint8_t         firstepLevel;
+       uint8_t         ofdmWeakSigDetectOff;
+       uint8_t         cckWeakSigThreshold;
+       uint32_t        listenTime;
+
+       /* NB: intentionally ordered so data exported to user space is first */
+       HAL_CHANNEL     c;
+       HAL_BOOL        isSetup;        /* has state to do a restore */
+       uint32_t        txFrameCount;   /* Last txFrameCount */
+       uint32_t        rxFrameCount;   /* Last rx Frame count */
+       uint32_t        cycleCount;     /* Last cycleCount
+                                          (to detect wrap-around) */
+       uint32_t        ofdmPhyErrCount;/* OFDM err count since last reset */
+       uint32_t        cckPhyErrCount; /* CCK err count since last reset */
+
+       const struct ar5212AniParams *params;
+};
+
+#define        HAL_ANI_ENA             0x00000001      /* ANI operation enabled */
+#define        HAL_RSSI_ANI_ENA        0x00000002      /* rssi-based processing ena'd*/
+
+struct ar5212Stats {
+       uint32_t        ast_ani_niup;   /* ANI increased noise immunity */
+       uint32_t        ast_ani_nidown; /* ANI decreased noise immunity */
+       uint32_t        ast_ani_spurup; /* ANI increased spur immunity */
+       uint32_t        ast_ani_spurdown;/* ANI descreased spur immunity */
+       uint32_t        ast_ani_ofdmon; /* ANI OFDM weak signal detect on */
+       uint32_t        ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */
+       uint32_t        ast_ani_cckhigh;/* ANI CCK weak signal threshold high */
+       uint32_t        ast_ani_ccklow; /* ANI CCK weak signal threshold low */
+       uint32_t        ast_ani_stepup; /* ANI increased first step level */
+       uint32_t        ast_ani_stepdown;/* ANI decreased first step level */
+       uint32_t        ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */
+       uint32_t        ast_ani_cckerrs;/* ANI cumulative cck phy err count */
+       uint32_t        ast_ani_reset;  /* ANI parameters zero'd for non-STA */
+       uint32_t        ast_ani_lzero;  /* ANI listen time forced to zero */
+       uint32_t        ast_ani_lneg;   /* ANI listen time calculated < 0 */
+       HAL_MIB_STATS   ast_mibstats;   /* MIB counter stats */
+       HAL_NODE_STATS  ast_nodestats;  /* Latest rssi stats from driver */
+};
+
+/*
+ * NF Cal history buffer
+ */
+#define        AR5212_CCA_MAX_GOOD_VALUE       -95
+#define        AR5212_CCA_MAX_HIGH_VALUE       -62
+#define        AR5212_CCA_MIN_BAD_VALUE        -125
+
+#define        AR512_NF_CAL_HIST_MAX           5
+
+struct ar5212NfCalHist {
+       int16_t         nfCalBuffer[AR512_NF_CAL_HIST_MAX];
+       int16_t         privNF;
+       uint8_t         currIndex;
+       uint8_t         first_run;
+       uint8_t         invalidNFcount;
+};
+
+struct ath_hal_5212 {
+       struct ath_hal_private  ah_priv;        /* base class */
+
+       /*
+        * Per-chip common Initialization data.
+        * NB: RF backends have their own ini data.
+        */
+       HAL_INI_ARRAY   ah_ini_modes;
+       HAL_INI_ARRAY   ah_ini_common;
+
+       GAIN_VALUES     ah_gainValues;
+
+       uint8_t         ah_macaddr[IEEE80211_ADDR_LEN];
+       uint8_t         ah_bssid[IEEE80211_ADDR_LEN];
+       uint8_t         ah_bssidmask[IEEE80211_ADDR_LEN];
+
+       /*
+        * Runtime state.
+        */
+       uint32_t        ah_maskReg;             /* copy of AR_IMR */
+       struct ar5212Stats ah_stats;            /* various statistics */
+       RF_HAL_FUNCS    *ah_rfHal;
+       uint32_t        ah_txDescMask;          /* mask for TXDESC */
+       uint32_t        ah_txOkInterruptMask;
+       uint32_t        ah_txErrInterruptMask;
+       uint32_t        ah_txDescInterruptMask;
+       uint32_t        ah_txEolInterruptMask;
+       uint32_t        ah_txUrnInterruptMask;
+       HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES];
+       uint32_t        ah_intrTxqs;            /* tx q interrupt state */
+                                               /* decomp mask array */
+       uint8_t         ah_decompMask[HAL_DECOMP_MASK_SIZE];
+       HAL_POWER_MODE  ah_powerMode;
+       HAL_ANT_SETTING ah_antControl;          /* antenna setting */
+       HAL_BOOL        ah_diversity;           /* fast diversity setting */
+       enum {
+               IQ_CAL_INACTIVE,
+               IQ_CAL_RUNNING,
+               IQ_CAL_DONE
+       } ah_bIQCalibration;                    /* IQ calibrate state */
+       HAL_RFGAIN      ah_rfgainState;         /* RF gain calibrartion state */
+       uint32_t        ah_tx6PowerInHalfDbm;   /* power output for 6Mb tx */
+       uint32_t        ah_staId1Defaults;      /* STA_ID1 default settings */
+       uint32_t        ah_miscMode;            /* MISC_MODE settings */
+       uint32_t        ah_rssiThr;             /* RSSI_THR settings */
+       HAL_BOOL        ah_cwCalRequire;        /* for ap51 */
+       HAL_BOOL        ah_tpcEnabled;          /* per-packet tpc enabled */
+       HAL_BOOL        ah_phyPowerOn;          /* PHY power state */
+       HAL_BOOL        ah_isHb63;              /* cached HB63 check */
+       uint32_t        ah_macTPC;              /* tpc register */
+       uint32_t        ah_beaconInterval;      /* XXX */
+       enum {
+               AUTO_32KHZ,             /* use it if 32kHz crystal present */
+               USE_32KHZ,              /* do it regardless */
+               DONT_USE_32KHZ,         /* don't use it regardless */
+       } ah_enable32kHzClock;                  /* whether to sleep at 32kHz */
+       uint32_t        ah_ofdmTxPower;
+       int16_t         ah_txPowerIndexOffset;
+       /*
+        * Noise floor cal histogram support.
+        */
+       struct ar5212NfCalHist ah_nfCalHist;
+
+       u_int           ah_slottime;            /* user-specified slot time */
+       u_int           ah_acktimeout;          /* user-specified ack timeout */
+       u_int           ah_ctstimeout;          /* user-specified cts timeout */
+       u_int           ah_sifstime;            /* user-specified sifs time */
+       /*
+        * RF Silent handling; setup according to the EEPROM.
+        */
+       uint32_t        ah_gpioSelect;          /* GPIO pin to use */
+       uint32_t        ah_polarity;            /* polarity to disable RF */
+       uint32_t        ah_gpioBit;             /* after init, prev value */
+       /*
+        * ANI support.
+        */
+       uint32_t        ah_procPhyErr;          /* Process Phy errs */
+       HAL_BOOL        ah_hasHwPhyCounters;    /* Hardware has phy counters */
+       struct ar5212AniParams ah_aniParams24;  /* 2.4GHz parameters */
+       struct ar5212AniParams ah_aniParams5;   /* 5GHz parameters */
+       struct ar5212AniState   *ah_curani;     /* cached last reference */
+       struct ar5212AniState   ah_ani[64];     /* per-channel state */
+
+       /*
+        * Transmit power state.  Note these are maintained
+        * here so they can be retrieved by diagnostic tools.
+        */
+       uint16_t        *ah_pcdacTable;
+       u_int           ah_pcdacTableSize;
+       uint16_t        ah_ratesArray[16];
+};
+#define        AH5212(_ah)     ((struct ath_hal_5212 *)(_ah))
+
+/*
+ * IS_XXXX macros test the MAC version
+ * IS_RADXXX macros test the radio/RF version (matching both 2G-only and 2/5G)
+ *
+ * Some single chip radios have equivalent radio/RF (e.g. 5112)
+ * for those use IS_RADXXX_ANY macros.
+ */
+#define IS_2317(ah) \
+       ((AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1) || \
+        (AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2))
+#define        IS_2316(ah) \
+       (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2415)
+#define        IS_2413(ah) \
+       (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2413 || IS_2316(ah))
+#define IS_5424(ah) \
+       (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5424 || \
+       (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5413 && \
+         AH_PRIVATE(ah)->ah_macRev <= AR_SREV_D2PLUS_MS))
+#define IS_5413(ah) \
+       (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5413 || IS_5424(ah))
+#define IS_2425(ah) \
+       (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425)
+#define IS_2417(ah) \
+       ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_2417)
+#define IS_HB63(ah)            (AH5212(ah)->ah_isHb63 == AH_TRUE)
+
+#define IS_PCIE(ah) (IS_5424(ah) || IS_2425(ah))
+
+#define        AH_RADIO_MAJOR(ah) \
+       (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)
+#define        AH_RADIO_MINOR(ah) \
+       (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MINOR)
+#define        IS_RAD5111(ah) \
+       (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR || \
+        AH_RADIO_MAJOR(ah) == AR_RAD2111_SREV_MAJOR)
+#define        IS_RAD5112(ah) \
+       (AH_RADIO_MAJOR(ah) == AR_RAD5112_SREV_MAJOR || \
+        AH_RADIO_MAJOR(ah) == AR_RAD2112_SREV_MAJOR)
+/* NB: does not include 5413 as Atheros' IS_5112 macro does */
+#define        IS_RAD5112_ANY(ah) \
+       (AR_RAD5112_SREV_MAJOR <= AH_RADIO_MAJOR(ah) && \
+        AH_RADIO_MAJOR(ah) <= AR_RAD2413_SREV_MAJOR)
+#define        IS_RAD5112_REV1(ah) \
+       (IS_RAD5112(ah) && \
+        AH_RADIO_MINOR(ah) < (AR_RAD5112_SREV_2_0 & AR_RADIO_SREV_MINOR))
+#define IS_RADX112_REV2(ah) \
+       (AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_0 || \
+        AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_0 || \
+        AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_1 || \
+        AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_1)
+
+#define        ar5212RfDetach(ah) do {                         \
+       if (AH5212(ah)->ah_rfHal != AH_NULL)            \
+               AH5212(ah)->ah_rfHal->rfDetach(ah);     \
+} while (0)
+#define        ar5212GetRfBank(ah, b) \
+       AH5212(ah)->ah_rfHal->getRfBank(ah, b)
+
+/*
+ * Hack macros for Nala/San: 11b is handled
+ * using 11g; flip the channel flags to accomplish this.
+ */
+#define SAVE_CCK(_ah, _chan, _flag) do {                       \
+       if ((IS_2425(_ah) || IS_2417(_ah)) &&                   \
+           (((_chan)->channelFlags) & CHANNEL_CCK)) {          \
+               (_chan)->channelFlags &= ~CHANNEL_CCK;          \
+               (_chan)->channelFlags |= CHANNEL_OFDM;          \
+               (_flag) = AH_TRUE;                              \
+       }                                                       \
+} while (0)
+#define RESTORE_CCK(_ah, _chan, _flag) do {                     \
+       if ((IS_2425(_ah) || IS_2417(_ah)) && (_flag) == AH_TRUE) {\
+               (_chan)->channelFlags &= ~CHANNEL_OFDM;         \
+               (_chan)->channelFlags |= CHANNEL_CCK;           \
+       }                                                       \
+} while (0)
+
+struct ath_hal;
+
+extern uint32_t ar5212GetRadioRev(struct ath_hal *ah);
+extern void ar5212InitState(struct ath_hal_5212 *, uint16_t devid, HAL_SOFTC,
+               HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status);
+extern void ar5212Detach(struct ath_hal *ah);
+extern  HAL_BOOL ar5212ChipTest(struct ath_hal *ah);
+extern  HAL_BOOL ar5212GetChannelEdges(struct ath_hal *ah,
+                uint16_t flags, uint16_t *low, uint16_t *high);
+extern HAL_BOOL ar5212FillCapabilityInfo(struct ath_hal *ah);
+
+extern void ar5212SetBeaconTimers(struct ath_hal *ah,
+               const HAL_BEACON_TIMERS *);
+extern void ar5212BeaconInit(struct ath_hal *ah,
+               uint32_t next_beacon, uint32_t beacon_period);
+extern void ar5212ResetStaBeaconTimers(struct ath_hal *ah);
+extern void ar5212SetStaBeaconTimers(struct ath_hal *ah,
+               const HAL_BEACON_STATE *);
+
+extern HAL_BOOL ar5212IsInterruptPending(struct ath_hal *ah);
+extern HAL_BOOL ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *);
+extern HAL_INT ar5212GetInterrupts(struct ath_hal *ah);
+extern HAL_INT ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints);
+
+extern uint32_t ar5212GetKeyCacheSize(struct ath_hal *);
+extern HAL_BOOL ar5212IsKeyCacheEntryValid(struct ath_hal *, uint16_t entry);
+extern HAL_BOOL ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry);
+extern HAL_BOOL ar5212SetKeyCacheEntryMac(struct ath_hal *,
+                       uint16_t entry, const uint8_t *mac);
+extern HAL_BOOL ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
+                       const HAL_KEYVAL *k, const uint8_t *mac, int xorKey);
+
+extern void ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac);
+extern HAL_BOOL ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *);
+extern void ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mac);
+extern HAL_BOOL ar5212SetBssIdMask(struct ath_hal *, const uint8_t *);
+extern HAL_BOOL ar5212EepromRead(struct ath_hal *, u_int off, uint16_t *data);
+extern HAL_BOOL ar5212EepromWrite(struct ath_hal *, u_int off, uint16_t data);
+extern HAL_BOOL ar5212SetRegulatoryDomain(struct ath_hal *ah,
+               uint16_t regDomain, HAL_STATUS *stats);
+extern u_int ar5212GetWirelessModes(struct ath_hal *ah);
+extern void ar5212EnableRfKill(struct ath_hal *);
+extern HAL_BOOL ar5212GpioCfgOutput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5212GpioCfgInput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5212GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val);
+extern uint32_t ar5212GpioGet(struct ath_hal *ah, uint32_t gpio);
+extern void ar5212GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel);
+extern void ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state);
+extern void ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid,
+               uint16_t assocId);
+extern uint32_t ar5212GetTsf32(struct ath_hal *ah);
+extern uint64_t ar5212GetTsf64(struct ath_hal *ah);
+extern void ar5212ResetTsf(struct ath_hal *ah);
+extern void ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *pSet);
+extern uint32_t ar5212GetRandomSeed(struct ath_hal *ah);
+extern HAL_BOOL ar5212DetectCardPresent(struct ath_hal *ah);
+extern void ar5212EnableMibCounters(struct ath_hal *);
+extern void ar5212DisableMibCounters(struct ath_hal *);
+extern void ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats);
+extern HAL_BOOL ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah);
+extern uint32_t ar5212GetCurRssi(struct ath_hal *ah);
+extern u_int ar5212GetDefAntenna(struct ath_hal *ah);
+extern void ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna);
+extern HAL_ANT_SETTING ar5212GetAntennaSwitch(struct ath_hal *);
+extern HAL_BOOL ar5212SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
+extern HAL_BOOL ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah);
+extern HAL_BOOL ar5212SetSifsTime(struct ath_hal *, u_int);
+extern u_int ar5212GetSifsTime(struct ath_hal *);
+extern HAL_BOOL ar5212SetSlotTime(struct ath_hal *, u_int);
+extern u_int ar5212GetSlotTime(struct ath_hal *);
+extern HAL_BOOL ar5212SetAckTimeout(struct ath_hal *, u_int);
+extern u_int ar5212GetAckTimeout(struct ath_hal *);
+extern HAL_BOOL ar5212SetAckCTSRate(struct ath_hal *, u_int);
+extern u_int ar5212GetAckCTSRate(struct ath_hal *);
+extern HAL_BOOL ar5212SetCTSTimeout(struct ath_hal *, u_int);
+extern u_int ar5212GetCTSTimeout(struct ath_hal *);
+extern  HAL_BOOL ar5212SetDecompMask(struct ath_hal *, uint16_t, int);
+void   ar5212SetCoverageClass(struct ath_hal *, uint8_t, int);
+extern void ar5212SetPCUConfig(struct ath_hal *);
+extern HAL_BOOL ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode);
+extern void ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode);
+extern void ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode);
+extern int16_t ar5212GetNfAdjust(struct ath_hal *,
+               const HAL_CHANNEL_INTERNAL *);
+extern void ar5212SetCompRegs(struct ath_hal *ah);
+extern HAL_STATUS ar5212GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE,
+               uint32_t, uint32_t *);
+extern HAL_BOOL ar5212SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE,
+               uint32_t, uint32_t, HAL_STATUS *);
+extern HAL_BOOL ar5212GetDiagState(struct ath_hal *ah, int request,
+               const void *args, uint32_t argsize,
+               void **result, uint32_t *resultsize);
+
+extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
+               int setChip);
+extern HAL_POWER_MODE ar5212GetPowerMode(struct ath_hal *ah);
+extern HAL_BOOL ar5212GetPowerStatus(struct ath_hal *ah);
+
+extern uint32_t ar5212GetRxDP(struct ath_hal *ath);
+extern void ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp);
+extern void ar5212EnableReceive(struct ath_hal *ah);
+extern HAL_BOOL ar5212StopDmaReceive(struct ath_hal *ah);
+extern void ar5212StartPcuReceive(struct ath_hal *ah);
+extern void ar5212StopPcuReceive(struct ath_hal *ah);
+extern void ar5212SetMulticastFilter(struct ath_hal *ah,
+               uint32_t filter0, uint32_t filter1);
+extern HAL_BOOL ar5212ClrMulticastFilterIndex(struct ath_hal *, uint32_t ix);
+extern HAL_BOOL ar5212SetMulticastFilterIndex(struct ath_hal *, uint32_t ix);
+extern uint32_t ar5212GetRxFilter(struct ath_hal *ah);
+extern void ar5212SetRxFilter(struct ath_hal *ah, uint32_t bits);
+extern HAL_BOOL ar5212SetupRxDesc(struct ath_hal *,
+               struct ath_desc *, uint32_t size, u_int flags);
+extern HAL_STATUS ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *,
+               uint32_t, struct ath_desc *, uint64_t,
+               struct ath_rx_status *);
+
+extern HAL_BOOL ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+               HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status);
+extern HAL_BOOL ar5212SetChannel(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+extern void ar5212SetOperatingMode(struct ath_hal *ah, int opmode);
+extern HAL_BOOL ar5212PhyDisable(struct ath_hal *ah);
+extern HAL_BOOL ar5212Disable(struct ath_hal *ah);
+extern HAL_BOOL ar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *);
+extern HAL_BOOL ar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan,
+               HAL_BOOL *isIQdone);
+extern HAL_BOOL ar5212PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan,
+               u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone);
+extern HAL_BOOL ar5212ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan);
+extern int16_t ar5212GetNoiseFloor(struct ath_hal *ah);
+extern void ar5212InitNfCalHistBuffer(struct ath_hal *);
+extern int16_t ar5212GetNfHistMid(const int16_t calData[]);
+extern void ar5212SetSpurMitigation(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+extern HAL_BOOL ar5212SetAntennaSwitchInternal(struct ath_hal *ah,
+               HAL_ANT_SETTING settings, const HAL_CHANNEL_INTERNAL *ichan);
+extern HAL_BOOL ar5212SetTxPowerLimit(struct ath_hal *ah, uint32_t limit);
+extern HAL_BOOL ar5212GetChipPowerLimits(struct ath_hal *ah,
+                                         HAL_CHANNEL *chans, uint32_t nchans);
+extern void ar5212InitializeGainValues(struct ath_hal *);
+extern HAL_RFGAIN ar5212GetRfgain(struct ath_hal *ah);
+extern void ar5212RequestRfgain(struct ath_hal *);
+
+extern HAL_BOOL ar5212UpdateTxTrigLevel(struct ath_hal *,
+               HAL_BOOL IncTrigLevel);
+extern  HAL_BOOL ar5212SetTxQueueProps(struct ath_hal *ah, int q,
+               const HAL_TXQ_INFO *qInfo);
+extern HAL_BOOL ar5212GetTxQueueProps(struct ath_hal *ah, int q,
+               HAL_TXQ_INFO *qInfo);
+extern int ar5212SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
+               const HAL_TXQ_INFO *qInfo);
+extern HAL_BOOL ar5212ReleaseTxQueue(struct ath_hal *ah, u_int q);
+extern HAL_BOOL ar5212ResetTxQueue(struct ath_hal *ah, u_int q);
+extern uint32_t ar5212GetTxDP(struct ath_hal *ah, u_int q);
+extern HAL_BOOL ar5212SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp);
+extern HAL_BOOL ar5212StartTxDma(struct ath_hal *ah, u_int q);
+extern uint32_t ar5212NumTxPending(struct ath_hal *ah, u_int q);
+extern HAL_BOOL ar5212StopTxDma(struct ath_hal *ah, u_int q);
+extern HAL_BOOL ar5212SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+               u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower,
+               u_int txRate0, u_int txTries0,
+               u_int keyIx, u_int antMode, u_int flags,
+               u_int rtsctsRate, u_int rtsctsDuration,
+               u_int compicvLen, u_int compivLen, u_int comp);
+extern HAL_BOOL ar5212SetupXTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int txRate1, u_int txRetries1,
+               u_int txRate2, u_int txRetries2,
+               u_int txRate3, u_int txRetries3);
+extern HAL_BOOL ar5212FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+               u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+               const struct ath_desc *ds0);
+extern HAL_STATUS ar5212ProcTxDesc(struct ath_hal *ah,
+               struct ath_desc *, struct ath_tx_status *);
+extern  void ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *);
+extern  void ar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *);
+
+extern const HAL_RATE_TABLE *ar5212GetRateTable(struct ath_hal *, u_int mode);
+
+extern void ar5212AniAttach(struct ath_hal *, const struct ar5212AniParams *,
+               const struct ar5212AniParams *, HAL_BOOL ena);
+extern void ar5212AniDetach(struct ath_hal *);
+extern struct ar5212AniState *ar5212AniGetCurrentState(struct ath_hal *);
+extern struct ar5212Stats *ar5212AniGetCurrentStats(struct ath_hal *);
+extern HAL_BOOL ar5212AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param);
+extern HAL_BOOL ar5212AniSetParams(struct ath_hal *,
+               const struct ar5212AniParams *, const struct ar5212AniParams *);
+struct ath_rx_status;
+extern void ar5212AniPhyErrReport(struct ath_hal *ah,
+               const struct ath_rx_status *rs);
+extern void ar5212ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *);
+extern void ar5212AniPoll(struct ath_hal *, const HAL_NODE_STATS *,
+                            HAL_CHANNEL *);
+extern void ar5212AniReset(struct ath_hal *, HAL_CHANNEL_INTERNAL *,
+               HAL_OPMODE, int);
+#endif /* _ATH_AR5212_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212.ini 2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,2171 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212.ini,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+/* Auto Generated PCI Register Writes.  Created: 09/01/04 */
+
+#ifdef AH_5212_COMMON
+static const uint32_t ar5212Modes[][6] = {
+    { 0x00001040, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f },
+    { 0x00001030, 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 },
+    { 0x00008014, 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 },
+    { 0x00009804, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e },
+    { 0x00009844, 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 },
+    { 0x00009860, 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 },
+    { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
+    { 0x00009918, 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 },
+    { 0x00009924, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 },
+};
+#endif /* AH_5212_COMMON */
+
+#ifdef AH_5212_5111
+static const uint32_t ar5212Modes_5111[][6] = {
+    { 0x00000030, 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 },
+    { 0x0000801c, 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b },
+    { 0x00009848, 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 },
+    { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 },
+    { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e },
+    { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 },
+    { 0x00009914, 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 },
+    { 0x00009944, 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 },
+    { 0x0000a20c, 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a },
+};
+#endif /* AH_5212_5111 */
+
+#ifdef AH_5212_5112
+static const uint32_t ar5212Modes_5112[][6] = {
+    { 0x00000030, 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 },
+    { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b },
+    { 0x00009848, 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 },
+    { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 },
+    { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e },
+    { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 },
+    { 0x00009944, 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 },
+    { 0x0000a204, 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 },
+    { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 },
+    { 0x0000a20c, 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a },
+};
+#endif /* AH_5212_5112 */
+
+#ifdef AH_5212_2413
+static const uint32_t ar5212Modes_2413[][6] = {
+    { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 },
+    { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 },
+    { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a },
+    { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 },
+    { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da },
+    { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e },
+    { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 },
+    { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 },
+    { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 },
+    { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a },
+};
+#endif /* AH_5212_2413 */
+
+#ifdef AH_5212_2316
+static const uint32_t ar5212Modes_2316[][6] = {
+    { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 },
+    { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 },
+    { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a },
+    { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 },
+    { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da },
+    { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e },
+    { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 },
+    { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 },
+    { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 },
+    { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a },
+};
+#endif
+
+#ifdef AH_5212_5413
+static const uint32_t ar5212Modes_5413[][6] = {
+    { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 },
+    { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b },
+    { 0x00009848, 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 },
+    { 0x00009850, 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da },
+    { 0x00009858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 },
+    { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 },
+    { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 },
+    { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a },
+    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
+    { 0x0000a304, 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 },
+    { 0x0000a308, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 },
+    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a },
+    { 0x0000a310, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f },
+    { 0x0000a314, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b },
+    { 0x0000a318, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a },
+    { 0x0000a31c, 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b },
+    { 0x0000a320, 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f },
+    { 0x0000a324, 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f },
+    { 0x0000a328, 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f },
+    { 0x0000a32c, 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f },
+    { 0x0000a330, 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f },
+    { 0x0000a334, 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf },
+};
+#endif /* AH_5212_5413 */
+
+#ifdef AH_5212_2425
+static const uint32_t ar5212Modes_2425[][6] = {
+    { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 },
+    { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf },
+    { 0x00009804, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b },
+    { 0x00009844, 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 },
+    { 0x00009848, 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 },
+    { 0x00009850, 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da },
+    { 0x00009858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 },
+    { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 },
+    { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 },
+    { 0x0000a20c, 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a },
+    { 0x0000a324, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf },
+    { 0x0000a328, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf },
+    { 0x0000a32c, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf },
+    { 0x0000a330, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf },
+    { 0x0000a334, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf },
+};
+#endif /* AH_5212_2425 */
+
+#ifdef AH_5212_COMMON
+static const uint32_t ar5212Common[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008024, 0x00000000 },
+    { 0x00008028, 0x00000030 },
+    { 0x0000802c, 0x0007ffff },
+    { 0x00008030, 0x01ffffff },
+    { 0x00008034, 0x00000031 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x00000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e1c },
+    { 0x000080d4, 0x0002aaaa },
+    { 0x000080d8, 0x02005555 },
+    { 0x000080dc, 0x00000000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x00000000 },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00000088 },
+    { 0x00008700, 0x00000000 },
+    { 0x00008704, 0x0000008c },
+    { 0x00008708, 0x000000e4 },
+    { 0x0000870c, 0x000002d5 },
+    { 0x00008710, 0x00000000 },
+    { 0x00008714, 0x00000000 },
+    { 0x00008718, 0x000000a0 },
+    { 0x0000871c, 0x000001c9 },
+    { 0x00008720, 0x0000002c },
+    { 0x00008724, 0x0000002c },
+    { 0x00008728, 0x00000030 },
+    { 0x0000872c, 0x0000003c },
+    { 0x00008730, 0x0000002c },
+    { 0x00008734, 0x0000002c },
+    { 0x00008738, 0x00000030 },
+    { 0x0000873c, 0x0000003c },
+    { 0x00008740, 0x00000000 },
+    { 0x00008744, 0x00000000 },
+    { 0x00008748, 0x00000000 },
+    { 0x0000874c, 0x00000000 },
+    { 0x00008750, 0x00000000 },
+    { 0x00008754, 0x00000000 },
+    { 0x00008758, 0x00000000 },
+    { 0x0000875c, 0x00000000 },
+    { 0x00008760, 0x000000d5 },
+    { 0x00008764, 0x000000df },
+    { 0x00008768, 0x00000102 },
+    { 0x0000876c, 0x0000013a },
+    { 0x00008770, 0x00000075 },
+    { 0x00008774, 0x0000007f },
+    { 0x00008778, 0x000000a2 },
+    { 0x0000877c, 0x00000000 },
+    { 0x00008100, 0x00010002 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x000000c0 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008114, 0x00000000 },
+    { 0x000087c0, 0x03020100 },
+    { 0x000087c4, 0x07060504 },
+    { 0x000087c8, 0x0b0a0908 },
+    { 0x000087cc, 0x0f0e0d0c },
+    { 0x000087d0, 0x13121110 },
+    { 0x000087d4, 0x17161514 },
+    { 0x000087d8, 0x1b1a1918 },
+    { 0x000087dc, 0x1f1e1d1c },
+    { 0x000087e0, 0x03020100 },
+    { 0x000087e4, 0x07060504 },
+    { 0x000087e8, 0x0b0a0908 },
+    { 0x000087ec, 0x0f0e0d0c },
+    { 0x000087f0, 0x13121110 },
+    { 0x000087f4, 0x17161514 },
+    { 0x000087f8, 0x1b1a1918 },
+    { 0x000087fc, 0x1f1e1d1c },
+    { 0x0000980c, 0xad848e19 },
+    { 0x00009810, 0x7d28e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x00009840, 0x206a017a },
+    { 0x00009854, 0x00000859 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00800000 },
+    { 0x00009910, 0x00000001 },
+    { 0x0000991c, 0x00000c80 },
+    { 0x00009920, 0x05100000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x0000003f },
+    { 0x00009948, 0x9280b212 },
+    { 0x00009954, 0x5d50e188 },
+    { 0x0000995c, 0x004b6a8e },
+    { 0x00009968, 0x000003ce },
+    { 0x00009970, 0x192fb515 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x0000a210, 0x00806333 },
+    { 0x0000a214, 0x00106c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x018830c6 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a22c, 0x00000000 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b28, 0x0000000c },
+    { 0x00009b38, 0x00000012 },
+    { 0x00009b64, 0x00000021 },
+    { 0x00009b8c, 0x0000002d },
+    { 0x00009b9c, 0x00000033 },
+};
+#endif /* AH_5212_COMMON */
+
+#ifdef AH_5212_5111
+static const uint32_t ar5212Common_5111[][2] = {
+    { 0x00001230, 0x00000000 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000982c, 0x00022ffe },
+    { 0x0000983c, 0x00020100 },
+    { 0x0000984c, 0x1284613c },
+    { 0x00009930, 0x00004883 },
+    { 0x00009940, 0x00000004 },
+    { 0x00009958, 0x000000ff },
+    { 0x00009974, 0x00000000 },
+    { 0x000099f8, 0x00000018 },
+    { 0x0000a204, 0x00000000 },
+    { 0x0000a208, 0xd03e6788 },
+    { 0x0000a228, 0x000001b5 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x00009b04, 0x00000020 },
+    { 0x00009b08, 0x00000010 },
+    { 0x00009b0c, 0x00000030 },
+    { 0x00009b10, 0x00000008 },
+    { 0x00009b14, 0x00000028 },
+    { 0x00009b18, 0x00000004 },
+    { 0x00009b1c, 0x00000024 },
+    { 0x00009b20, 0x00000014 },
+    { 0x00009b24, 0x00000034 },
+    { 0x00009b2c, 0x0000002c },
+    { 0x00009b30, 0x00000002 },
+    { 0x00009b34, 0x00000022 },
+    { 0x00009b3c, 0x00000032 },
+    { 0x00009b40, 0x0000000a },
+    { 0x00009b44, 0x0000002a },
+    { 0x00009b48, 0x00000006 },
+    { 0x00009b4c, 0x00000026 },
+    { 0x00009b50, 0x00000016 },
+    { 0x00009b54, 0x00000036 },
+    { 0x00009b58, 0x0000000e },
+    { 0x00009b5c, 0x0000002e },
+    { 0x00009b60, 0x00000001 },
+    { 0x00009b68, 0x00000011 },
+    { 0x00009b6c, 0x00000031 },
+    { 0x00009b70, 0x00000009 },
+    { 0x00009b74, 0x00000029 },
+    { 0x00009b78, 0x00000005 },
+    { 0x00009b7c, 0x00000025 },
+    { 0x00009b80, 0x00000015 },
+    { 0x00009b84, 0x00000035 },
+    { 0x00009b88, 0x0000000d },
+    { 0x00009b90, 0x00000003 },
+    { 0x00009b94, 0x00000023 },
+    { 0x00009b98, 0x00000013 },
+    { 0x00009ba0, 0x0000000b },
+    { 0x00009ba4, 0x0000002b },
+    { 0x00009ba8, 0x0000002b },
+    { 0x00009bac, 0x0000002b },
+    { 0x00009bb0, 0x0000002b },
+    { 0x00009bb4, 0x0000002b },
+    { 0x00009bb8, 0x0000002b },
+    { 0x00009bbc, 0x0000002b },
+    { 0x00009bc0, 0x0000002b },
+    { 0x00009bc4, 0x0000002b },
+    { 0x00009bc8, 0x0000002b },
+    { 0x00009bcc, 0x0000002b },
+    { 0x00009bd0, 0x0000002b },
+    { 0x00009bd4, 0x0000002b },
+    { 0x00009bd8, 0x0000002b },
+    { 0x00009bdc, 0x0000002b },
+    { 0x00009be0, 0x0000002b },
+    { 0x00009be4, 0x0000002b },
+    { 0x00009be8, 0x0000002b },
+    { 0x00009bec, 0x0000002b },
+    { 0x00009bf0, 0x0000002b },
+    { 0x00009bf4, 0x0000002b },
+    { 0x00009bf8, 0x00000002 },
+    { 0x00009bfc, 0x00000016 },
+};
+#endif /* AH_5212_5111 */
+
+#ifdef AH_5212_5112
+static const uint32_t ar5212Common_5112[][2] = {
+    { 0x00001230, 0x00000000 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000982c, 0x00022ffe },
+    { 0x0000983c, 0x00020100 },
+    { 0x0000984c, 0x1284613c },
+    { 0x00009930, 0x00004882 },
+    { 0x00009940, 0x00000004 },
+    { 0x00009958, 0x000000ff },
+    { 0x00009974, 0x00000000 },
+    { 0x0000a228, 0x000001b5 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+};
+#endif /* AH_5212_5112 */
+
+#ifdef AH_5212_2413
+static const uint32_t ar5212Common_2413[][2] = {
+    { 0x00001230, 0x000003e0 },
+    { 0x00008060, 0x0000000f },
+    { 0x00008118, 0x00000000 },
+    { 0x0000811c, 0x00000000 },
+    { 0x00008120, 0x00000000 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008140, 0x800000a8 },
+    { 0x00008144, 0x00000000 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009870, 0x0000001f },
+    { 0x00009874, 0x00000080 },
+    { 0x00009878, 0x0000000e },
+    { 0x00009958, 0x000000ff },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x02800000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099e0, 0x00000000 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x000000aa },
+    { 0x000099f0, 0x0000000c },
+    { 0x000099f4, 0x000000ff },
+    { 0x000099f8, 0x00000014 },
+    { 0x0000a228, 0x000009b5 },
+    { 0x0000a23c, 0x93c889af },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0x5f690f01 },
+    { 0x0000a264, 0x00418a11 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0c30c16a },
+    { 0x0000a270, 0x00820820 },
+    { 0x0000a274, 0x001b7caa },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x051701ce },
+    { 0x0000a300, 0x18010000 },
+    { 0x0000a304, 0x30032602 },
+    { 0x0000a308, 0x48073e06 },
+    { 0x0000a30c, 0x560b4c0a },
+    { 0x0000a310, 0x641a600f },
+    { 0x0000a314, 0x784f6e1b },
+    { 0x0000a318, 0x868f7c5a },
+    { 0x0000a31c, 0x8ecf865b },
+    { 0x0000a320, 0x9d4f970f },
+    { 0x0000a324, 0xa5cfa18f },
+    { 0x0000a328, 0xb55faf1f },
+    { 0x0000a32c, 0xbddfb99f },
+    { 0x0000a330, 0xcd7fc73f },
+    { 0x0000a334, 0xd5ffd1bf },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa1f },
+    { 0x0000a35c, 0x066c420f },
+    { 0x0000a360, 0x0f282207 },
+    { 0x0000a364, 0x17601685 },
+    { 0x0000a368, 0x1f801104 },
+    { 0x0000a36c, 0x37a00c03 },
+    { 0x0000a370, 0x3fc40883 },
+    { 0x0000a374, 0x57c00803 },
+    { 0x0000a378, 0x5fd80682 },
+    { 0x0000a37c, 0x7fe00482 },
+    { 0x0000a380, 0x7f3c7bba },
+    { 0x0000a384, 0xf3307ff0 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+};
+#endif /* AH_5212_2413 */
+
+#ifdef AH_5212_2316
+static const uint32_t ar5212Common_2316[][2] = {
+    { 0x00001230, 0x000003e0 },
+    { 0x00008060, 0x0000000f },
+    { 0x00008118, 0x00000000 },
+    { 0x0000811c, 0x00000000 },
+    { 0x00008120, 0x00000000 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008140, 0x800000a8 },
+    { 0x00008144, 0x00000000 },
+    { 0x00009808, 0x00004000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009870, 0x0000001f },
+    { 0x00009874, 0x00000080 },
+    { 0x00009878, 0x0000000e },
+    { 0x00009958, 0x000000ff },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x02800000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099e0, 0x00000000 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x000000aa },
+    { 0x000099f0, 0x0000000c },
+    { 0x000099f4, 0x000000ff },
+    { 0x000099f8, 0x00000014 },
+    { 0x0000a228, 0x000009b5 },
+    { 0x0000a23c, 0x93c889af },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0x5f690f01 },
+    { 0x0000a264, 0x00418a11 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0c30c16a },
+    { 0x0000a270, 0x00820820 },
+    { 0x0000a274, 0x081b7caa },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x051701ce },
+    { 0x0000a300, 0x18010000 },
+    { 0x0000a304, 0x30032602 },
+    { 0x0000a308, 0x48073e06 },
+    { 0x0000a30c, 0x560b4c0a },
+    { 0x0000a310, 0x641a600f },
+    { 0x0000a314, 0x784f6e1b },
+    { 0x0000a318, 0x868f7c5a },
+    { 0x0000a31c, 0x8ecf865b },
+    { 0x0000a320, 0x9d4f970f },
+    { 0x0000a324, 0xa5cfa18f },
+    { 0x0000a328, 0xb55faf1f },
+    { 0x0000a32c, 0xbddfb99f },
+    { 0x0000a330, 0xcd7fc73f },
+    { 0x0000a334, 0xd5ffd1bf },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa1f },
+    { 0x0000a35c, 0x066c420f },
+    { 0x0000a360, 0x0f282207 },
+    { 0x0000a364, 0x17601685 },
+    { 0x0000a368, 0x1f801104 },
+    { 0x0000a36c, 0x37a00c03 },
+    { 0x0000a370, 0x3fc40883 },
+    { 0x0000a374, 0x57c00803 },
+    { 0x0000a378, 0x5fd80682 },
+    { 0x0000a37c, 0x7fe00482 },
+    { 0x0000a380, 0x7f3c7bba },
+    { 0x0000a384, 0xf3307ff0 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+};
+#endif
+
+#ifdef AH_5212_5413
+static const uint32_t ar5212Common_5413[][2] = {
+    { 0x00001230, 0x000003e0 },
+    { 0x00004068, 0x00000010 },
+    { 0x00008060, 0x0000000f },
+    { 0x0000809c, 0x00000000 },
+    { 0x000080a0, 0x00000000 },
+    { 0x00008118, 0x00000000 },
+    { 0x0000811c, 0x00000000 },
+    { 0x00008120, 0x00000000 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008140, 0x800003f9 },
+    { 0x00008144, 0x00000000 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009870, 0x0000001f },
+    { 0x00009874, 0x00000080 },
+    { 0x00009878, 0x0000000e },
+    { 0x00009958, 0x00081fff },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x02800000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099e0, 0x00000000 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x000000aa },
+    { 0x000099f0, 0x0000000c },
+    { 0x000099f4, 0x000000ff },
+    { 0x000099f8, 0x00000014 },
+    { 0x0000a228, 0x000009b5 },
+    { 0x0000a23c, 0x93c889af },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0x5f690f01 },
+    { 0x0000a264, 0x00418a11 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0c30c16a },
+    { 0x0000a270, 0x00820820 },
+    { 0x0000a274, 0x081b7caa },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x051701ce },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa1f },
+    { 0x0000a35c, 0x066c420f },
+    { 0x0000a360, 0x0f282207 },
+    { 0x0000a364, 0x17601685 },
+    { 0x0000a368, 0x1f801104 },
+    { 0x0000a36c, 0x37a00c03 },
+    { 0x0000a370, 0x3fc40883 },
+    { 0x0000a374, 0x57c00803 },
+    { 0x0000a378, 0x5fd80682 },
+    { 0x0000a37c, 0x7fe00482 },
+    { 0x0000a380, 0x7f3c7bba },
+    { 0x0000a384, 0xf3307ff0 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+};
+#endif /* AH_5212_5413 */
+
+#ifdef AH_5212_2425
+static const uint32_t ar5212Common_2425[][2] = {
+    { 0x00001230, 0x000003e0 },
+    { 0x00008060, 0x0000000f },
+    { 0x0000809c, 0x00000000 },
+    { 0x000080a0, 0x00000000 },
+    { 0x00008118, 0x00000000 },
+    { 0x0000811c, 0x00000000 },
+    { 0x00008120, 0x00000000 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008140, 0x800003f9 },
+    { 0x00008144, 0x00000000 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009870, 0x0000001f },
+    { 0x00009874, 0x00000080 },
+    { 0x00009878, 0x0000000e },
+    { 0x00009958, 0x00081fff },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x02800000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099dc, 0xfebadbe8 },
+    { 0x000099e0, 0x00000000 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x000000aa },
+    { 0x000099f0, 0x0000000c },
+    { 0x000099f4, 0x000000ff },
+    { 0x000099f8, 0x00000014 },
+    { 0x0000a228, 0x000009b5 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x93c889af },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0x5f690f01 },
+    { 0x0000a264, 0x00418a11 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0c30c166 },
+    { 0x0000a270, 0x00820820 },
+    { 0x0000a274, 0x081a3caa },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x051701ce },
+    { 0x0000a300, 0x16010000 },
+    { 0x0000a304, 0x2c032402 },
+    { 0x0000a308, 0x48433e42 },
+    { 0x0000a30c, 0x5a0f500b },
+    { 0x0000a310, 0x6c4b624a },
+    { 0x0000a314, 0x7e8b748a },
+    { 0x0000a318, 0x96cf8ccb },
+    { 0x0000a31c, 0xa34f9d0f },
+    { 0x0000a320, 0xa7cfa58f },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa1f },
+    { 0x0000a35c, 0x066c420f },
+    { 0x0000a360, 0x0f282207 },
+    { 0x0000a364, 0x17601685 },
+    { 0x0000a368, 0x1f801104 },
+    { 0x0000a36c, 0x37a00c03 },
+    { 0x0000a370, 0x3fc40883 },
+    { 0x0000a374, 0x57c00803 },
+    { 0x0000a378, 0x5fd80682 },
+    { 0x0000a37c, 0x7fe00482 },
+    { 0x0000a380, 0x7f3c7bba },
+    { 0x0000a384, 0xf3307ff0 },
+};
+#endif /* AH_5212_2425 */
+
+#ifdef AH_5212_5111
+static const uint32_t ar5212Bank0_5111[][6] = {
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 },
+    { 0x0000989c, 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd },
+    { 0x000098d4, 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 },
+};
+
+static const uint32_t ar5212BB_RfGain_5111[][3] = {
+    { 0x00009a00, 0x000001a9, 0x00000000 },
+    { 0x00009a04, 0x000001e9, 0x00000040 },
+    { 0x00009a08, 0x00000029, 0x00000080 },
+    { 0x00009a0c, 0x00000069, 0x00000150 },
+    { 0x00009a10, 0x00000199, 0x00000190 },
+    { 0x00009a14, 0x000001d9, 0x000001d0 },
+    { 0x00009a18, 0x00000019, 0x00000010 },
+    { 0x00009a1c, 0x00000059, 0x00000044 },
+    { 0x00009a20, 0x00000099, 0x00000084 },
+    { 0x00009a24, 0x000001a5, 0x00000148 },
+    { 0x00009a28, 0x000001e5, 0x00000188 },
+    { 0x00009a2c, 0x00000025, 0x000001c8 },
+    { 0x00009a30, 0x000001c8, 0x00000014 },
+    { 0x00009a34, 0x00000008, 0x00000042 },
+    { 0x00009a38, 0x00000048, 0x00000082 },
+    { 0x00009a3c, 0x00000088, 0x00000178 },
+    { 0x00009a40, 0x00000198, 0x000001b8 },
+    { 0x00009a44, 0x000001d8, 0x000001f8 },
+    { 0x00009a48, 0x00000018, 0x00000012 },
+    { 0x00009a4c, 0x00000058, 0x00000052 },
+    { 0x00009a50, 0x00000098, 0x00000092 },
+    { 0x00009a54, 0x000001a4, 0x0000017c },
+    { 0x00009a58, 0x000001e4, 0x000001bc },
+    { 0x00009a5c, 0x00000024, 0x000001fc },
+    { 0x00009a60, 0x00000064, 0x0000000a },
+    { 0x00009a64, 0x000000a4, 0x0000004a },
+    { 0x00009a68, 0x000000e4, 0x0000008a },
+    { 0x00009a6c, 0x0000010a, 0x0000015a },
+    { 0x00009a70, 0x0000014a, 0x0000019a },
+    { 0x00009a74, 0x0000018a, 0x000001da },
+    { 0x00009a78, 0x000001ca, 0x0000000e },
+    { 0x00009a7c, 0x0000000a, 0x0000004e },
+    { 0x00009a80, 0x0000004a, 0x0000008e },
+    { 0x00009a84, 0x0000008a, 0x0000015e },
+    { 0x00009a88, 0x000001ba, 0x0000019e },
+    { 0x00009a8c, 0x000001fa, 0x000001de },
+    { 0x00009a90, 0x0000003a, 0x00000009 },
+    { 0x00009a94, 0x0000007a, 0x00000049 },
+    { 0x00009a98, 0x00000186, 0x00000089 },
+    { 0x00009a9c, 0x000001c6, 0x00000179 },
+    { 0x00009aa0, 0x00000006, 0x000001b9 },
+    { 0x00009aa4, 0x00000046, 0x000001f9 },
+    { 0x00009aa8, 0x00000086, 0x00000039 },
+    { 0x00009aac, 0x000000c6, 0x00000079 },
+    { 0x00009ab0, 0x000000c6, 0x000000b9 },
+    { 0x00009ab4, 0x000000c6, 0x000001bd },
+    { 0x00009ab8, 0x000000c6, 0x000001fd },
+    { 0x00009abc, 0x000000c6, 0x0000003d },
+    { 0x00009ac0, 0x000000c6, 0x0000007d },
+    { 0x00009ac4, 0x000000c6, 0x000000bd },
+    { 0x00009ac8, 0x000000c6, 0x000000fd },
+    { 0x00009acc, 0x000000c6, 0x000000fd },
+    { 0x00009ad0, 0x000000c6, 0x000000fd },
+    { 0x00009ad4, 0x000000c6, 0x000000fd },
+    { 0x00009ad8, 0x000000c6, 0x000000fd },
+    { 0x00009adc, 0x000000c6, 0x000000fd },
+    { 0x00009ae0, 0x000000c6, 0x000000fd },
+    { 0x00009ae4, 0x000000c6, 0x000000fd },
+    { 0x00009ae8, 0x000000c6, 0x000000fd },
+    { 0x00009aec, 0x000000c6, 0x000000fd },
+    { 0x00009af0, 0x000000c6, 0x000000fd },
+    { 0x00009af4, 0x000000c6, 0x000000fd },
+    { 0x00009af8, 0x000000c6, 0x000000fd },
+    { 0x00009afc, 0x000000c6, 0x000000fd },
+};
+#endif /* AH_5212_5111 */
+
+#ifdef AH_5212_5112
+static const uint32_t ar5212BB_RfGain_5112[][3] = {
+    { 0x00009a00, 0x00000007, 0x00000007 },
+    { 0x00009a04, 0x00000047, 0x00000047 },
+    { 0x00009a08, 0x00000087, 0x00000087 },
+    { 0x00009a0c, 0x000001a0, 0x000001a0 },
+    { 0x00009a10, 0x000001e0, 0x000001e0 },
+    { 0x00009a14, 0x00000020, 0x00000020 },
+    { 0x00009a18, 0x00000060, 0x00000060 },
+    { 0x00009a1c, 0x000001a1, 0x000001a1 },
+    { 0x00009a20, 0x000001e1, 0x000001e1 },
+    { 0x00009a24, 0x00000021, 0x00000021 },
+    { 0x00009a28, 0x00000061, 0x00000061 },
+    { 0x00009a2c, 0x00000162, 0x00000162 },
+    { 0x00009a30, 0x000001a2, 0x000001a2 },
+    { 0x00009a34, 0x000001e2, 0x000001e2 },
+    { 0x00009a38, 0x00000022, 0x00000022 },
+    { 0x00009a3c, 0x00000062, 0x00000062 },
+    { 0x00009a40, 0x00000163, 0x00000163 },
+    { 0x00009a44, 0x000001a3, 0x000001a3 },
+    { 0x00009a48, 0x000001e3, 0x000001e3 },
+    { 0x00009a4c, 0x00000023, 0x00000023 },
+    { 0x00009a50, 0x00000063, 0x00000063 },
+    { 0x00009a54, 0x00000184, 0x00000184 },
+    { 0x00009a58, 0x000001c4, 0x000001c4 },
+    { 0x00009a5c, 0x00000004, 0x00000004 },
+    { 0x00009a60, 0x000001ea, 0x0000000b },
+    { 0x00009a64, 0x0000002a, 0x0000004b },
+    { 0x00009a68, 0x0000006a, 0x0000008b },
+    { 0x00009a6c, 0x000000aa, 0x000001ac },
+    { 0x00009a70, 0x000001ab, 0x000001ec },
+    { 0x00009a74, 0x000001eb, 0x0000002c },
+    { 0x00009a78, 0x0000002b, 0x00000012 },
+    { 0x00009a7c, 0x0000006b, 0x00000052 },
+    { 0x00009a80, 0x000000ab, 0x00000092 },
+    { 0x00009a84, 0x000001ac, 0x00000193 },
+    { 0x00009a88, 0x000001ec, 0x000001d3 },
+    { 0x00009a8c, 0x0000002c, 0x00000013 },
+    { 0x00009a90, 0x0000003a, 0x00000053 },
+    { 0x00009a94, 0x0000007a, 0x00000093 },
+    { 0x00009a98, 0x000000ba, 0x00000194 },
+    { 0x00009a9c, 0x000001bb, 0x000001d4 },
+    { 0x00009aa0, 0x000001fb, 0x00000014 },
+    { 0x00009aa4, 0x0000003b, 0x0000003a },
+    { 0x00009aa8, 0x0000007b, 0x0000007a },
+    { 0x00009aac, 0x000000bb, 0x000000ba },
+    { 0x00009ab0, 0x000001bc, 0x000001bb },
+    { 0x00009ab4, 0x000001fc, 0x000001fb },
+    { 0x00009ab8, 0x0000003c, 0x0000003b },
+    { 0x00009abc, 0x0000007c, 0x0000007b },
+    { 0x00009ac0, 0x000000bc, 0x000000bb },
+    { 0x00009ac4, 0x000000fc, 0x000001bc },
+    { 0x00009ac8, 0x000000fc, 0x000001fc },
+    { 0x00009acc, 0x000000fc, 0x0000003c },
+    { 0x00009ad0, 0x000000fc, 0x0000007c },
+    { 0x00009ad4, 0x000000fc, 0x000000bc },
+    { 0x00009ad8, 0x000000fc, 0x000000fc },
+    { 0x00009adc, 0x000000fc, 0x000000fc },
+    { 0x00009ae0, 0x000000fc, 0x000000fc },
+    { 0x00009ae4, 0x000000fc, 0x000000fc },
+    { 0x00009ae8, 0x000000fc, 0x000000fc },
+    { 0x00009aec, 0x000000fc, 0x000000fc },
+    { 0x00009af0, 0x000000fc, 0x000000fc },
+    { 0x00009af4, 0x000000fc, 0x000000fc },
+    { 0x00009af8, 0x000000fc, 0x000000fc },
+    { 0x00009afc, 0x000000fc, 0x000000fc },
+};
+#endif /* AH_5212_5112 */
+
+#ifdef AH_5212_2413
+static const uint32_t ar5212BB_RfGain_2413[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000000, 0x00000040 },
+    { 0x00009a08, 0x00000000, 0x00000080 },
+    { 0x00009a0c, 0x00000000, 0x00000181 },
+    { 0x00009a10, 0x00000000, 0x000001c1 },
+    { 0x00009a14, 0x00000000, 0x00000001 },
+    { 0x00009a18, 0x00000000, 0x00000041 },
+    { 0x00009a1c, 0x00000000, 0x00000081 },
+    { 0x00009a20, 0x00000000, 0x00000168 },
+    { 0x00009a24, 0x00000000, 0x000001a8 },
+    { 0x00009a28, 0x00000000, 0x000001e8 },
+    { 0x00009a2c, 0x00000000, 0x00000028 },
+    { 0x00009a30, 0x00000000, 0x00000068 },
+    { 0x00009a34, 0x00000000, 0x00000189 },
+    { 0x00009a38, 0x00000000, 0x000001c9 },
+    { 0x00009a3c, 0x00000000, 0x00000009 },
+    { 0x00009a40, 0x00000000, 0x00000049 },
+    { 0x00009a44, 0x00000000, 0x00000089 },
+    { 0x00009a48, 0x00000000, 0x00000190 },
+    { 0x00009a4c, 0x00000000, 0x000001d0 },
+    { 0x00009a50, 0x00000000, 0x00000010 },
+    { 0x00009a54, 0x00000000, 0x00000050 },
+    { 0x00009a58, 0x00000000, 0x00000090 },
+    { 0x00009a5c, 0x00000000, 0x00000191 },
+    { 0x00009a60, 0x00000000, 0x000001d1 },
+    { 0x00009a64, 0x00000000, 0x00000011 },
+    { 0x00009a68, 0x00000000, 0x00000051 },
+    { 0x00009a6c, 0x00000000, 0x00000091 },
+    { 0x00009a70, 0x00000000, 0x00000178 },
+    { 0x00009a74, 0x00000000, 0x000001b8 },
+    { 0x00009a78, 0x00000000, 0x000001f8 },
+    { 0x00009a7c, 0x00000000, 0x00000038 },
+    { 0x00009a80, 0x00000000, 0x00000078 },
+    { 0x00009a84, 0x00000000, 0x00000199 },
+    { 0x00009a88, 0x00000000, 0x000001d9 },
+    { 0x00009a8c, 0x00000000, 0x00000019 },
+    { 0x00009a90, 0x00000000, 0x00000059 },
+    { 0x00009a94, 0x00000000, 0x00000099 },
+    { 0x00009a98, 0x00000000, 0x000000d9 },
+    { 0x00009a9c, 0x00000000, 0x000000f9 },
+    { 0x00009aa0, 0x00000000, 0x000000f9 },
+    { 0x00009aa4, 0x00000000, 0x000000f9 },
+    { 0x00009aa8, 0x00000000, 0x000000f9 },
+    { 0x00009aac, 0x00000000, 0x000000f9 },
+    { 0x00009ab0, 0x00000000, 0x000000f9 },
+    { 0x00009ab4, 0x00000000, 0x000000f9 },
+    { 0x00009ab8, 0x00000000, 0x000000f9 },
+    { 0x00009abc, 0x00000000, 0x000000f9 },
+    { 0x00009ac0, 0x00000000, 0x000000f9 },
+    { 0x00009ac4, 0x00000000, 0x000000f9 },
+    { 0x00009ac8, 0x00000000, 0x000000f9 },
+    { 0x00009acc, 0x00000000, 0x000000f9 },
+    { 0x00009ad0, 0x00000000, 0x000000f9 },
+    { 0x00009ad4, 0x00000000, 0x000000f9 },
+    { 0x00009ad8, 0x00000000, 0x000000f9 },
+    { 0x00009adc, 0x00000000, 0x000000f9 },
+    { 0x00009ae0, 0x00000000, 0x000000f9 },
+    { 0x00009ae4, 0x00000000, 0x000000f9 },
+    { 0x00009ae8, 0x00000000, 0x000000f9 },
+    { 0x00009aec, 0x00000000, 0x000000f9 },
+    { 0x00009af0, 0x00000000, 0x000000f9 },
+    { 0x00009af4, 0x00000000, 0x000000f9 },
+    { 0x00009af8, 0x00000000, 0x000000f9 },
+    { 0x00009afc, 0x00000000, 0x000000f9 },
+};
+#endif /* AH_5212_2413 */
+
+#ifdef AH_5212_2316
+static const uint32_t ar5212BB_RfGain_2316[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000000, 0x00000040 },
+    { 0x00009a08, 0x00000000, 0x00000080 },
+    { 0x00009a0c, 0x00000000, 0x00000161 },
+    { 0x00009a10, 0x00000000, 0x000001a1 },
+    { 0x00009a14, 0x00000000, 0x000001e1 },
+    { 0x00009a18, 0x00000000, 0x00000021 },
+    { 0x00009a1c, 0x00000000, 0x00000061 },
+    { 0x00009a20, 0x00000000, 0x000000a1 },
+    { 0x00009a24, 0x00000000, 0x00000168 },
+    { 0x00009a28, 0x00000000, 0x000001a8 },
+    { 0x00009a2c, 0x00000000, 0x000001e8 },
+    { 0x00009a30, 0x00000000, 0x00000028 },
+    { 0x00009a34, 0x00000000, 0x00000068 },
+    { 0x00009a38, 0x00000000, 0x000000a8 },
+    { 0x00009a3c, 0x00000000, 0x00000189 },
+    { 0x00009a40, 0x00000000, 0x000001c9 },
+    { 0x00009a44, 0x00000000, 0x00000009 },
+    { 0x00009a48, 0x00000000, 0x00000049 },
+    { 0x00009a4c, 0x00000000, 0x00000089 },
+    { 0x00009a50, 0x00000000, 0x000001b0 },
+    { 0x00009a54, 0x00000000, 0x000001f0 },
+    { 0x00009a58, 0x00000000, 0x00000030 },
+    { 0x00009a5c, 0x00000000, 0x00000070 },
+    { 0x00009a60, 0x00000000, 0x000000b0 },
+    { 0x00009a64, 0x00000000, 0x000001b1 },
+    { 0x00009a68, 0x00000000, 0x000001f1 },
+    { 0x00009a6c, 0x00000000, 0x00000031 },
+    { 0x00009a70, 0x00000000, 0x00000071 },
+    { 0x00009a74, 0x00000000, 0x00000198 },
+    { 0x00009a78, 0x00000000, 0x000001d8 },
+    { 0x00009a7c, 0x00000000, 0x00000018 },
+    { 0x00009a80, 0x00000000, 0x00000058 },
+    { 0x00009a84, 0x00000000, 0x00000098 },
+    { 0x00009a88, 0x00000000, 0x00000199 },
+    { 0x00009a8c, 0x00000000, 0x000001d9 },
+    { 0x00009a90, 0x00000000, 0x00000019 },
+    { 0x00009a94, 0x00000000, 0x00000059 },
+    { 0x00009a98, 0x00000000, 0x00000099 },
+    { 0x00009a9c, 0x00000000, 0x000000d9 },
+    { 0x00009aa0, 0x00000000, 0x000000f9 },
+    { 0x00009aa4, 0x00000000, 0x000000f9 },
+    { 0x00009aa8, 0x00000000, 0x000000f9 },
+    { 0x00009aac, 0x00000000, 0x000000f9 },
+    { 0x00009ab0, 0x00000000, 0x000000f9 },
+    { 0x00009ab4, 0x00000000, 0x000000f9 },
+    { 0x00009ab8, 0x00000000, 0x000000f9 },
+    { 0x00009abc, 0x00000000, 0x000000f9 },
+    { 0x00009ac0, 0x00000000, 0x000000f9 },
+    { 0x00009ac4, 0x00000000, 0x000000f9 },
+    { 0x00009ac8, 0x00000000, 0x000000f9 },
+    { 0x00009acc, 0x00000000, 0x000000f9 },
+    { 0x00009ad0, 0x00000000, 0x000000f9 },
+    { 0x00009ad4, 0x00000000, 0x000000f9 },
+    { 0x00009ad8, 0x00000000, 0x000000f9 },
+    { 0x00009adc, 0x00000000, 0x000000f9 },
+    { 0x00009ae0, 0x00000000, 0x000000f9 },
+    { 0x00009ae4, 0x00000000, 0x000000f9 },
+    { 0x00009ae8, 0x00000000, 0x000000f9 },
+    { 0x00009aec, 0x00000000, 0x000000f9 },
+    { 0x00009af0, 0x00000000, 0x000000f9 },
+    { 0x00009af4, 0x00000000, 0x000000f9 },
+    { 0x00009af8, 0x00000000, 0x000000f9 },
+    { 0x00009afc, 0x00000000, 0x000000f9 },
+};
+#endif
+
+#ifdef AH_5212_5413
+static const uint32_t ar5212BB_RfGain_5413[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000040, 0x00000040 },
+    { 0x00009a08, 0x00000080, 0x00000080 },
+    { 0x00009a0c, 0x000001a1, 0x00000161 },
+    { 0x00009a10, 0x000001e1, 0x000001a1 },
+    { 0x00009a14, 0x00000021, 0x000001e1 },
+    { 0x00009a18, 0x00000061, 0x00000021 },
+    { 0x00009a1c, 0x00000188, 0x00000061 },
+    { 0x00009a20, 0x000001c8, 0x00000188 },
+    { 0x00009a24, 0x00000008, 0x000001c8 },
+    { 0x00009a28, 0x00000048, 0x00000008 },
+    { 0x00009a2c, 0x00000088, 0x00000048 },
+    { 0x00009a30, 0x000001a9, 0x00000088 },
+    { 0x00009a34, 0x000001e9, 0x00000169 },
+    { 0x00009a38, 0x00000029, 0x000001a9 },
+    { 0x00009a3c, 0x00000069, 0x000001e9 },
+    { 0x00009a40, 0x000001d0, 0x00000029 },
+    { 0x00009a44, 0x00000010, 0x00000069 },
+    { 0x00009a48, 0x00000050, 0x00000190 },
+    { 0x00009a4c, 0x00000090, 0x000001d0 },
+    { 0x00009a50, 0x000001b1, 0x00000010 },
+    { 0x00009a54, 0x000001f1, 0x00000050 },
+    { 0x00009a58, 0x00000031, 0x00000090 },
+    { 0x00009a5c, 0x00000071, 0x00000171 },
+    { 0x00009a60, 0x000001b8, 0x000001b1 },
+    { 0x00009a64, 0x000001f8, 0x000001f1 },
+    { 0x00009a68, 0x00000038, 0x00000031 },
+    { 0x00009a6c, 0x00000078, 0x00000071 },
+    { 0x00009a70, 0x00000199, 0x00000198 },
+    { 0x00009a74, 0x000001d9, 0x000001d8 },
+    { 0x00009a78, 0x00000019, 0x00000018 },
+    { 0x00009a7c, 0x00000059, 0x00000058 },
+    { 0x00009a80, 0x00000099, 0x00000098 },
+    { 0x00009a84, 0x000000d9, 0x00000179 },
+    { 0x00009a88, 0x000000f9, 0x000001b9 },
+    { 0x00009a8c, 0x000000f9, 0x000001f9 },
+    { 0x00009a90, 0x000000f9, 0x00000039 },
+    { 0x00009a94, 0x000000f9, 0x00000079 },
+    { 0x00009a98, 0x000000f9, 0x000000b9 },
+    { 0x00009a9c, 0x000000f9, 0x000000f9 },
+    { 0x00009aa0, 0x000000f9, 0x000000f9 },
+    { 0x00009aa4, 0x000000f9, 0x000000f9 },
+    { 0x00009aa8, 0x000000f9, 0x000000f9 },
+    { 0x00009aac, 0x000000f9, 0x000000f9 },
+    { 0x00009ab0, 0x000000f9, 0x000000f9 },
+    { 0x00009ab4, 0x000000f9, 0x000000f9 },
+    { 0x00009ab8, 0x000000f9, 0x000000f9 },
+    { 0x00009abc, 0x000000f9, 0x000000f9 },
+    { 0x00009ac0, 0x000000f9, 0x000000f9 },
+    { 0x00009ac4, 0x000000f9, 0x000000f9 },
+    { 0x00009ac8, 0x000000f9, 0x000000f9 },
+    { 0x00009acc, 0x000000f9, 0x000000f9 },
+    { 0x00009ad0, 0x000000f9, 0x000000f9 },
+    { 0x00009ad4, 0x000000f9, 0x000000f9 },
+    { 0x00009ad8, 0x000000f9, 0x000000f9 },
+    { 0x00009adc, 0x000000f9, 0x000000f9 },
+    { 0x00009ae0, 0x000000f9, 0x000000f9 },
+    { 0x00009ae4, 0x000000f9, 0x000000f9 },
+    { 0x00009ae8, 0x000000f9, 0x000000f9 },
+    { 0x00009aec, 0x000000f9, 0x000000f9 },
+    { 0x00009af0, 0x000000f9, 0x000000f9 },
+    { 0x00009af4, 0x000000f9, 0x000000f9 },
+    { 0x00009af8, 0x000000f9, 0x000000f9 },
+    { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+#endif /* AH_5212_5413 */
+
+#ifdef AH_5212_2425
+static const uint32_t ar5212BB_RfGain_2425[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000000, 0x00000040 },
+    { 0x00009a08, 0x00000000, 0x00000080 },
+    { 0x00009a0c, 0x00000000, 0x00000181 },
+    { 0x00009a10, 0x00000000, 0x000001c1 },
+    { 0x00009a14, 0x00000000, 0x00000001 },
+    { 0x00009a18, 0x00000000, 0x00000041 },
+    { 0x00009a1c, 0x00000000, 0x00000081 },
+    { 0x00009a20, 0x00000000, 0x00000188 },
+    { 0x00009a24, 0x00000000, 0x000001c8 },
+    { 0x00009a28, 0x00000000, 0x00000008 },
+    { 0x00009a2c, 0x00000000, 0x00000048 },
+    { 0x00009a30, 0x00000000, 0x00000088 },
+    { 0x00009a34, 0x00000000, 0x00000189 },
+    { 0x00009a38, 0x00000000, 0x000001c9 },
+    { 0x00009a3c, 0x00000000, 0x00000009 },
+    { 0x00009a40, 0x00000000, 0x00000049 },
+    { 0x00009a44, 0x00000000, 0x00000089 },
+    { 0x00009a48, 0x00000000, 0x000001b0 },
+    { 0x00009a4c, 0x00000000, 0x000001f0 },
+    { 0x00009a50, 0x00000000, 0x00000030 },
+    { 0x00009a54, 0x00000000, 0x00000070 },
+    { 0x00009a58, 0x00000000, 0x00000171 },
+    { 0x00009a5c, 0x00000000, 0x000001b1 },
+    { 0x00009a60, 0x00000000, 0x000001f1 },
+    { 0x00009a64, 0x00000000, 0x00000031 },
+    { 0x00009a68, 0x00000000, 0x00000071 },
+    { 0x00009a6c, 0x00000000, 0x000001b8 },
+    { 0x00009a70, 0x00000000, 0x000001f8 },
+    { 0x00009a74, 0x00000000, 0x00000038 },
+    { 0x00009a78, 0x00000000, 0x00000078 },
+    { 0x00009a7c, 0x00000000, 0x000000b8 },
+    { 0x00009a80, 0x00000000, 0x000001b9 },
+    { 0x00009a84, 0x00000000, 0x000001f9 },
+    { 0x00009a88, 0x00000000, 0x00000039 },
+    { 0x00009a8c, 0x00000000, 0x00000079 },
+    { 0x00009a90, 0x00000000, 0x000000b9 },
+    { 0x00009a94, 0x00000000, 0x000000f9 },
+    { 0x00009a98, 0x00000000, 0x000000f9 },
+    { 0x00009a9c, 0x00000000, 0x000000f9 },
+    { 0x00009aa0, 0x00000000, 0x000000f9 },
+    { 0x00009aa4, 0x00000000, 0x000000f9 },
+    { 0x00009aa8, 0x00000000, 0x000000f9 },
+    { 0x00009aac, 0x00000000, 0x000000f9 },
+    { 0x00009ab0, 0x00000000, 0x000000f9 },
+    { 0x00009ab4, 0x00000000, 0x000000f9 },
+    { 0x00009ab8, 0x00000000, 0x000000f9 },
+    { 0x00009abc, 0x00000000, 0x000000f9 },
+    { 0x00009ac0, 0x00000000, 0x000000f9 },
+    { 0x00009ac4, 0x00000000, 0x000000f9 },
+    { 0x00009ac8, 0x00000000, 0x000000f9 },
+    { 0x00009acc, 0x00000000, 0x000000f9 },
+    { 0x00009ad0, 0x00000000, 0x000000f9 },
+    { 0x00009ad4, 0x00000000, 0x000000f9 },
+    { 0x00009ad8, 0x00000000, 0x000000f9 },
+    { 0x00009adc, 0x00000000, 0x000000f9 },
+    { 0x00009ae0, 0x00000000, 0x000000f9 },
+    { 0x00009ae4, 0x00000000, 0x000000f9 },
+    { 0x00009ae8, 0x00000000, 0x000000f9 },
+    { 0x00009aec, 0x00000000, 0x000000f9 },
+    { 0x00009af0, 0x00000000, 0x000000f9 },
+    { 0x00009af4, 0x00000000, 0x000000f9 },
+    { 0x00009af8, 0x00000000, 0x000000f9 },
+    { 0x00009afc, 0x00000000, 0x000000f9 },
+};
+#endif /* AH_5212_2425 */
+
+#ifdef AH_5212_5111
+static const uint32_t ar5212Bank1_5111[][2] = {
+    { 0x000098d4, 0x00000020 },
+};
+#endif /* AH_5212_5111 */
+
+#ifdef AH_5212_5112
+static const uint32_t ar5212Bank1_5112[][2] = {
+    { 0x000098d4, 0x00000020 },
+};
+#endif /* AH_5212_5112 */
+
+#ifdef AH_5212_2413
+static const uint32_t ar5212Bank1_2413[][2] = {
+    { 0x000098d4, 0x00000020 },
+};
+#endif /* AH_5212_2413 */
+
+#ifdef AH_5212_2316
+static const uint32_t ar5212Bank1_2316[][2] = {
+    { 0x000098d4, 0x00000020 },
+};
+#endif
+
+#ifdef AH_5212_5413
+static const uint32_t ar5212Bank1_5413[][2] = {
+    { 0x000098d4, 0x00000020 },
+};
+#endif /* AH_5212_5413 */
+
+#ifdef AH_5212_2425
+static const uint32_t ar5212Bank1_2425[][2] = {
+    { 0x000098d4, 0x00000020 },
+};
+#endif /* AH_5212_2425 */
+
+#ifdef AH_5212_5111
+static const uint32_t ar5212Bank2_5111[][6] = {
+    { 0x000098d4, 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 },
+};
+#endif /* AH_5212_5111 */
+
+#ifdef AH_5212_5112
+static const uint32_t ar5212Bank2_5112[][6] = {
+    { 0x000098d0, 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 },
+};
+#endif /* AH_5212_5112 */
+
+#ifdef AH_5212_2413
+static const uint32_t ar5212Bank2_2413[][6] = {
+    { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 },
+};
+#endif /* AH_5212_2413 */
+
+#ifdef AH_5212_2316
+static const uint32_t ar5212Bank2_2316[][6] = {
+    { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 },
+};
+#endif
+
+#ifdef AH_5212_5413
+static const uint32_t ar5212Bank2_5413[][6] = {
+    { 0x000098d0, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 },
+};
+#endif /* AH_5212_5413 */
+
+#ifdef AH_5212_2425
+static const uint32_t ar5212Bank2_2425[][6] = {
+    { 0x000098d0, 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 },
+};
+#endif /* AH_5212_2425 */
+
+#ifdef AH_5212_5111
+static const uint32_t ar5212Bank3_5111[][6] = {
+    { 0x000098d8, 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 },
+};
+#endif /* AH_5212_5111 */
+
+#ifdef AH_5212_5112
+static const uint32_t ar5212Bank3_5112[][6] = {
+    { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 },
+};
+#endif /* AH_5212_5112 */
+
+#ifdef AH_5212_2413
+static const uint32_t ar5212Bank3_2413[][6] = {
+    { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 },
+};
+#endif /* AH_5212_2413 */
+
+#ifdef AH_5212_2316
+static const uint32_t ar5212Bank3_2316[][6] = {
+    { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 },
+};
+#endif
+
+#ifdef AH_5212_5413
+static const uint32_t ar5212Bank3_5413[][6] = {
+    { 0x000098dc, 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 },
+};
+#endif /* AH_5212_5413 */
+
+#ifdef AH_5212_2425
+static const uint32_t ar5212Bank3_2425[][6] = {
+    { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 },
+};
+#endif /* AH_5212_2425 */
+
+#ifdef AH_5212_5111
+static const uint32_t ar5212Bank6_5111[][6] = {
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 },
+    { 0x0000989c, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 },
+    { 0x0000989c, 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 },
+    { 0x0000989c, 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 },
+    { 0x0000989c, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 },
+    { 0x0000989c, 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 },
+    { 0x000098d4, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a },
+};
+#endif /* AH_5212_5111 */
+
+#ifdef AH_5212_5112
+static const uint32_t ar5212Bank6_5112[][6] = {
+    { 0x0000989c, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 },
+    { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 },
+    { 0x0000989c, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 },
+    { 0x0000989c, 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 },
+    { 0x0000989c, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 },
+    { 0x0000989c, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 },
+    { 0x0000989c, 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 },
+    { 0x0000989c, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 },
+    { 0x0000989c, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 },
+    { 0x0000989c, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 },
+    { 0x0000989c, 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 },
+    { 0x0000989c, 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 },
+    { 0x0000989c, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 },
+    { 0x0000989c, 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 },
+    { 0x0000989c, 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 },
+    { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 },
+    { 0x0000989c, 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 },
+    { 0x0000989c, 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 },
+    { 0x0000989c, 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 },
+    { 0x0000989c, 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 },
+    { 0x0000989c, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 },
+    { 0x0000989c, 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 },
+    { 0x0000989c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 },
+    { 0x0000989c, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 },
+    { 0x0000989c, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 },
+    { 0x0000989c, 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 },
+    { 0x0000989c, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 },
+    { 0x000098d8, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 },
+};
+#endif /* AH_5212_5112 */
+
+#ifdef AH_5212_2413
+static const uint32_t ar5212Bank6_2413[][6] = {
+    { 0x0000989c, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 },
+    { 0x0000989c, 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 },
+    { 0x0000989c, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 },
+    { 0x0000989c, 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 },
+    { 0x0000989c, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 },
+    { 0x0000989c, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 },
+    { 0x0000989c, 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 },
+    { 0x0000989c, 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 },
+    { 0x0000989c, 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 },
+    { 0x0000989c, 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 },
+    { 0x0000989c, 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 },
+    { 0x0000989c, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f },
+    { 0x0000989c, 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 },
+    { 0x000098d8, 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 },
+};
+#endif /* AH_5212_2413 */
+
+#ifdef AH_5212_2316
+static const uint32_t ar5212Bank6_2316[][6] = {
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 },
+    { 0x0000989c, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 },
+    { 0x0000989c, 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 },
+    { 0x0000989c, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 },
+    { 0x0000989c, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 },
+    { 0x0000989c, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 },
+    { 0x0000989c, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 },
+    { 0x0000989c, 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 },
+    { 0x0000989c, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 },
+    { 0x0000989c, 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 },
+    { 0x0000989c, 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d },
+    { 0x0000989c, 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 },
+    { 0x0000989c, 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 },
+    { 0x0000989c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 },
+    { 0x0000989c, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 },
+    { 0x0000989c, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 },
+    { 0x000098c0, 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 },
+};
+#endif
+
+#ifdef AH_5212_5413
+static const uint32_t ar5212Bank6_5413[][6] = {
+    { 0x0000989c, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 },
+    { 0x0000989c, 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 },
+    { 0x0000989c, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 },
+    { 0x0000989c, 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 },
+    { 0x0000989c, 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 },
+    { 0x0000989c, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 },
+    { 0x0000989c, 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 },
+    { 0x0000989c, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 },
+    { 0x0000989c, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 },
+    { 0x0000989c, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 },
+    { 0x0000989c, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 },
+    { 0x0000989c, 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 },
+    { 0x0000989c, 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 },
+    { 0x0000989c, 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 },
+    { 0x0000989c, 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 },
+    { 0x0000989c, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 },
+    { 0x0000989c, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 },
+    { 0x0000989c, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f },
+    { 0x0000989c, 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 },
+    { 0x0000989c, 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 },
+    { 0x0000989c, 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 },
+    { 0x000098c8, 0x00000403, 0x00000403, 0x00000403, 0x00000403, 0x00000403 },
+};
+#endif /* AH_5212_5413 */
+
+#ifdef AH_5212_2425
+static const uint32_t ar5212Bank6_2425[][6] = {
+    { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 },
+    { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 },
+    { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 },
+    { 0x0000989c, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 },
+    { 0x0000989c, 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 },
+    { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 },
+    { 0x0000989c, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a },
+    { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 },
+    { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 },
+    { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 },
+    { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 },
+    { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 },
+};
+#endif /* AH_5212_2425 */
+
+#ifdef AH_5212_2417
+static const uint32_t ar5212Bank6_2417[][6] = {
+    { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 },
+    { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 },
+    { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 },
+    { 0x0000989c, 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 },
+    { 0x0000989c, 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 },
+    { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 },
+    { 0x0000989c, 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a },
+    { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 },
+    { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 },
+    { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 },
+    { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 },
+    { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 },
+};
+#endif /* AH_5212_2417 */
+
+#ifdef AH_5212_5111
+static const uint32_t ar5212Bank7_5111[][6] = {
+    { 0x0000989c, 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 },
+    { 0x0000989c, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+    { 0x0000989c, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 },
+    { 0x0000989c, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f },
+    { 0x0000989c, 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 },
+    { 0x0000989c, 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f },
+    { 0x0000989c, 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a },
+    { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e },
+};
+#endif /* AH_5212_5111 */
+
+#ifdef AH_5212_5112
+static const uint32_t ar5212Bank7_5112[][6] = {
+    { 0x0000989c, 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 },
+    { 0x0000989c, 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 },
+    { 0x0000989c, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 },
+    { 0x0000989c, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 },
+    { 0x0000989c, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 },
+    { 0x0000989c, 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 },
+    { 0x0000989c, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 },
+    { 0x0000989c, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 },
+    { 0x0000989c, 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 },
+    { 0x0000989c, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 },
+    { 0x0000989c, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc },
+    { 0x0000989c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c },
+    { 0x000098c4, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 },
+};
+#endif /* AH_5212_5112 */
+
+#ifdef AH_5212_2413
+static const uint32_t ar5212Bank7_2413[][6] = {
+    { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 },
+    { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 },
+    { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e },
+};
+#endif /* AH_5212_2413 */
+
+#ifdef AH_5212_2316
+static const uint32_t ar5212Bank7_2316[][6] = {
+    { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 },
+    { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 },
+    { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e },
+};
+#endif
+
+#ifdef AH_5212_5413
+static const uint32_t ar5212Bank7_5413[][6] = {
+    { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 },
+    { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 },
+    { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e },
+};
+#endif /* AH_5212_5413 */
+
+#ifdef AH_5212_2317
+static const uint32_t ar5212Modes_2317[][6] = {
+    { 0x00000030, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 },
+    { 0x0000801c, 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 },
+    { 0x00009838, 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a },
+    { 0x00009848, 0x0018da6d, 0x0018da6d, 0x001a6a67, 0x001a6a67, 0x001a6a67 },
+    { 0x00009850, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da },
+    { 0x00009858, 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e },
+    { 0x0000985c, 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 },
+    { 0x00009944, 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 },
+    { 0x0000a204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a208, 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 },
+    { 0x0000a20c, 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a },
+};
+
+static const uint32_t ar5212Common_2317[][2] = {
+    { 0x00001230, 0x000003e0 },
+    { 0x00008060, 0x0000000f },
+    { 0x00008118, 0x00000000 },
+    { 0x0000811c, 0x00000000 },
+    { 0x00008120, 0x00000000 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008140, 0x800000a8 },
+    { 0x00008144, 0x00000000 },
+    { 0x00009808, 0x00004000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009870, 0x0000001f },
+    { 0x00009874, 0x00000080 },
+    { 0x00009878, 0x0000000e },
+    { 0x00009958, 0x000000ff },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x02800000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099e0, 0x00000001 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x000000aa },
+    { 0x000099f0, 0x0000000c },
+    { 0x000099f4, 0x000000ff },
+    { 0x000099f8, 0x00000014 },
+    { 0x0000a228, 0x000009b5 },
+    { 0x0000a23c, 0x93c889af },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0x5f690f01 },
+    { 0x0000a264, 0x00418a11 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0c30c16a },
+    { 0x0000a270, 0x00820820 },
+    { 0x0000a274, 0x081a3caa },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x051701ce },
+    { 0x0000a300, 0x16010000 },
+    { 0x0000a304, 0x2c032402 },
+    { 0x0000a308, 0x48433e42 },
+    { 0x0000a30c, 0x5a0f500b },
+    { 0x0000a310, 0x6c4b624a },
+    { 0x0000a314, 0x7e8b748a },
+    { 0x0000a318, 0x96cf8ccb },
+    { 0x0000a31c, 0xa34f9d0f },
+    { 0x0000a320, 0xa7cfa58f },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa1f },
+    { 0x0000a35c, 0x066c420f },
+    { 0x0000a360, 0x0f282207 },
+    { 0x0000a364, 0x17601685 },
+    { 0x0000a368, 0x1f801104 },
+    { 0x0000a36c, 0x37a00c03 },
+    { 0x0000a370, 0x3fc40883 },
+    { 0x0000a374, 0x57c00803 },
+    { 0x0000a378, 0x5fd80682 },
+    { 0x0000a37c, 0x7fe00482 },
+    { 0x0000a380, 0x7f3c7bba },
+    { 0x0000a384, 0xf3307ff0 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+};
+
+static const uint32_t ar5212BB_RfGain_2317[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000000, 0x00000040 },
+    { 0x00009a08, 0x00000000, 0x00000080 },
+    { 0x00009a0c, 0x00000000, 0x00000181 },
+    { 0x00009a10, 0x00000000, 0x000001c1 },
+    { 0x00009a14, 0x00000000, 0x00000001 },
+    { 0x00009a18, 0x00000000, 0x00000041 },
+    { 0x00009a1c, 0x00000000, 0x00000081 },
+    { 0x00009a20, 0x00000000, 0x00000188 },
+    { 0x00009a24, 0x00000000, 0x000001c8 },
+    { 0x00009a28, 0x00000000, 0x00000008 },
+    { 0x00009a2c, 0x00000000, 0x00000048 },
+    { 0x00009a30, 0x00000000, 0x00000088 },
+    { 0x00009a34, 0x00000000, 0x00000189 },
+    { 0x00009a38, 0x00000000, 0x000001c9 },
+    { 0x00009a3c, 0x00000000, 0x00000009 },
+    { 0x00009a40, 0x00000000, 0x00000049 },
+    { 0x00009a44, 0x00000000, 0x00000089 },
+    { 0x00009a48, 0x00000000, 0x00000190 },
+    { 0x00009a4c, 0x00000000, 0x000001d0 },
+    { 0x00009a50, 0x00000000, 0x00000010 },
+    { 0x00009a54, 0x00000000, 0x00000050 },
+    { 0x00009a58, 0x00000000, 0x00000090 },
+    { 0x00009a5c, 0x00000000, 0x00000191 },
+    { 0x00009a60, 0x00000000, 0x000001d1 },
+    { 0x00009a64, 0x00000000, 0x00000011 },
+    { 0x00009a68, 0x00000000, 0x00000051 },
+    { 0x00009a6c, 0x00000000, 0x00000091 },
+    { 0x00009a70, 0x00000000, 0x00000178 },
+    { 0x00009a74, 0x00000000, 0x000001b8 },
+    { 0x00009a78, 0x00000000, 0x000001f8 },
+    { 0x00009a7c, 0x00000000, 0x00000038 },
+    { 0x00009a80, 0x00000000, 0x00000078 },
+    { 0x00009a84, 0x00000000, 0x00000179 },
+    { 0x00009a88, 0x00000000, 0x000001b9 },
+    { 0x00009a8c, 0x00000000, 0x000001f9 },
+    { 0x00009a90, 0x00000000, 0x00000039 },
+    { 0x00009a94, 0x00000000, 0x00000079 },
+    { 0x00009a98, 0x00000000, 0x000000b9 },
+    { 0x00009a9c, 0x00000000, 0x000000f9 },
+    { 0x00009aa0, 0x00000000, 0x000000f9 },
+    { 0x00009aa4, 0x00000000, 0x000000f9 },
+    { 0x00009aa8, 0x00000000, 0x000000f9 },
+    { 0x00009aac, 0x00000000, 0x000000f9 },
+    { 0x00009ab0, 0x00000000, 0x000000f9 },
+    { 0x00009ab4, 0x00000000, 0x000000f9 },
+    { 0x00009ab8, 0x00000000, 0x000000f9 },
+    { 0x00009abc, 0x00000000, 0x000000f9 },
+    { 0x00009ac0, 0x00000000, 0x000000f9 },
+    { 0x00009ac4, 0x00000000, 0x000000f9 },
+    { 0x00009ac8, 0x00000000, 0x000000f9 },
+    { 0x00009acc, 0x00000000, 0x000000f9 },
+    { 0x00009ad0, 0x00000000, 0x000000f9 },
+    { 0x00009ad4, 0x00000000, 0x000000f9 },
+    { 0x00009ad8, 0x00000000, 0x000000f9 },
+    { 0x00009adc, 0x00000000, 0x000000f9 },
+    { 0x00009ae0, 0x00000000, 0x000000f9 },
+    { 0x00009ae4, 0x00000000, 0x000000f9 },
+    { 0x00009ae8, 0x00000000, 0x000000f9 },
+    { 0x00009aec, 0x00000000, 0x000000f9 },
+    { 0x00009af0, 0x00000000, 0x000000f9 },
+    { 0x00009af4, 0x00000000, 0x000000f9 },
+    { 0x00009af8, 0x00000000, 0x000000f9 },
+    { 0x00009afc, 0x00000000, 0x000000f9 },
+};
+
+static const uint32_t ar5212Bank1_2317[][2] = {
+    { 0x000098d4, 0x00000020 },
+};
+
+static const uint32_t ar5212Bank2_2317[][6] = {
+    { 0x000098d0, 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 },
+};
+
+static const uint32_t ar5212Bank3_2317[][6] = {
+    { 0x000098dc, 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 },
+};
+
+static const uint32_t ar5212Bank6_2317[][6] = {
+    { 0x0000989c, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 },
+    { 0x0000989c, 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 },
+    { 0x0000989c, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 },
+    { 0x0000989c, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 },
+    { 0x0000989c, 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 },
+    { 0x0000989c, 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 },
+    { 0x0000989c, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a },
+    { 0x0000989c, 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 },
+    { 0x0000989c, 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 },
+    { 0x0000989c, 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 },
+    { 0x0000989c, 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 },
+    { 0x000098c4, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 },
+};
+
+static const uint32_t ar5212Bank7_2317[][6] = {
+    { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 },
+    { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 },
+    { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e },
+};
+#endif /* AH_5212_2317 */
+
+#ifdef AH_5212_2425
+static const uint32_t ar5212Bank7_2425[][6] = {
+    { 0x0000989c, 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 },
+    { 0x0000989c, 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 },
+    { 0x000098cc, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e },
+};
+#endif /* AH_5212_2425 */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_ani.c       2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,1016 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_ani.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+/*
+ * Anti noise immunity support.  We track phy errors and react
+ * to excessive errors by adjusting the noise immunity parameters.
+ */
+
+#define HAL_EP_RND(x, mul) \
+       ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+#define        BEACON_RSSI(ahp) \
+       HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \
+               HAL_RSSI_EP_MULTIPLIER)
+
+/*
+ * ANI processing tunes radio parameters according to PHY errors
+ * and related information.  This is done for for noise and spur
+ * immunity in all operating modes if the device indicates it's
+ * capable at attach time.  In addition, when there is a reference
+ * rssi value (e.g. beacon frames from an ap in station mode)
+ * further tuning is done.
+ *
+ * ANI_ENA indicates whether any ANI processing should be done;
+ * this is specified at attach time.
+ *
+ * ANI_ENA_RSSI indicates whether rssi-based processing should
+ * done, this is enabled based on operating mode and is meaningful
+ * only if ANI_ENA is true.
+ *
+ * ANI parameters are typically controlled only by the hal.  The
+ * AniControl interface however permits manual tuning through the
+ * diagnostic api.
+ */
+#define ANI_ENA(ah) \
+       (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA)
+#define ANI_ENA_RSSI(ah) \
+       (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA)
+
+#define        ah_mibStats     ah_stats.ast_mibstats
+
+static void
+enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: "
+           "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n",
+           __func__, params->ofdmPhyErrBase, params->cckPhyErrBase);
+
+       OS_REG_WRITE(ah, AR_FILTOFDM, 0);
+       OS_REG_WRITE(ah, AR_FILTCCK, 0);
+
+       OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);
+       OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);
+
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/
+       ar5212EnableMibCounters(ah);                    /* enable everything */
+}
+
+static void
+disableAniMIBCounters(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n");
+
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */
+       ar5212DisableMibCounters(ah);                   /* disable everything */
+
+       OS_REG_WRITE(ah, AR_PHYCNTMASK1, 0);
+       OS_REG_WRITE(ah, AR_PHYCNTMASK2, 0);
+}
+
+/*
+ * This routine returns the index into the aniState array that
+ * corresponds to the channel in *chan.  If no match is found and the
+ * array is still not fully utilized, a new entry is created for the
+ * channel.  We assume the attach function has already initialized the
+ * ah_ani values and only the channel field needs to be set.
+ */
+static int
+ar5212GetAniChannelIndex(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+#define N(a)     (sizeof(a) / sizeof(a[0]))
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       int i;
+
+       for (i = 0; i < N(ahp->ah_ani); i++) {
+               struct ar5212AniState *asp = &ahp->ah_ani[i];
+               if (asp->c.channel == chan->channel)
+                       return i;
+               if (asp->c.channel == 0) {
+                       asp->c.channel = chan->channel;
+                       asp->c.channelFlags = chan->channelFlags;
+                       asp->c.privFlags = chan->privFlags;
+                       asp->isSetup = AH_FALSE;
+                       if (IS_CHAN_2GHZ(chan))
+                               asp->params = &ahp->ah_aniParams24;
+                       else
+                               asp->params = &ahp->ah_aniParams5;
+                       return i;
+               }
+       }
+       /* XXX statistic */
+       HALDEBUG(ah, HAL_DEBUG_ANY,
+           "No more channel states left. Using channel 0\n");
+       return 0;               /* XXX gotta return something valid */
+#undef N
+}
+
+/*
+ * Return the current ANI state of the channel we're on
+ */
+struct ar5212AniState *
+ar5212AniGetCurrentState(struct ath_hal *ah)
+{
+       return AH5212(ah)->ah_curani;
+}
+
+/*
+ * Return the current statistics.
+ */
+struct ar5212Stats *
+ar5212AniGetCurrentStats(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       /* update mib stats so we return current data */
+       /* XXX? side-effects to doing this here? */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+       return &ahp->ah_stats;
+}
+
+static void
+setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params)
+{
+       if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "OFDM Trigger %d is too high for hw counters, using max\n",
+                   params->ofdmTrigHigh);
+               params->ofdmPhyErrBase = 0;
+       } else
+               params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh;
+       if (params->cckTrigHigh >= AR_PHY_COUNTMAX) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "CCK Trigger %d is too high for hw counters, using max\n",
+                   params->cckTrigHigh);
+               params->cckPhyErrBase = 0;
+       } else
+               params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh;
+}
+
+/*
+ * Setup ANI handling.  Sets all thresholds and reset the
+ * channel statistics.  Note that ar5212AniReset should be
+ * called by ar5212Reset before anything else happens and
+ * that's where we force initial settings.
+ */
+void
+ar5212AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24,
+       const struct ar5212AniParams *params5, HAL_BOOL enable)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       ahp->ah_hasHwPhyCounters =
+               AH_PRIVATE(ah)->ah_caps.halHwPhyCounterSupport;
+
+       if (params24 != AH_NULL) {
+               OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));
+               setPhyErrBase(ah, &ahp->ah_aniParams24);
+       }
+       if (params5 != AH_NULL) {
+               OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));
+               setPhyErrBase(ah, &ahp->ah_aniParams5);
+       }
+
+       OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));
+       if (ahp->ah_hasHwPhyCounters) {
+               /* Enable MIB Counters */
+               enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/);
+       }
+       if (enable) {           /* Enable ani now */
+               HALASSERT(params24 != AH_NULL && params5 != AH_NULL);
+               ahp->ah_procPhyErr |= HAL_ANI_ENA;
+       } else {
+               ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
+       }
+}
+
+HAL_BOOL
+ar5212AniSetParams(struct ath_hal *ah, const struct ar5212AniParams *params24,
+       const struct ar5212AniParams *params5)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_BOOL ena = (ahp->ah_procPhyErr & HAL_ANI_ENA) != 0;
+
+       ar5212AniControl(ah, HAL_ANI_MODE, AH_FALSE);
+
+       OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));
+       setPhyErrBase(ah, &ahp->ah_aniParams24);
+       OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));
+       setPhyErrBase(ah, &ahp->ah_aniParams5);
+
+       OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));
+       ar5212AniReset(ah, AH_PRIVATE(ah)->ah_curchan,
+           AH_PRIVATE(ah)->ah_opmode, AH_FALSE);
+
+       ar5212AniControl(ah, HAL_ANI_MODE, ena);
+
+       return AH_TRUE;
+}
+
+/*
+ * Cleanup any ANI state setup.
+ */
+void
+ar5212AniDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n");
+       if (ahp->ah_hasHwPhyCounters)
+               disableAniMIBCounters(ah);
+}
+
+/*
+ * Control Adaptive Noise Immunity Parameters
+ */
+HAL_BOOL
+ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
+{
+       typedef int TABLE[];
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState = ahp->ah_curani;
+       const struct ar5212AniParams *params = aniState->params;
+
+       OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);
+
+       switch (cmd) {
+       case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxNoiseImmunityLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxNoiseImmunityLevel);
+                       return AH_FALSE;
+               }
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+                   AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+                   AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+                   AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                   AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]);
+
+               if (level > aniState->noiseImmunityLevel)
+                       ahp->ah_stats.ast_ani_niup++;
+               else if (level < aniState->noiseImmunityLevel)
+                       ahp->ah_stats.ast_ani_nidown++;
+               aniState->noiseImmunityLevel = level;
+               break;
+       }
+       case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
+               static const TABLE m1ThreshLow   = { 127,   50 };
+               static const TABLE m2ThreshLow   = { 127,   40 };
+               static const TABLE m1Thresh      = { 127, 0x4d };
+               static const TABLE m2Thresh      = { 127, 0x40 };
+               static const TABLE m2CountThr    = {  31,   16 };
+               static const TABLE m2CountThrLow = {  63,   48 };
+               u_int on = param ? 1 : 0;
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]);
+
+               if (on) {
+                       OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+                               AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               } else {
+                       OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+                               AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               }
+               if (on)
+                       ahp->ah_stats.ast_ani_ofdmon++;
+               else
+                       ahp->ah_stats.ast_ani_ofdmoff++;
+               aniState->ofdmWeakSigDetectOff = !on;
+               break;
+       }
+       case HAL_ANI_CCK_WEAK_SIGNAL_THR: {
+               static const TABLE weakSigThrCck = { 8, 6 };
+               u_int high = param ? 1 : 0;
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+                   AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]);
+               if (high)
+                       ahp->ah_stats.ast_ani_cckhigh++;
+               else
+                       ahp->ah_stats.ast_ani_ccklow++;
+               aniState->cckWeakSigThreshold = high;
+               break;
+       }
+       case HAL_ANI_FIRSTEP_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxFirstepLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxFirstepLevel);
+                       return AH_FALSE;
+               }
+               OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                   AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]);
+               if (level > aniState->firstepLevel)
+                       ahp->ah_stats.ast_ani_stepup++;
+               else if (level < aniState->firstepLevel)
+                       ahp->ah_stats.ast_ani_stepdown++;
+               aniState->firstepLevel = level;
+               break;
+       }
+       case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxSpurImmunityLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxSpurImmunityLevel);
+                       return AH_FALSE;
+               }
+               OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+                   AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]);
+               if (level > aniState->spurImmunityLevel)
+                       ahp->ah_stats.ast_ani_spurup++;
+               else if (level < aniState->spurImmunityLevel)
+                       ahp->ah_stats.ast_ani_spurdown++;
+               aniState->spurImmunityLevel = level;
+               break;
+       }
+       case HAL_ANI_PRESENT:
+               break;
+       case HAL_ANI_MODE:
+               if (param == 0) {
+                       ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
+                       /* Turn off HW counters if we have them */
+                       ar5212AniDetach(ah);
+                       ar5212SetRxFilter(ah,
+                               ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
+               } else {                        /* normal/auto mode */
+                       /* don't mess with state if already enabled */
+                       if (ahp->ah_procPhyErr & HAL_ANI_ENA)
+                               break;
+                       if (ahp->ah_hasHwPhyCounters) {
+                               ar5212SetRxFilter(ah,
+                                       ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
+                               /* Enable MIB Counters */
+                               enableAniMIBCounters(ah,
+                                   ahp->ah_curani != AH_NULL ?
+                                       ahp->ah_curani->params:
+                                       &ahp->ah_aniParams24 /*XXX*/);
+                       } else {
+                               ar5212SetRxFilter(ah,
+                                       ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR);
+                       }
+                       ahp->ah_procPhyErr |= HAL_ANI_ENA;
+               }
+               break;
+#ifdef AH_PRIVATE_DIAG
+       case HAL_ANI_PHYERR_RESET:
+               ahp->ah_stats.ast_ani_ofdmerrs = 0;
+               ahp->ah_stats.ast_ani_cckerrs = 0;
+               break;
+#endif /* AH_PRIVATE_DIAG */
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n",
+                   __func__, cmd);
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+static void
+ar5212AniOfdmErrTrigger(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(chan != AH_NULL);
+
+       if (!ANI_ENA(ah))
+               return;
+
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       /* First, raise noise immunity level, up to max */
+       if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
+                   aniState->noiseImmunityLevel + 1);
+               ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel + 1);
+               return;
+       }
+       /* then, raise spur immunity level, up to max */
+       if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise SI to %u\n", __func__,
+                   aniState->spurImmunityLevel + 1);
+               ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel + 1);
+               return;
+       }
+
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi > params->rssiThrHigh) {
+                       /*
+                        * Beacon rssi is high, can turn off ofdm
+                        * weak sig detect.
+                        */
+                       if (!aniState->ofdmWeakSigDetectOff) {
+                               HALDEBUG(ah, HAL_DEBUG_ANI,
+                                   "%s: rssi %d OWSD off\n", __func__, rssi);
+                               ar5212AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_FALSE);
+                               ar5212AniControl(ah,
+                                   HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
+                               return;
+                       }
+                       /*
+                        * If weak sig detect is already off, as last resort,
+                        * raise firstep level
+                        */
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+                               HALDEBUG(ah, HAL_DEBUG_ANI,
+                                   "%s: rssi %d raise ST %u\n", __func__, rssi,
+                                   aniState->firstepLevel+1);
+                               ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel + 1);
+                               return;
+                       }
+               } else if (rssi > params->rssiThrLow) {
+                       /*
+                        * Beacon rssi in mid range, need ofdm weak signal
+                        * detect, but we can raise firststepLevel.
+                        */
+                       if (aniState->ofdmWeakSigDetectOff) {
+                               HALDEBUG(ah, HAL_DEBUG_ANI,
+                                   "%s: rssi %d OWSD on\n", __func__, rssi);
+                               ar5212AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_TRUE);
+                       }
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+                               HALDEBUG(ah, HAL_DEBUG_ANI,
+                                   "%s: rssi %d raise ST %u\n", __func__, rssi,
+                                   aniState->firstepLevel+1);
+                               ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                    aniState->firstepLevel + 1);
+                       }
+                       return;
+               } else {
+                       /*
+                        * Beacon rssi is low, if in 11b/g mode, turn off ofdm
+                        * weak signal detection and zero firstepLevel to
+                        * maximize CCK sensitivity
+                        */
+                       /* XXX can optimize */
+                       if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) {
+                               if (!aniState->ofdmWeakSigDetectOff) {
+                                       HALDEBUG(ah, HAL_DEBUG_ANI,
+                                           "%s: rssi %d OWSD off\n",
+                                           __func__, rssi);
+                                       ar5212AniControl(ah,
+                                           HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                           AH_FALSE);
+                               }
+                               if (aniState->firstepLevel > 0) {
+                                       HALDEBUG(ah, HAL_DEBUG_ANI,
+                                           "%s: rssi %d zero ST (was %u)\n",
+                                           __func__, rssi,
+                                           aniState->firstepLevel);
+                                       ar5212AniControl(ah,
+                                            HAL_ANI_FIRSTEP_LEVEL, 0);
+                               }
+                               return;
+                       }
+               }
+       }
+}
+
+static void
+ar5212AniCckErrTrigger(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(chan != AH_NULL);
+
+       if (!ANI_ENA(ah))
+               return;
+
+       /* first, raise noise immunity level, up to max */
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
+                   aniState->noiseImmunityLevel + 1);
+               ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel + 1);
+               return;
+       }
+
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi >  params->rssiThrLow) {
+                       /*
+                        * Beacon signal in mid and high range,
+                        * raise firstep level.
+                        */
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+                               HALDEBUG(ah, HAL_DEBUG_ANI,
+                                   "%s: rssi %d raise ST %u\n", __func__, rssi,
+                                   aniState->firstepLevel+1);
+                               ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel + 1);
+                       }
+               } else {
+                       /*
+                        * Beacon rssi is low, zero firstep level to maximize
+                        * CCK sensitivity in 11b/g mode.
+                        */
+                       /* XXX can optimize */
+                       if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) {
+                               if (aniState->firstepLevel > 0) {
+                                       HALDEBUG(ah, HAL_DEBUG_ANI,
+                                           "%s: rssi %d zero ST (was %u)\n",
+                                           __func__, rssi,
+                                           aniState->firstepLevel);
+                                       ar5212AniControl(ah,
+                                           HAL_ANI_FIRSTEP_LEVEL, 0);
+                               }
+                       }
+               }
+       }
+}
+
+static void
+ar5212AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       aniState->listenTime = 0;
+       if (ahp->ah_hasHwPhyCounters) {
+               const struct ar5212AniParams *params = aniState->params;
+               /*
+                * NB: these are written on reset based on the
+                *     ini so we must re-write them!
+                */
+               OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase);
+               OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase);
+               OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);
+               OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);
+
+               /* Clear the mib counters and save them in the stats */
+               ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+       }
+       aniState->ofdmPhyErrCount = 0;
+       aniState->cckPhyErrCount = 0;
+}
+
+/*
+ * Restore/reset the ANI parameters and reset the statistics.
+ * This routine must be called for every channel change.
+ *
+ * NOTE: This is where ah_curani is set; other ani code assumes
+ *       it is setup to reflect the current channel.
+ */
+void
+ar5212AniReset(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
+       HAL_OPMODE opmode, int restore)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       uint32_t rxfilter;
+       int index;
+
+       index = ar5212GetAniChannelIndex(ah, chan);
+       aniState = &ahp->ah_ani[index];
+       ahp->ah_curani = aniState;
+#if 0
+       ath_hal_printf(ah,"%s: chan %u/0x%x restore %d setup %d opmode %u\n",
+           __func__, chan->channel, chan->channelFlags, restore,
+           aniState->isSetup, opmode);
+#else
+       HALDEBUG(ah, HAL_DEBUG_ANI,
+           "%s: chan %u/0x%x restore %d setup %d opmode %u\n",
+           __func__, chan->channel, chan->channelFlags, restore,
+           aniState->isSetup, opmode);
+#endif
+       OS_MARK(ah, AH_MARK_ANI_RESET, opmode);
+
+       /*
+        * Turn off PHY error frame delivery while we futz with settings.
+        */
+       rxfilter = ar5212GetRxFilter(ah);
+       ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
+       /*
+        * Automatic processing is done only in station mode right now.
+        */
+       if (opmode == HAL_M_STA)
+               ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA;
+       else
+               ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA;
+       /*
+        * Set all ani parameters.  We either set them to initial
+        * values or restore the previous ones for the channel.
+        * XXX if ANI follows hardware, we don't care what mode we're
+        * XXX in, we should keep the ani parameters
+        */
+       if (restore && aniState->isSetup) {
+               ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel);
+               ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel);
+               ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                !aniState->ofdmWeakSigDetectOff);
+               ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
+                                aniState->cckWeakSigThreshold);
+               ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                aniState->firstepLevel);
+       } else {
+               ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
+               ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
+               ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                       AH_TRUE);
+               ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);
+               ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
+               aniState->isSetup = AH_TRUE;
+       }
+       ar5212AniRestart(ah, aniState);
+
+       /* restore RX filter mask */
+       ar5212SetRxFilter(ah, rxfilter);
+}
+
+/*
+ * Process a MIB interrupt.  We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
+void
+ar5212ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t phyCnt1, phyCnt2;
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x "
+           "filtofdm 0x%x filtcck 0x%x\n",
+           __func__, OS_REG_READ(ah, AR_MIBC),
+           OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2),
+           OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK));
+
+       /*
+        * First order of business is to clear whatever caused
+        * the interrupt so we don't keep getting interrupted.
+        * We have the usual mib counters that are reset-on-read
+        * and the additional counters that appeared starting in
+        * Hainan.  We collect the mib counters and explicitly
+        * zero additional counters we are not using.  Anything
+        * else is reset only if it caused the interrupt.
+        */
+       /* NB: these are not reset-on-read */
+       phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1);
+       phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2);
+       /* not used, always reset them in case they are the cause */
+       OS_REG_WRITE(ah, AR_FILTOFDM, 0);
+       OS_REG_WRITE(ah, AR_FILTCCK, 0);
+
+       /* Clear the mib counters and save them in the stats */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+       ahp->ah_stats.ast_nodestats = *stats;
+
+       /*
+        * Check for an ani stat hitting the trigger threshold.
+        * When this happens we get a MIB interrupt and the top
+        * 2 bits of the counter register will be 0b11, hence
+        * the mask check of phyCnt?.
+        */
+       if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
+           ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+               struct ar5212AniState *aniState = ahp->ah_curani;
+               const struct ar5212AniParams *params = aniState->params;
+               uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+               ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
+               ahp->ah_stats.ast_ani_ofdmerrs +=
+                       ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+               aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+               cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
+               ahp->ah_stats.ast_ani_cckerrs +=
+                       cckPhyErrCnt - aniState->cckPhyErrCount;
+               aniState->cckPhyErrCount = cckPhyErrCnt;
+
+               /*
+                * NB: figure out which counter triggered.  If both
+                * trigger we'll only deal with one as the processing
+                * clobbers the error counter so the trigger threshold
+                * check will never be true.
+                */
+               if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh)
+                       ar5212AniOfdmErrTrigger(ah);
+               if (aniState->cckPhyErrCount > params->cckTrigHigh)
+                       ar5212AniCckErrTrigger(ah);
+               /* NB: always restart to insure the h/w counters are reset */
+               ar5212AniRestart(ah, aniState);
+       }
+}
+
+void
+ar5212AniPhyErrReport(struct ath_hal *ah, const struct ath_rx_status *rs)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(!ahp->ah_hasHwPhyCounters && rs != AH_NULL);
+
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       if (rs->rs_phyerr == HAL_PHYERR_OFDM_TIMING) {
+               aniState->ofdmPhyErrCount++;
+               ahp->ah_stats.ast_ani_ofdmerrs++;
+               if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) {
+                       ar5212AniOfdmErrTrigger(ah);
+                       ar5212AniRestart(ah, aniState);
+               }
+       } else if (rs->rs_phyerr == HAL_PHYERR_CCK_TIMING) {
+               aniState->cckPhyErrCount++;
+               ahp->ah_stats.ast_ani_cckerrs++;
+               if (aniState->cckPhyErrCount > params->cckTrigHigh) {
+                       ar5212AniCckErrTrigger(ah);
+                       ar5212AniRestart(ah, aniState);
+               }
+       }
+}
+
+static void
+ar5212AniLowerImmunity(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(ANI_ENA(ah));
+
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi > params->rssiThrHigh) {
+                       /*
+                        * Beacon signal is high, leave ofdm weak signal
+                        * detection off or it may oscillate.  Let it fall
+                        * through.
+                        */
+               } else if (rssi > params->rssiThrLow) {
+                       /*
+                        * Beacon rssi in mid range, turn on ofdm weak signal
+                        * detection or lower firstep level.
+                        */
+                       if (aniState->ofdmWeakSigDetectOff) {
+                               HALDEBUG(ah, HAL_DEBUG_ANI,
+                                   "%s: rssi %d OWSD on\n", __func__, rssi);
+                               ar5212AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_TRUE);
+                               return;
+                       }
+                       if (aniState->firstepLevel > 0) {
+                               HALDEBUG(ah, HAL_DEBUG_ANI,
+                                   "%s: rssi %d lower ST %u\n", __func__, rssi,
+                                   aniState->firstepLevel-1);
+                               ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel - 1);
+                               return;
+                       }
+               } else {
+                       /*
+                        * Beacon rssi is low, reduce firstep level.
+                        */
+                       if (aniState->firstepLevel > 0) {
+                               HALDEBUG(ah, HAL_DEBUG_ANI,
+                                   "%s: rssi %d lower ST %u\n", __func__, rssi,
+                                   aniState->firstepLevel-1);
+                               ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel - 1);
+                               return;
+                       }
+               }
+       }
+       /* then lower spur immunity level, down to zero */
+       if (aniState->spurImmunityLevel > 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower SI %u\n",
+                   __func__, aniState->spurImmunityLevel-1);
+               ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel - 1);
+               return;
+       }
+       /*
+        * if all else fails, lower noise immunity level down to a min value
+        * zero for now
+        */
+       if (aniState->noiseImmunityLevel > 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower NI %u\n",
+                   __func__, aniState->noiseImmunityLevel-1);
+               ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel - 1);
+               return;
+       }
+}
+
+#define CLOCK_RATE 44000       /* XXX use mac_usec or similar */
+/* convert HW counter values to ms using 11g clock rate, goo9d enough
+   for 11a and Turbo */
+
+/*
+ * Return an approximation of the time spent ``listening'' by
+ * deducting the cycles spent tx'ing and rx'ing from the total
+ * cycle count since our last call.  A return value <0 indicates
+ * an invalid/inconsistent time.
+ */
+static int32_t
+ar5212AniGetListenTime(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       uint32_t txFrameCount, rxFrameCount, cycleCount;
+       int32_t listenTime;
+
+       txFrameCount = OS_REG_READ(ah, AR_TFCNT);
+       rxFrameCount = OS_REG_READ(ah, AR_RFCNT);
+       cycleCount = OS_REG_READ(ah, AR_CCCNT);
+
+       aniState = ahp->ah_curani;
+       if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
+               /*
+                * Cycle counter wrap (or initial call); it's not possible
+                * to accurately calculate a value because the registers
+                * right shift rather than wrap--so punt and return 0.
+                */
+               listenTime = 0;
+               ahp->ah_stats.ast_ani_lzero++;
+       } else {
+               int32_t ccdelta = cycleCount - aniState->cycleCount;
+               int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
+               int32_t tfdelta = txFrameCount - aniState->txFrameCount;
+               listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
+       }
+       aniState->cycleCount = cycleCount;
+       aniState->txFrameCount = txFrameCount;
+       aniState->rxFrameCount = rxFrameCount;
+       return listenTime;
+}
+
+/*
+ * Update ani stats in preparation for listen time processing.
+ */
+static void
+updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const struct ar5212AniParams *params = aniState->params;
+       uint32_t phyCnt1, phyCnt2;
+       int32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+       HALASSERT(ahp->ah_hasHwPhyCounters);
+
+       /* Clear the mib counters and save them in the stats */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+
+       /* NB: these are not reset-on-read */
+       phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1);
+       phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2);
+
+       /* NB: these are spec'd to never roll-over */
+       ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
+       if (ofdmPhyErrCnt < 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n",
+                   ofdmPhyErrCnt, phyCnt1);
+               ofdmPhyErrCnt = AR_PHY_COUNTMAX;
+       }
+       ahp->ah_stats.ast_ani_ofdmerrs +=
+            ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+       aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+       cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
+       if (cckPhyErrCnt < 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n",
+                   cckPhyErrCnt, phyCnt2);
+               cckPhyErrCnt = AR_PHY_COUNTMAX;
+       }
+       ahp->ah_stats.ast_ani_cckerrs +=
+               cckPhyErrCnt - aniState->cckPhyErrCount;
+       aniState->cckPhyErrCount = cckPhyErrCnt;
+}
+
+/*
+ * Do periodic processing.  This routine is called from the
+ * driver's rx interrupt handler after processing frames.
+ */
+void
+ar5212AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
+               HAL_CHANNEL *chan)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState = ahp->ah_curani;
+       const struct ar5212AniParams *params;
+       int32_t listenTime;
+
+       ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi;
+
+       /* XXX can aniState be null? */
+       if (aniState == AH_NULL)
+               return;
+       if (!ANI_ENA(ah))
+               return;
+
+       listenTime = ar5212AniGetListenTime(ah);
+       if (listenTime < 0) {
+               ahp->ah_stats.ast_ani_lneg++;
+               /* restart ANI period if listenTime is invalid */
+               ar5212AniRestart(ah, aniState);
+       }
+       /* XXX beware of overflow? */
+       aniState->listenTime += listenTime;
+
+       OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime);
+
+       params = aniState->params;
+       if (aniState->listenTime > 5*params->period) {
+               /*
+                * Check to see if need to lower immunity if
+                * 5 aniPeriods have passed
+                */
+               if (ahp->ah_hasHwPhyCounters)
+                       updateMIBStats(ah, aniState);
+               if (aniState->ofdmPhyErrCount <= aniState->listenTime *
+                   params->ofdmTrigLow/1000 &&
+                   aniState->cckPhyErrCount <= aniState->listenTime *
+                   params->cckTrigLow/1000)
+                       ar5212AniLowerImmunity(ah);
+               ar5212AniRestart(ah, aniState);
+       } else if (aniState->listenTime > params->period) {
+               if (ahp->ah_hasHwPhyCounters)
+                       updateMIBStats(ah, aniState);
+               /* check to see if need to raise immunity */
+               if (aniState->ofdmPhyErrCount > aniState->listenTime *
+                   params->ofdmTrigHigh / 1000) {
+                       HALDEBUG(ah, HAL_DEBUG_ANI,
+                           "%s: OFDM err %u listenTime %u\n", __func__,
+                           aniState->ofdmPhyErrCount, aniState->listenTime);
+                       ar5212AniOfdmErrTrigger(ah);
+                       ar5212AniRestart(ah, aniState);
+               } else if (aniState->cckPhyErrCount > aniState->listenTime *
+                          params->cckTrigHigh / 1000) {
+                       HALDEBUG(ah, HAL_DEBUG_ANI,
+                           "%s: CCK err %u listenTime %u\n", __func__,
+                           aniState->cckPhyErrCount, aniState->listenTime);
+                       ar5212AniCckErrTrigger(ah);
+                       ar5212AniRestart(ah, aniState);
+               }
+       }
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_attach.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,870 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_attach.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#define AH_5212_COMMON
+#include "ar5212/ar5212.ini"
+
+static const struct ath_hal_private ar5212hal = {{
+       .ah_magic                       = AR5212_MAGIC,
+       .ah_abi                         = HAL_ABI_VERSION,
+       .ah_countryCode                 = CTRY_DEFAULT,
+
+       .ah_getRateTable                = ar5212GetRateTable,
+       .ah_detach                      = ar5212Detach,
+
+       /* Reset Functions */
+       .ah_reset                       = ar5212Reset,
+       .ah_phyDisable                  = ar5212PhyDisable,
+       .ah_disable                     = ar5212Disable,
+       .ah_setPCUConfig                = ar5212SetPCUConfig,
+       .ah_perCalibration              = ar5212PerCalibration,
+       .ah_perCalibrationN             = ar5212PerCalibrationN,
+       .ah_resetCalValid               = ar5212ResetCalValid,
+       .ah_setTxPowerLimit             = ar5212SetTxPowerLimit,
+       .ah_getChanNoise                = ath_hal_getChanNoise,
+
+       /* Transmit functions */
+       .ah_updateTxTrigLevel           = ar5212UpdateTxTrigLevel,
+       .ah_setupTxQueue                = ar5212SetupTxQueue,
+       .ah_setTxQueueProps             = ar5212SetTxQueueProps,
+       .ah_getTxQueueProps             = ar5212GetTxQueueProps,
+       .ah_releaseTxQueue              = ar5212ReleaseTxQueue,
+       .ah_resetTxQueue                = ar5212ResetTxQueue,
+       .ah_getTxDP                     = ar5212GetTxDP,
+       .ah_setTxDP                     = ar5212SetTxDP,
+       .ah_numTxPending                = ar5212NumTxPending,
+       .ah_startTxDma                  = ar5212StartTxDma,
+       .ah_stopTxDma                   = ar5212StopTxDma,
+       .ah_setupTxDesc                 = ar5212SetupTxDesc,
+       .ah_setupXTxDesc                = ar5212SetupXTxDesc,
+       .ah_fillTxDesc                  = ar5212FillTxDesc,
+       .ah_procTxDesc                  = ar5212ProcTxDesc,
+       .ah_getTxIntrQueue              = ar5212GetTxIntrQueue,
+       .ah_reqTxIntrDesc               = ar5212IntrReqTxDesc,
+
+       /* RX Functions */
+       .ah_getRxDP                     = ar5212GetRxDP,
+       .ah_setRxDP                     = ar5212SetRxDP,
+       .ah_enableReceive               = ar5212EnableReceive,
+       .ah_stopDmaReceive              = ar5212StopDmaReceive,
+       .ah_startPcuReceive             = ar5212StartPcuReceive,
+       .ah_stopPcuReceive              = ar5212StopPcuReceive,
+       .ah_setMulticastFilter          = ar5212SetMulticastFilter,
+       .ah_setMulticastFilterIndex     = ar5212SetMulticastFilterIndex,
+       .ah_clrMulticastFilterIndex     = ar5212ClrMulticastFilterIndex,
+       .ah_getRxFilter                 = ar5212GetRxFilter,
+       .ah_setRxFilter                 = ar5212SetRxFilter,
+       .ah_setupRxDesc                 = ar5212SetupRxDesc,
+       .ah_procRxDesc                  = ar5212ProcRxDesc,
+       .ah_rxMonitor                   = ar5212AniPoll,
+       .ah_procMibEvent                = ar5212ProcessMibIntr,
+
+       /* Misc Functions */
+       .ah_getCapability               = ar5212GetCapability,
+       .ah_setCapability               = ar5212SetCapability,
+       .ah_getDiagState                = ar5212GetDiagState,
+       .ah_getMacAddress               = ar5212GetMacAddress,
+       .ah_setMacAddress               = ar5212SetMacAddress,
+       .ah_getBssIdMask                = ar5212GetBssIdMask,
+       .ah_setBssIdMask                = ar5212SetBssIdMask,
+       .ah_setRegulatoryDomain         = ar5212SetRegulatoryDomain,
+       .ah_setLedState                 = ar5212SetLedState,
+       .ah_writeAssocid                = ar5212WriteAssocid,
+       .ah_gpioCfgInput                = ar5212GpioCfgInput,
+       .ah_gpioCfgOutput               = ar5212GpioCfgOutput,
+       .ah_gpioGet                     = ar5212GpioGet,
+       .ah_gpioSet                     = ar5212GpioSet,
+       .ah_gpioSetIntr                 = ar5212GpioSetIntr,
+       .ah_getTsf32                    = ar5212GetTsf32,
+       .ah_getTsf64                    = ar5212GetTsf64,
+       .ah_resetTsf                    = ar5212ResetTsf,
+       .ah_detectCardPresent           = ar5212DetectCardPresent,
+       .ah_updateMibCounters           = ar5212UpdateMibCounters,
+       .ah_getRfGain                   = ar5212GetRfgain,
+       .ah_getDefAntenna               = ar5212GetDefAntenna,
+       .ah_setDefAntenna               = ar5212SetDefAntenna,
+       .ah_getAntennaSwitch            = ar5212GetAntennaSwitch,
+       .ah_setAntennaSwitch            = ar5212SetAntennaSwitch,
+       .ah_setSifsTime                 = ar5212SetSifsTime,
+       .ah_getSifsTime                 = ar5212GetSifsTime,
+       .ah_setSlotTime                 = ar5212SetSlotTime,
+       .ah_getSlotTime                 = ar5212GetSlotTime,
+       .ah_setAckTimeout               = ar5212SetAckTimeout,
+       .ah_getAckTimeout               = ar5212GetAckTimeout,
+       .ah_setAckCTSRate               = ar5212SetAckCTSRate,
+       .ah_getAckCTSRate               = ar5212GetAckCTSRate,
+       .ah_setCTSTimeout               = ar5212SetCTSTimeout,
+       .ah_getCTSTimeout               = ar5212GetCTSTimeout,
+       .ah_setDecompMask               = ar5212SetDecompMask,
+       .ah_setCoverageClass            = ar5212SetCoverageClass,
+
+       /* Key Cache Functions */
+       .ah_getKeyCacheSize             = ar5212GetKeyCacheSize,
+       .ah_resetKeyCacheEntry          = ar5212ResetKeyCacheEntry,
+       .ah_isKeyCacheEntryValid        = ar5212IsKeyCacheEntryValid,
+       .ah_setKeyCacheEntry            = ar5212SetKeyCacheEntry,
+       .ah_setKeyCacheEntryMac         = ar5212SetKeyCacheEntryMac,
+
+       /* Power Management Functions */
+       .ah_setPowerMode                = ar5212SetPowerMode,
+       .ah_getPowerMode                = ar5212GetPowerMode,
+
+       /* Beacon Functions */
+       .ah_setBeaconTimers             = ar5212SetBeaconTimers,
+       .ah_beaconInit                  = ar5212BeaconInit,
+       .ah_setStationBeaconTimers      = ar5212SetStaBeaconTimers,
+       .ah_resetStationBeaconTimers    = ar5212ResetStaBeaconTimers,
+
+       /* Interrupt Functions */
+       .ah_isInterruptPending          = ar5212IsInterruptPending,
+       .ah_getPendingInterrupts        = ar5212GetPendingInterrupts,
+       .ah_getInterrupts               = ar5212GetInterrupts,
+       .ah_setInterrupts               = ar5212SetInterrupts },
+
+       .ah_getChannelEdges             = ar5212GetChannelEdges,
+       .ah_getWirelessModes            = ar5212GetWirelessModes,
+       .ah_eepromRead                  = ar5212EepromRead,
+#ifdef AH_SUPPORT_WRITE_EEPROM
+       .ah_eepromWrite                 = ar5212EepromWrite,
+#endif
+       .ah_gpioCfgOutput               = ar5212GpioCfgOutput,
+       .ah_gpioCfgInput                = ar5212GpioCfgInput,
+       .ah_gpioGet                     = ar5212GpioGet,
+       .ah_gpioSet                     = ar5212GpioSet,
+       .ah_gpioSetIntr                 = ar5212GpioSetIntr,
+       .ah_getChipPowerLimits          = ar5212GetChipPowerLimits,
+};
+
+/*
+ * Disable PLL when in L0s as well as receiver clock when in L1.
+ * This power saving option must be enabled through the Serdes.
+ *
+ * Programming the Serdes must go through the same 288 bit serial shift
+ * register as the other analog registers.  Hence the 9 writes.
+ *
+ * XXX Clean up the magic numbers.
+ */
+static void
+configurePciePowerSave(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+
+       /* RX shut off when elecidle is asserted */
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
+
+       /* Shut off PLL and CLKREQ active in L1 */
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+       OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
+
+       /* Load the new settings */
+       OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+}
+
+uint32_t
+ar5212GetRadioRev(struct ath_hal *ah)
+{
+       uint32_t val;
+       int i;
+
+       /* Read Radio Chip Rev Extract */
+       OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16);
+       for (i = 0; i < 8; i++)
+               OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
+       val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
+       val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
+       return ath_hal_reverseBits(val, 8);
+}
+
+static void
+ar5212AniSetup(struct ath_hal *ah)
+{
+       static const struct ar5212AniParams aniparams = {
+               .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
+               .totalSizeDesired       = { -55, -55, -55, -55, -62 },
+               .coarseHigh             = { -14, -14, -14, -14, -12 },
+               .coarseLow              = { -64, -64, -64, -64, -70 },
+               .firpwr                 = { -78, -78, -78, -78, -80 },
+               .maxSpurImmunityLevel   = 2,    /* NB: depends on chip rev */
+               .cycPwrThr1             = { 2, 4, 6, 8, 10, 12, 14, 16 },
+               .maxFirstepLevel        = 2,    /* levels 0..2 */
+               .firstep                = { 0, 4, 8 },
+               .ofdmTrigHigh           = 500,
+               .ofdmTrigLow            = 200,
+               .cckTrigHigh            = 200,
+               .cckTrigLow             = 100,
+               .rssiThrHigh            = 40,
+               .rssiThrLow             = 7,
+               .period                 = 100,
+       };
+       if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) {
+               struct ar5212AniParams tmp;
+               OS_MEMCPY(&tmp, &aniparams, sizeof(struct ar5212AniParams));
+               tmp.maxSpurImmunityLevel = 7;   /* Venice and earlier */
+               ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE);
+       } else
+               ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
+}
+
+/*
+ * Attach for an AR5212 part.
+ */
+void
+ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+       static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] =
+               { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+       struct ath_hal *ah;
+
+       ah = &ahp->ah_priv.h;
+       /* set initial values */
+       OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private));
+       ah->ah_sc = sc;
+       ah->ah_st = st;
+       ah->ah_sh = sh;
+
+       ah->ah_devid = devid;                   /* NB: for alq */
+       AH_PRIVATE(ah)->ah_devid = devid;
+       AH_PRIVATE(ah)->ah_subvendorid = 0;     /* XXX */
+
+       AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER;
+       AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX;  /* no scaling */
+
+       ahp->ah_antControl = HAL_ANT_VARIABLE;
+       ahp->ah_diversity = AH_TRUE;
+       ahp->ah_bIQCalibration = AH_FALSE;
+       /*
+        * Enable MIC handling.
+        */
+       ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
+       ahp->ah_rssiThr = INIT_RSSI_THR;
+       ahp->ah_tpcEnabled = AH_FALSE;          /* disabled by default */
+       ahp->ah_phyPowerOn = AH_FALSE;
+       ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK)
+                      | SM(MAX_RATE_POWER, AR_TPC_CTS)
+                      | SM(MAX_RATE_POWER, AR_TPC_CHIRP);
+       ahp->ah_beaconInterval = 100;           /* XXX [20..1000] */
+       ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */
+       ahp->ah_slottime = (u_int) -1;
+       ahp->ah_acktimeout = (u_int) -1;
+       ahp->ah_ctstimeout = (u_int) -1;
+       ahp->ah_sifstime = (u_int) -1;
+       OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN);
+#undef N
+}
+
+/*
+ * Validate MAC version and revision.
+ */
+static HAL_BOOL
+ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev)
+{
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+       static const struct {
+               uint8_t version;
+               uint8_t revMin, revMax;
+       } macs[] = {
+           { AR_SREV_VERSION_VENICE,
+             AR_SREV_D2PLUS,           AR_SREV_REVISION_MAX },
+           { AR_SREV_VERSION_GRIFFIN,
+             AR_SREV_D2PLUS,           AR_SREV_REVISION_MAX },
+           { AR_SREV_5413,
+             AR_SREV_REVISION_MIN,     AR_SREV_REVISION_MAX },
+           { AR_SREV_5424,
+             AR_SREV_REVISION_MIN,     AR_SREV_REVISION_MAX },
+           { AR_SREV_2425,
+             AR_SREV_REVISION_MIN,     AR_SREV_REVISION_MAX },
+           { AR_SREV_2417,
+             AR_SREV_REVISION_MIN,     AR_SREV_REVISION_MAX },
+       };
+       int i;
+
+       for (i = 0; i < N(macs); i++)
+               if (macs[i].version == macVersion &&
+                   macs[i].revMin <= macRev && macRev <= macs[i].revMax)
+                       return AH_TRUE;
+       return AH_FALSE;
+#undef N
+}
+
+/*
+ * Attach for an AR5212 part.
+ */
+static struct ath_hal *
+ar5212Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+#define        AH_EEPROM_PROTECT(ah) \
+       (IS_PCIE(ah) ? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT)
+       struct ath_hal_5212 *ahp;
+       struct ath_hal *ah;
+       struct ath_hal_rf *rf;
+       uint32_t val;
+       uint16_t eeval;
+       HAL_STATUS ecode;
+
+       HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
+           __func__, sc, (void*) st, (void*) sh);
+
+       /* NB: memory is returned zero'd */
+       ahp = ath_hal_malloc(sizeof (struct ath_hal_5212));
+       if (ahp == AH_NULL) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                   "%s: cannot allocate memory for state block\n", __func__);
+               *status = HAL_ENOMEM;
+               return AH_NULL;
+       }
+       ar5212InitState(ahp, devid, sc, st, sh, status);
+       ah = &ahp->ah_priv.h;
+
+       if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
+                   __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+       /* Read Revisions from Chips before taking out of reset */
+       val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
+       AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;
+       AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION;
+
+       if (!ar5212IsMacSupported(AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: Mac Chip Rev 0x%02x.%x not supported\n" ,
+                   __func__, AH_PRIVATE(ah)->ah_macVersion,
+                   AH_PRIVATE(ah)->ah_macRev);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+       }
+
+       /* setup common ini data; rf backends handle remainder */
+       HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6);
+       HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2);
+
+       if (!ar5212ChipReset(ah, AH_NULL)) {    /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
+
+       if (IS_PCIE(ah)) {
+               /* XXX: build flag to disable this? */
+               configurePciePowerSave(ah);
+       }
+
+       if (!ar5212ChipTest(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
+                   __func__);
+               ecode = HAL_ESELFTEST;
+               goto bad;
+       }
+
+       /* Enable PCI core retry fix in software for Hainan and up */
+       if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_VENICE)
+               OS_REG_SET_BIT(ah, AR_PCICFG, AR_PCICFG_RETRYFIXEN);
+
+       /*
+        * Set correct Baseband to analog shift
+        * setting to access analog chips.
+        */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       /* Read Radio Chip Rev Extract */
+       AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
+
+       rf = ath_hal_rfprobe(ah, &ecode);
+       if (rf == AH_NULL)
+               goto bad;
+
+       /* NB: silently accept anything in release code per Atheros */
+       switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
+       case AR_RAD5111_SREV_MAJOR:
+       case AR_RAD5112_SREV_MAJOR:
+       case AR_RAD2112_SREV_MAJOR:
+       case AR_RAD2111_SREV_MAJOR:
+       case AR_RAD2413_SREV_MAJOR:
+       case AR_RAD5413_SREV_MAJOR:
+       case AR_RAD5424_SREV_MAJOR:
+               break;
+       default:
+               if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
+                       /*
+                        * When RF_Silent is used, the
+                        * analog chip is reset.  So when the system boots
+                        * up with the radio switch off we cannot determine
+                        * the RF chip rev.  To workaround this check the
+                        * mac+phy revs and if Hainan, set the radio rev
+                        * to Derby.
+                        */
+                       if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
+                           AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN &&
+                           AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) {
+                               AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN;
+                               break;
+                       }
+                       if (IS_2413(ah)) {              /* Griffin */
+                               AH_PRIVATE(ah)->ah_analog5GhzRev =
+                                   AR_RAD2413_SREV_MAJOR | 0x1;
+                               break;
+                       }
+                       if (IS_5413(ah)) {              /* Eagle */
+                               AH_PRIVATE(ah)->ah_analog5GhzRev =
+                                   AR_RAD5413_SREV_MAJOR | 0x2;
+                               break;
+                       }
+                       if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */
+                               AH_PRIVATE(ah)->ah_analog5GhzRev =
+                                   AR_RAD5424_SREV_MAJOR | 0x2;
+                               break;
+                       }
+               }
+#ifdef AH_DEBUG
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: 5G Radio Chip Rev 0x%02X is not supported by "
+                   "this driver\n",
+                   __func__, AH_PRIVATE(ah)->ah_analog5GhzRev);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+#endif
+       }
+       if (IS_RAD5112_REV1(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: 5112 Rev 1 is not supported by this "
+                   "driver (analog5GhzRev 0x%x)\n", __func__,
+                   AH_PRIVATE(ah)->ah_analog5GhzRev);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+       }
+
+       val = OS_REG_READ(ah, AR_PCICFG);
+       val = MS(val, AR_PCICFG_EEPROM_SIZE);
+       if (val == 0) {
+               if (!IS_PCIE(ah)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: unsupported EEPROM size %u (0x%x) found\n",
+                           __func__, val, val);
+                       ecode = HAL_EESIZE;
+                       goto bad;
+               }
+               /* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */
+       } else if (val != AR_PCICFG_EEPROM_SIZE_16K) {
+               if (AR_PCICFG_EEPROM_SIZE_FAILED == val) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: unsupported EEPROM size %u (0x%x) found\n",
+                           __func__, val, val);
+                       ecode = HAL_EESIZE;
+                       goto bad;
+               }
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: EEPROM size = %d. Must be %d (16k).\n",
+                   __func__, val, AR_PCICFG_EEPROM_SIZE_16K);
+               ecode = HAL_EESIZE;
+               goto bad;
+       }
+       ecode = ath_hal_legacyEepromAttach(ah);
+       if (ecode != HAL_OK) {
+               goto bad;
+       }
+       ahp->ah_isHb63 = IS_2425(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_ISTALON);
+
+       /*
+        * If Bmode and AR5212, verify 2.4 analog exists
+        */
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) &&
+           (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) {
+               /*
+                * Set correct Baseband to analog shift
+                * setting to access analog chips.
+                */
+               OS_REG_WRITE(ah, AR_PHY(0), 0x00004007);
+               OS_DELAY(2000);
+               AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah);
+
+               /* Set baseband for 5GHz chip */
+               OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+               OS_DELAY(2000);
+               if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: 2G Radio Chip Rev 0x%02X is not "
+                           "supported by this driver\n", __func__,
+                           AH_PRIVATE(ah)->ah_analog2GhzRev);
+                       ecode = HAL_ENOTSUPP;
+                       goto bad;
+               }
+       }
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot read regulatory domain from EEPROM\n",
+                   __func__);
+               goto bad;
+        }
+       AH_PRIVATE(ah)->ah_currentRD = eeval;
+       /* XXX record serial number */
+
+       /*
+        * Got everything we need now to setup the capabilities.
+        */
+       if (!ar5212FillCapabilityInfo(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: failed ar5212FillCapabilityInfo\n", __func__);
+               ecode = HAL_EEREAD;
+               goto bad;
+       }
+
+       if (!rf->attach(ah, &ecode)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
+                   __func__, ecode);
+               goto bad;
+       }
+       /*
+        * Set noise floor adjust method; we arrange a
+        * direct call instead of thunking.
+        */
+       AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust;
+
+       /* Initialize gain ladder thermal calibration structure */
+       ar5212InitializeGainValues(ah);
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error getting mac address from EEPROM\n", __func__);
+               goto bad;
+        }
+
+       ar5212AniSetup(ah);
+       /* Setup of Radar/AR structures happens in ath_hal_initchannels*/
+       ar5212InitNfCalHistBuffer(ah);
+
+       /* XXX EAR stuff goes here */
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
+
+       return ah;
+
+bad:
+       if (ahp)
+               ar5212Detach((struct ath_hal *) ahp);
+       if (status)
+               *status = ecode;
+       return AH_NULL;
+#undef AH_EEPROM_PROTECT
+}
+
+void
+ar5212Detach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
+
+       HALASSERT(ah != AH_NULL);
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       ar5212AniDetach(ah);
+       ar5212RfDetach(ah);
+       ar5212Disable(ah);
+       ar5212SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
+
+       ath_hal_eepromDetach(ah);
+       ath_hal_free(ah);
+}
+
+HAL_BOOL
+ar5212ChipTest(struct ath_hal *ah)
+{
+       uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) };
+       uint32_t regHold[2];
+       uint32_t patternData[4] =
+           { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };
+       int i, j;
+
+       /* Test PHY & MAC registers */
+       for (i = 0; i < 2; i++) {
+               uint32_t addr = regAddr[i];
+               uint32_t wrData, rdData;
+
+               regHold[i] = OS_REG_READ(ah, addr);
+               for (j = 0; j < 0x100; j++) {
+                       wrData = (j << 16) | j;
+                       OS_REG_WRITE(ah, addr, wrData);
+                       rdData = OS_REG_READ(ah, addr);
+                       if (rdData != wrData) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+                               __func__, addr, wrData, rdData);
+                               return AH_FALSE;
+                       }
+               }
+               for (j = 0; j < 4; j++) {
+                       wrData = patternData[j];
+                       OS_REG_WRITE(ah, addr, wrData);
+                       rdData = OS_REG_READ(ah, addr);
+                       if (wrData != rdData) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+                                       __func__, addr, wrData, rdData);
+                               return AH_FALSE;
+                       }
+               }
+               OS_REG_WRITE(ah, regAddr[i], regHold[i]);
+       }
+       OS_DELAY(100);
+       return AH_TRUE;
+}
+
+/*
+ * Store the channel edges for the requested operational mode
+ */
+HAL_BOOL
+ar5212GetChannelEdges(struct ath_hal *ah,
+       uint16_t flags, uint16_t *low, uint16_t *high)
+{
+       if (flags & CHANNEL_5GHZ) {
+               *low = 4915;
+               *high = 6100;
+               return AH_TRUE;
+       }
+       if ((flags & CHANNEL_2GHZ) &&
+           (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) ||
+            ath_hal_eepromGetFlag(ah, AR_EEP_GMODE))) {
+               *low = 2312;
+               *high = 2732;
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Fill all software cached or static hardware state information.
+ * Return failure if capabilities are to come from EEPROM and
+ * cannot be read.
+ */
+HAL_BOOL
+ar5212FillCapabilityInfo(struct ath_hal *ah)
+{
+#define        AR_KEYTABLE_SIZE        128
+#define        IS_GRIFFIN_LITE(ah) \
+    (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \
+     AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE)
+#define        IS_COBRA(ah) \
+    (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA)
+#define IS_2112(ah) \
+       ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR)
+
+       struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
+       HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
+       uint16_t capField, val;
+
+       /* Read the capability EEPROM location */
+       if (ath_hal_eepromGet(ah, AR_EEP_OPCAP, &capField) != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: unable to read caps from eeprom\n", __func__);
+               return AH_FALSE;
+       }
+       if (IS_2112(ah))
+               ath_hal_eepromSet(ah, AR_EEP_AMODE, AH_FALSE);
+       if (capField == 0 && IS_GRIFFIN_LITE(ah)) {
+               /*
+                * For griffin-lite cards with unprogrammed capabilities.
+                */
+               ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);
+               ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);
+               ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);
+               ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);
+               HALDEBUG(ah, HAL_DEBUG_ATTACH,
+                   "%s: override caps for griffin-lite, now 0x%x (+!turbo)\n",
+                   __func__, capField);
+       }
+
+       /* Modify reg domain on newer cards that need to work with older sw */
+       if (ahpriv->ah_opmode != HAL_M_HOSTAP &&
+           ahpriv->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+               if (ahpriv->ah_currentRD == 0x64 ||
+                   ahpriv->ah_currentRD == 0x65)
+                       ahpriv->ah_currentRD += 5;
+               else if (ahpriv->ah_currentRD == 0x41)
+                       ahpriv->ah_currentRD = 0x43;
+               HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: regdomain mapped to 0x%x\n",
+                   __func__, ahpriv->ah_currentRD);
+       }
+
+       if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2417 ||
+           AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) {
+               HALDEBUG(ah, HAL_DEBUG_ATTACH,
+                   "%s: enable Bmode and disable turbo for Swan/Nala\n",
+                   __func__);
+               ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_TRUE);
+               ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);
+               ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);
+               ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);
+               ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);
+       }
+
+       /* Construct wireless mode from EEPROM */
+       pCap->halWirelessModes = 0;
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
+               pCap->halWirelessModes |= HAL_MODE_11A;
+               if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
+                       pCap->halWirelessModes |= HAL_MODE_TURBO;
+       }
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
+               pCap->halWirelessModes |= HAL_MODE_11B;
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
+           ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
+               pCap->halWirelessModes |= HAL_MODE_11G;
+               if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
+                       pCap->halWirelessModes |= HAL_MODE_108G;
+       }
+
+       pCap->halLow2GhzChan = 2312;
+       /* XXX 2417 too? */
+       if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) ||  IS_2417(ah))
+               pCap->halHigh2GhzChan = 2500;
+       else
+               pCap->halHigh2GhzChan = 2732;
+
+       pCap->halLow5GhzChan = 4915;
+       pCap->halHigh5GhzChan = 6100;
+
+       pCap->halCipherCkipSupport = AH_FALSE;
+       pCap->halCipherTkipSupport = AH_TRUE;
+       pCap->halCipherAesCcmSupport =
+               (ath_hal_eepromGetFlag(ah, AR_EEP_AES) &&
+                ((AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) ||
+                 ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE) &&
+                  (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_VERSION_OAHU))));
+
+       pCap->halMicCkipSupport    = AH_FALSE;
+       pCap->halMicTkipSupport    = AH_TRUE;
+       pCap->halMicAesCcmSupport  = ath_hal_eepromGetFlag(ah, AR_EEP_AES);
+       /*
+        * Starting with Griffin TX+RX mic keys can be combined
+        * in one key cache slot.
+        */
+       if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_GRIFFIN)
+               pCap->halTkipMicTxRxKeySupport = AH_TRUE;
+       else
+               pCap->halTkipMicTxRxKeySupport = AH_FALSE;
+       pCap->halChanSpreadSupport = AH_TRUE;
+       pCap->halSleepAfterBeaconBroken = AH_TRUE;
+
+       if (ahpriv->ah_macRev > 1 || IS_COBRA(ah)) {
+               pCap->halCompressSupport   =
+                       ath_hal_eepromGetFlag(ah, AR_EEP_COMPRESS) &&
+                       (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;
+               pCap->halBurstSupport = ath_hal_eepromGetFlag(ah, AR_EEP_BURST);
+               pCap->halFastFramesSupport =
+                       ath_hal_eepromGetFlag(ah, AR_EEP_FASTFRAME) &&
+                       (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;
+               pCap->halChapTuningSupport = AH_TRUE;
+               pCap->halTurboPrimeSupport = AH_TRUE;
+       }
+       pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G;
+
+       pCap->halPSPollBroken = AH_TRUE;        /* XXX fixed in later revs? */
+       pCap->halVEOLSupport = AH_TRUE;
+       pCap->halBssIdMaskSupport = AH_TRUE;
+       pCap->halMcastKeySrchSupport = AH_TRUE;
+       if ((ahpriv->ah_macVersion == AR_SREV_VERSION_VENICE &&
+            ahpriv->ah_macRev == 8) ||
+           ahpriv->ah_macVersion > AR_SREV_VERSION_VENICE)
+               pCap->halTsfAddSupport = AH_TRUE;
+
+       if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)
+               pCap->halTotalQueues = val;
+       else
+               pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
+
+       if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK)
+               pCap->halKeyCacheSize = val;
+       else
+               pCap->halKeyCacheSize = AR_KEYTABLE_SIZE;
+
+       pCap->halChanHalfRate = AH_TRUE;
+       pCap->halChanQuarterRate = AH_TRUE;
+
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
+           ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
+               /* NB: enabled by default */
+               ahpriv->ah_rfkillEnabled = AH_TRUE;
+               pCap->halRfSilentSupport = AH_TRUE;
+       }
+
+       /* NB: this is a guess, noone seems to know the answer */
+       ahpriv->ah_rxornIsFatal =
+           (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_VENICE);
+
+       /* h/w phy counters first appeared in Hainan */
+       pCap->halHwPhyCounterSupport =
+           (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
+            AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN) ||
+           AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE;
+
+       pCap->halTstampPrecision = 15;
+
+       return AH_TRUE;
+#undef IS_COBRA
+#undef IS_GRIFFIN_LITE
+#undef AR_KEYTABLE_SIZE
+}
+
+static const char*
+ar5212Probe(uint16_t vendorid, uint16_t devid)
+{
+       if (vendorid == ATHEROS_VENDOR_ID ||
+           vendorid == ATHEROS_3COM_VENDOR_ID ||
+           vendorid == ATHEROS_3COM2_VENDOR_ID) {
+               switch (devid) {
+               case AR5212_FPGA:
+                       return "Atheros 5212 (FPGA)";
+               case AR5212_DEVID:
+               case AR5212_DEVID_IBM:
+               case AR5212_DEFAULT:
+                       return "Atheros 5212";
+               case AR5212_AR2413:
+                       return "Atheros 2413";
+               case AR5212_AR2417:
+                       return "Atheros 2417";
+               case AR5212_AR5413:
+                       return "Atheros 5413";
+               case AR5212_AR5424:
+                       return "Atheros 5424/2424";
+               }
+       }
+       return AH_NULL;
+}
+AH_CHIP(AR5212, ar5212Probe, ar5212Attach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_beacon.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_beacon.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212desc.h"
+
+/*
+ * Initialize all of the hardware registers used to
+ * send beacons.  Note that for station operation the
+ * driver calls ar5212SetStaBeaconTimers instead.
+ */
+void
+ar5212SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
+{
+
+       OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt);
+       OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba);
+       OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba);
+       OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim);
+       /*
+        * Set the Beacon register after setting all timers.
+        */
+       if (bt->bt_intval & AR_BEACON_RESET_TSF) {
+               /*
+                * When resetting the TSF,
+                * write twice to the corresponding register; each
+                * write to the RESET_TSF bit toggles the internal
+                * signal to cause a reset of the TSF - but if the signal
+                * is left high, it will reset the TSF on the next
+                * chip reset also! writing the bit an even number
+                * of times fixes this issue
+                */
+               OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_RESET_TSF);
+       }
+       OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval);
+}
+
+/*
+ * Old api for setting up beacon timer registers when
+ * operating in !station mode.  Note the fixed constants
+ * adjusting the DBA and SWBA timers and the fixed ATIM
+ * window.
+ */
+void
+ar5212BeaconInit(struct ath_hal *ah,
+       uint32_t next_beacon, uint32_t beacon_period)
+{
+       HAL_BEACON_TIMERS bt;
+
+       bt.bt_nexttbtt = next_beacon;
+       /*
+        * TIMER1: in AP/adhoc mode this controls the DMA beacon
+        * alert timer; otherwise it controls the next wakeup time.
+        * TIMER2: in AP mode, it controls the SBA beacon alert
+        * interrupt; otherwise it sets the start of the next CFP.
+        */
+       switch (AH_PRIVATE(ah)->ah_opmode) {
+       case HAL_M_STA:
+       case HAL_M_MONITOR:
+               bt.bt_nextdba = 0xffff;
+               bt.bt_nextswba = 0x7ffff;
+               break;
+       case HAL_M_HOSTAP:
+       case HAL_M_IBSS:
+               bt.bt_nextdba = (next_beacon -
+                       ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */
+               bt.bt_nextswba = (next_beacon -
+                       ath_hal_sw_beacon_response_time) << 3;  /* 1/8 TU */
+               break;
+       }
+       /*
+        * Set the ATIM window
+        * Our hardware does not support an ATIM window of 0
+        * (beacons will not work).  If the ATIM windows is 0,
+        * force it to 1.
+        */
+       bt.bt_nextatim = next_beacon + 1;
+       bt.bt_intval = beacon_period &
+               (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
+       ar5212SetBeaconTimers(ah, &bt);
+}
+
+void
+ar5212ResetStaBeaconTimers(struct ath_hal *ah)
+{
+       uint32_t val;
+
+       OS_REG_WRITE(ah, AR_TIMER0, 0);         /* no beacons */
+       val = OS_REG_READ(ah, AR_STA_ID1);
+       val |= AR_STA_ID1_PWR_SAV;              /* XXX */
+       /* tell the h/w that the associated AP is not PCF capable */
+       OS_REG_WRITE(ah, AR_STA_ID1,
+               val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF));
+       OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD);
+}
+
+/*
+ * Set all the beacon related bits on the h/w for stations
+ * i.e. initializes the corresponding h/w timers;
+ * also tells the h/w whether to anticipate PCF beacons
+ */
+void
+ar5212SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod;
+
+       HALASSERT(bs->bs_intval != 0);
+       /* if the AP will do PCF */
+       if (bs->bs_cfpmaxduration != 0) {
+               /* tell the h/w that the associated AP is PCF capable */
+               OS_REG_WRITE(ah, AR_STA_ID1,
+                       OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF);
+
+               /* set CFP_PERIOD(1.024ms) register */
+               OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod);
+
+               /* set CFP_DUR(1.024ms) register to max cfp duration */
+               OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration);
+
+               /* set TIMER2(128us) to anticipated time of next CFP */
+               OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3);
+       } else {
+               /* tell the h/w that the associated AP is not PCF capable */
+               OS_REG_WRITE(ah, AR_STA_ID1,
+                       OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF);
+       }
+
+       /*
+        * Set TIMER0(1.024ms) to the anticipated time of the next beacon.
+        */
+       OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt);
+
+       /*
+        * Start the beacon timers by setting the BEACON register
+        * to the beacon interval; also write the tim offset which
+        * we should know by now.  The code, in ar5211WriteAssocid,
+        * also sets the tim offset once the AID is known which can
+        * be left as such for now.
+        */
+       OS_REG_WRITE(ah, AR_BEACON,
+               (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM))
+               | SM(bs->bs_intval, AR_BEACON_PERIOD)
+               | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM)
+       );
+
+       /*
+        * Configure the BMISS interrupt.  Note that we
+        * assume the caller blocks interrupts while enabling
+        * the threshold.
+        */
+       HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR));
+       ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR)
+                       | SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR);
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+
+       /*
+        * Program the sleep registers to correlate with the beacon setup.
+        */
+
+       /*
+        * Oahu beacons timers on the station were used for power
+        * save operation (waking up in anticipation of a beacon)
+        * and any CFP function; Venice does sleep/power-save timers
+        * differently - so this is the right place to set them up;
+        * don't think the beacon timers are used by venice sta hw
+        * for any useful purpose anymore
+        * Setup venice's sleep related timers
+        * Current implementation assumes sw processing of beacons -
+        *   assuming an interrupt is generated every beacon which
+        *   causes the hardware to become awake until the sw tells
+        *   it to go to sleep again; beacon timeout is to allow for
+        *   beacon jitter; cab timeout is max time to wait for cab
+        *   after seeing the last DTIM or MORE CAB bit
+        */
+#define CAB_TIMEOUT_VAL     10 /* in TU */
+#define BEACON_TIMEOUT_VAL  10 /* in TU */
+#define SLEEP_SLOP          3  /* in TU */
+
+       /*
+        * For max powersave mode we may want to sleep for longer than a
+        * beacon period and not want to receive all beacons; modify the
+        * timers accordingly; make sure to align the next TIM to the
+        * next DTIM if we decide to wake for DTIMs only
+        */
+       beaconintval = bs->bs_intval & HAL_BEACON_PERIOD;
+       HALASSERT(beaconintval != 0);
+       if (bs->bs_sleepduration > beaconintval) {
+               HALASSERT(roundup(bs->bs_sleepduration, beaconintval) ==
+                               bs->bs_sleepduration);
+               beaconintval = bs->bs_sleepduration;
+       }
+       dtimperiod = bs->bs_dtimperiod;
+       if (bs->bs_sleepduration > dtimperiod) {
+               HALASSERT(dtimperiod == 0 ||
+                       roundup(bs->bs_sleepduration, dtimperiod) ==
+                               bs->bs_sleepduration);
+               dtimperiod = bs->bs_sleepduration;
+       }
+       HALASSERT(beaconintval <= dtimperiod);
+       if (beaconintval == dtimperiod)
+               nextTbtt = bs->bs_nextdtim;
+       else
+               nextTbtt = bs->bs_nexttbtt;
+       nextdtim = bs->bs_nextdtim;
+
+       OS_REG_WRITE(ah, AR_SLEEP1,
+                 SM((nextdtim - SLEEP_SLOP) << 3, AR_SLEEP1_NEXT_DTIM)
+               | SM(CAB_TIMEOUT_VAL, AR_SLEEP1_CAB_TIMEOUT)
+               | AR_SLEEP1_ASSUME_DTIM
+               | AR_SLEEP1_ENH_SLEEP_ENA
+       );
+       OS_REG_WRITE(ah, AR_SLEEP2,
+                 SM((nextTbtt - SLEEP_SLOP) << 3, AR_SLEEP2_NEXT_TIM)
+               | SM(BEACON_TIMEOUT_VAL, AR_SLEEP2_BEACON_TIMEOUT)
+       );
+       OS_REG_WRITE(ah, AR_SLEEP3,
+                 SM(beaconintval, AR_SLEEP3_TIM_PERIOD)
+               | SM(dtimperiod, AR_SLEEP3_DTIM_PERIOD)
+       );
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n",
+           __func__, bs->bs_nextdtim);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n",
+           __func__, nextTbtt);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n",
+           __func__, beaconintval);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n",
+           __func__, dtimperiod);
+#undef CAB_TIMEOUT_VAL
+#undef BEACON_TIMEOUT_VAL
+#undef SLEEP_SLOP
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_eeprom.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_eeprom.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#ifdef AH_DEBUG
+#include "ah_desc.h"                   /* NB: for HAL_PHYERR* */
+#endif
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+/*
+ * Read 16 bits of data from offset into *data
+ */
+HAL_BOOL
+ar5212EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
+{
+       OS_REG_WRITE(ah, AR_EEPROM_ADDR, off);
+       OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ);
+
+       if (!ath_hal_wait(ah, AR_EEPROM_STS,
+           AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR,
+           AR_EEPROM_STS_READ_COMPLETE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n",
+                   __func__, off);
+               return AH_FALSE;
+       }
+       *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff;
+       return AH_TRUE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_gpio.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_gpio.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#ifdef AH_DEBUG
+#include "ah_desc.h"                   /* NB: for HAL_PHYERR* */
+#endif
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#define        AR_NUM_GPIO     6               /* 6 GPIO pins */
+#define        AR_GPIOD_MASK   0x0000002F      /* GPIO data reg r/w mask */
+
+/*
+ * Configure GPIO Output lines
+ */
+HAL_BOOL
+ar5212GpioCfgOutput(struct ath_hal *ah, uint32_t gpio)
+{
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       /*
+        * NB: AR_GPIOCR_CR_A(pin) is all 1's so there's no need
+        *     to clear the field before or'ing in the new value.
+        */
+       OS_REG_WRITE(ah, AR_GPIOCR,
+                 OS_REG_READ(ah, AR_GPIOCR) | AR_GPIOCR_CR_A(gpio));
+
+       return AH_TRUE;
+}
+
+/*
+ * Configure GPIO Input lines
+ */
+HAL_BOOL
+ar5212GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
+{
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       OS_REG_WRITE(ah, AR_GPIOCR,
+                 (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_CR_A(gpio))
+               | AR_GPIOCR_CR_N(gpio));
+
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - set output lines
+ */
+HAL_BOOL
+ar5212GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
+{
+       uint32_t reg;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       reg =  OS_REG_READ(ah, AR_GPIODO);
+       reg &= ~(1 << gpio);
+       reg |= (val&1) << gpio;
+
+       OS_REG_WRITE(ah, AR_GPIODO, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - get input lines
+ */
+uint32_t
+ar5212GpioGet(struct ath_hal *ah, uint32_t gpio)
+{
+       if (gpio < AR_NUM_GPIO) {
+               uint32_t val = OS_REG_READ(ah, AR_GPIODI);
+               val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
+               return val;
+       } else  {
+               return 0xffffffff;
+       }
+}
+
+/*
+ * Set the GPIO Interrupt
+ */
+void
+ar5212GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
+{
+       uint32_t val;
+
+       /* XXX bounds check gpio */
+       val = OS_REG_READ(ah, AR_GPIOCR);
+       val &= ~(AR_GPIOCR_CR_A(gpio) |
+                AR_GPIOCR_INT_MASK | AR_GPIOCR_INT_ENA | AR_GPIOCR_INT_SEL);
+       val |= AR_GPIOCR_CR_N(gpio) | AR_GPIOCR_INT(gpio) | AR_GPIOCR_INT_ENA;
+       if (ilevel)
+               val |= AR_GPIOCR_INT_SELH;      /* interrupt on pin high */
+       else
+               val |= AR_GPIOCR_INT_SELL;      /* interrupt on pin low */
+
+       /* Don't need to change anything for low level interrupt. */
+       OS_REG_WRITE(ah, AR_GPIOCR, val);
+
+       /* Change the interrupt mask. */
+       (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_interrupts.c        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_interrupts.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+
+/*
+ * Checks to see if an interrupt is pending on our NIC
+ *
+ * Returns: TRUE    if an interrupt is pending
+ *          FALSE   if not
+ */
+HAL_BOOL
+ar5212IsInterruptPending(struct ath_hal *ah)
+{
+       /*
+        * Some platforms trigger our ISR before applying power to
+        * the card, so make sure the INTPEND is really 1, not 0xffffffff.
+        */
+       return (OS_REG_READ(ah, AR_INTPEND) == AR_INTPEND_TRUE);
+}
+
+/*
+ * Reads the Interrupt Status Register value from the NIC, thus deasserting
+ * the interrupt line, and returns both the masked and unmasked mapped ISR
+ * values.  The value returned is mapped to abstract the hw-specific bit
+ * locations in the Interrupt Status Register.
+ *
+ * Returns: A hardware-abstracted bitmap of all non-masked-out
+ *          interrupts pending, as well as an unmasked value
+ */
+HAL_BOOL
+ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)
+{
+       uint32_t isr, isr0, isr1;
+       uint32_t mask2=0;
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       isr = OS_REG_READ(ah, AR_ISR);
+       if (isr & AR_ISR_BCNMISC) {
+               uint32_t isr2;
+               isr2 = OS_REG_READ(ah, AR_ISR_S2);
+               if (isr2 & AR_ISR_S2_TIM)
+                       mask2 |= HAL_INT_TIM;
+               if (isr2 & AR_ISR_S2_DTIM)
+                       mask2 |= HAL_INT_DTIM;
+               if (isr2 & AR_ISR_S2_DTIMSYNC)
+                       mask2 |= HAL_INT_DTIMSYNC;
+               if (isr2 & (AR_ISR_S2_CABEND ))
+                       mask2 |= HAL_INT_CABEND;
+       }
+       isr = OS_REG_READ(ah, AR_ISR_RAC);
+       if (isr == 0xffffffff) {
+               *masked = 0;
+               return AH_FALSE;;
+       }
+
+       *masked = isr & HAL_INT_COMMON;
+
+       if (isr & AR_ISR_HIUERR)
+               *masked |= HAL_INT_FATAL;
+       if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+               *masked |= HAL_INT_RX;
+       if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) {
+               *masked |= HAL_INT_TX;
+               isr0 = OS_REG_READ(ah, AR_ISR_S0_S);
+               ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK);
+               ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC);
+               isr1 = OS_REG_READ(ah, AR_ISR_S1_S);
+               ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR);
+               ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL);
+       }
+
+       /*
+        * Receive overrun is usually non-fatal on Oahu/Spirit.
+        * BUT on some parts rx could fail and the chip must be reset.
+        * So we force a hardware reset in all cases.
+        */
+       if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: receive FIFO overrun interrupt\n", __func__);
+               *masked |= HAL_INT_FATAL;
+       }
+       *masked |= mask2;
+
+       /*
+        * On fatal errors collect ISR state for debugging.
+        */
+       if (*masked & HAL_INT_FATAL) {
+               AH_PRIVATE(ah)->ah_fatalState[0] = isr;
+               AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S);
+               AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S);
+               AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S);
+               AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S);
+               AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S);
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n",
+                   __func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]);
+       }
+       return AH_TRUE;
+}
+
+HAL_INT
+ar5212GetInterrupts(struct ath_hal *ah)
+{
+       return AH5212(ah)->ah_maskReg;
+}
+
+/*
+ * Atomically enables NIC interrupts.  Interrupts are passed in
+ * via the enumerated bitmask in ints.
+ */
+HAL_INT
+ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t omask = ahp->ah_maskReg;
+       uint32_t mask,mask2;
+
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",
+           __func__, omask, ints);
+
+       if (omask & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+               (void) OS_REG_READ(ah, AR_IER);   /* flush write to HW */
+       }
+
+       mask = ints & HAL_INT_COMMON;
+       mask2 = 0;
+       if (ints & HAL_INT_TX) {
+               if (ahp->ah_txOkInterruptMask)
+                       mask |= AR_IMR_TXOK;
+               if (ahp->ah_txErrInterruptMask)
+                       mask |= AR_IMR_TXERR;
+               if (ahp->ah_txDescInterruptMask)
+                       mask |= AR_IMR_TXDESC;
+               if (ahp->ah_txEolInterruptMask)
+                       mask |= AR_IMR_TXEOL;
+       }
+       if (ints & HAL_INT_RX)
+               mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC;
+       if (ints & (HAL_INT_BMISC)) {
+               mask |= AR_IMR_BCNMISC;
+               if (ints & HAL_INT_TIM)
+                       mask2 |= AR_IMR_S2_TIM;
+               if (ints & HAL_INT_DTIM)
+                       mask2 |= AR_IMR_S2_DTIM;
+               if (ints & HAL_INT_DTIMSYNC)
+                       mask2 |= AR_IMR_S2_DTIMSYNC;
+               if (ints & HAL_INT_CABEND)
+                       mask2 |= (AR_IMR_S2_CABEND );
+       }
+       if (ints & HAL_INT_FATAL) {
+               /*
+                * NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2
+                *     so enabling HIUERR enables delivery.
+                */
+               mask |= AR_IMR_HIUERR;
+       }
+
+       /* Write the new IMR and store off our SW copy. */
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
+       OS_REG_WRITE(ah, AR_IMR, mask);
+       OS_REG_WRITE(ah, AR_IMR_S2,
+                                (OS_REG_READ(ah, AR_IMR_S2) &
+                                 ~(AR_IMR_S2_TIM |
+                                       AR_IMR_S2_DTIM |
+                                       AR_IMR_S2_DTIMSYNC |
+                                       AR_IMR_S2_CABEND |
+                                       AR_IMR_S2_CABTO  |
+                                       AR_IMR_S2_TSFOOR ) )
+                                | mask2);
+       ahp->ah_maskReg = ints;
+
+       /* Re-enable interrupts if they were enabled before. */
+       if (ints & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+       }
+
+
+       return omask;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_keycache.c  2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_keycache.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212desc.h"
+
+/*
+ * Note: The key cache hardware requires that each double-word
+ * pair be written in even/odd order (since the destination is
+ * a 64-bit register).  Don't reorder the writes in this code
+ * w/o considering this!
+ */
+#define        KEY_XOR                 0xaa
+
+#define        IS_MIC_ENABLED(ah) \
+       (AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
+
+/*
+ * Return the size of the hardware key cache.
+ */
+uint32_t
+ar5212GetKeyCacheSize(struct ath_hal *ah)
+{
+       return AH_PRIVATE(ah)->ah_caps.halKeyCacheSize;
+}
+
+/*
+ * Return true if the specific key cache entry is valid.
+ */
+HAL_BOOL
+ar5212IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry)
+{
+       if (entry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
+               uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
+               if (val & AR_KEYTABLE_VALID)
+                       return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Clear the specified key cache entry and any associated MIC entry.
+ */
+HAL_BOOL
+ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
+{
+       uint32_t keyType;
+
+       if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n",
+                   __func__, entry);
+               return AH_FALSE;
+       }
+       keyType = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry));
+
+       /* XXX why not clear key type/valid bit first? */
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+       OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+       OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+       OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+       if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
+               uint16_t micentry = entry+64;   /* MIC goes at slot+64 */
+
+               HALASSERT(micentry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+               /* NB: key type and MAC are known to be ok */
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Sets the mac part of the specified key cache entry (and any
+ * associated MIC entry) and mark them valid.
+ */
+HAL_BOOL
+ar5212SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac)
+{
+       uint32_t macHi, macLo;
+
+       if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n",
+                   __func__, entry);
+               return AH_FALSE;
+       }
+       /*
+        * Set MAC address -- shifted right by 1.  MacLo is
+        * the 4 MSBs, and MacHi is the 2 LSBs.
+        */
+       if (mac != AH_NULL) {
+               macHi = (mac[5] << 8) | mac[4];
+               macLo = (mac[3] << 24)| (mac[2] << 16)
+                     | (mac[1] << 8) | mac[0];
+               macLo >>= 1;
+               macLo |= (macHi & 1) << 31;     /* carry */
+               macHi >>= 1;
+       } else {
+               macLo = macHi = 0;
+       }
+       OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+       OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
+       return AH_TRUE;
+}
+
+/*
+ * Sets the contents of the specified key cache entry
+ * and any associated MIC entry.
+ */
+HAL_BOOL
+ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
+                       const HAL_KEYVAL *k, const uint8_t *mac,
+                       int xorKey)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+       uint32_t key0, key1, key2, key3, key4;
+       uint32_t keyType;
+       uint32_t xorMask = xorKey ?
+               (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
+
+       if (entry >= pCap->halKeyCacheSize) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n",
+                   __func__, entry);
+               return AH_FALSE;
+       }
+       switch (k->kv_type) {
+       case HAL_CIPHER_AES_OCB:
+               keyType = AR_KEYTABLE_TYPE_AES;
+               break;
+       case HAL_CIPHER_AES_CCM:
+               if (!pCap->halCipherAesCcmSupport) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: AES-CCM not supported by mac rev 0x%x\n",
+                           __func__, AH_PRIVATE(ah)->ah_macRev);
+                       return AH_FALSE;
+               }
+               keyType = AR_KEYTABLE_TYPE_CCM;
+               break;
+       case HAL_CIPHER_TKIP:
+               keyType = AR_KEYTABLE_TYPE_TKIP;
+               if (IS_MIC_ENABLED(ah) && entry+64 >= pCap->halKeyCacheSize) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: entry %u inappropriate for TKIP\n",
+                           __func__, entry);
+                       return AH_FALSE;
+               }
+               break;
+       case HAL_CIPHER_WEP:
+               if (k->kv_len < 40 / NBBY) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: WEP key length %u too small\n",
+                           __func__, k->kv_len);
+                       return AH_FALSE;
+               }
+               if (k->kv_len <= 40 / NBBY)
+                       keyType = AR_KEYTABLE_TYPE_40;
+               else if (k->kv_len <= 104 / NBBY)
+                       keyType = AR_KEYTABLE_TYPE_104;
+               else
+                       keyType = AR_KEYTABLE_TYPE_128;
+               break;
+       case HAL_CIPHER_CLR:
+               keyType = AR_KEYTABLE_TYPE_CLR;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n",
+                   __func__, k->kv_type);
+               return AH_FALSE;
+       }
+
+       key0 = LE_READ_4(k->kv_val+0) ^ xorMask;
+       key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff;
+       key2 = LE_READ_4(k->kv_val+6) ^ xorMask;
+       key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff;
+       key4 = LE_READ_4(k->kv_val+12) ^ xorMask;
+       if (k->kv_len <= 104 / NBBY)
+               key4 &= 0xff;
+
+       /*
+        * Note: key cache hardware requires that each double-word
+        * pair be written in even/odd order (since the destination is
+        * a 64-bit register).  Don't reorder these writes w/o
+        * considering this!
+        */
+       if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
+               uint16_t micentry = entry+64;   /* MIC goes at slot+64 */
+               uint32_t mic0, mic1, mic2, mic3, mic4;
+
+               /*
+                * Invalidate the encrypt/decrypt key until the MIC
+                * key is installed so pending rx frames will fail
+                * with decrypt errors rather than a MIC error.
+                */
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+               OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+               (void) ar5212SetKeyCacheEntryMac(ah, entry, mac);
+
+
+               /*
+                * Write MIC entry according to new or old key layout.
+                * The MISC_MODE register is assumed already set so
+                * these writes will be handled properly (happens on
+                * attach and at every reset).
+                */
+               /* RX mic */
+               mic0 = LE_READ_4(k->kv_mic+0);
+               mic2 = LE_READ_4(k->kv_mic+4);
+               if (ahp->ah_miscMode & AR_MISC_MODE_MIC_NEW_LOC_ENABLE) {
+                       /*
+                        * Both RX and TX mic values can be combined into
+                        * one cache slot entry:
+                        *  8*N + 800         31:0    RX Michael key 0
+                        *  8*N + 804         15:0    TX Michael key 0 [31:16]
+                        *  8*N + 808         31:0    RX Michael key 1
+                        *  8*N + 80C         15:0    TX Michael key 0 [15:0]
+                        *  8*N + 810         31:0    TX Michael key 1
+                        *  8*N + 814         15:0    reserved
+                        *  8*N + 818         31:0    reserved
+                        *  8*N + 81C         14:0    reserved
+                        *                    15      key valid == 0
+                        */
+                       /* TX mic */
+                       mic1 = LE_READ_2(k->kv_txmic+2) & 0xffff;
+                       mic3 = LE_READ_2(k->kv_txmic+0) & 0xffff;
+                       mic4 = LE_READ_4(k->kv_txmic+4);
+               } else {
+                       mic1 = mic3 = mic4 = 0;
+               }
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
+               OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+                       AR_KEYTABLE_TYPE_CLR);
+               /* NB: MIC key is not marked valid and has no MAC address */
+               OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
+
+               /* correct intentionally corrupted key */
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+       } else {
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+               OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+               (void) ar5212SetKeyCacheEntryMac(ah, entry, mac);
+       }
+       return AH_TRUE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_misc.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,1074 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_misc.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#ifdef AH_DEBUG
+#include "ah_desc.h"                   /* NB: for HAL_PHYERR* */
+#endif
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#include "ah_eeprom_v3.h"
+
+#define        AR_NUM_GPIO     6               /* 6 GPIO pins */
+#define        AR_GPIOD_MASK   0x0000002F      /* GPIO data reg r/w mask */
+
+extern void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *);
+
+void
+ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
+}
+
+HAL_BOOL
+ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
+       return AH_TRUE;
+}
+
+void
+ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN);
+}
+
+HAL_BOOL
+ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       /* save it since it must be rewritten on reset */
+       OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN);
+
+       OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
+       OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
+       return AH_TRUE;
+}
+
+/*
+ * Attempt to change the cards operating regulatory domain to the given value
+ */
+HAL_BOOL
+ar5212SetRegulatoryDomain(struct ath_hal *ah,
+       uint16_t regDomain, HAL_STATUS *status)
+{
+       HAL_STATUS ecode;
+
+       if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
+               ecode = HAL_EINVAL;
+               goto bad;
+       }
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
+               ecode = HAL_EEWRITE;
+               goto bad;
+       }
+#ifdef AH_SUPPORT_WRITE_REGDOMAIN
+       if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: set regulatory domain to %u (0x%x)\n",
+                   __func__, regDomain, regDomain);
+               AH_PRIVATE(ah)->ah_currentRD = regDomain;
+               return AH_TRUE;
+       }
+#endif
+       ecode = HAL_EIO;
+bad:
+       if (status)
+               *status = ecode;
+       return AH_FALSE;
+}
+
+/*
+ * Return the wireless modes (a,b,g,t) supported by hardware.
+ *
+ * This value is what is actually supported by the hardware
+ * and is unaffected by regulatory/country code settings.
+ */
+u_int
+ar5212GetWirelessModes(struct ath_hal *ah)
+{
+       u_int mode = 0;
+
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
+               mode = HAL_MODE_11A;
+               if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
+                       mode |= HAL_MODE_TURBO | HAL_MODE_108A;
+               if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
+                       mode |= HAL_MODE_11A_HALF_RATE;
+               if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
+                       mode |= HAL_MODE_11A_QUARTER_RATE;
+       }
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
+               mode |= HAL_MODE_11B;
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
+           AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
+               mode |= HAL_MODE_11G;
+               if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
+                       mode |= HAL_MODE_108G;
+               if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
+                       mode |= HAL_MODE_11G_HALF_RATE;
+               if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
+                       mode |= HAL_MODE_11G_QUARTER_RATE;
+       }
+       return mode;
+}
+
+/*
+ * Set the interrupt and GPIO values so the ISR can disable RF
+ * on a switch signal.  Assumes GPIO port and interrupt polarity
+ * are set prior to call.
+ */
+void
+ar5212EnableRfKill(struct ath_hal *ah)
+{
+       uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
+       int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
+       int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
+
+       /*
+        * Configure the desired GPIO port for input
+        * and enable baseband rf silence.
+        */
+       ath_hal_gpioCfgInput(ah, select);
+       OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000);
+       /*
+        * If radio disable switch connection to GPIO bit x is enabled
+        * program GPIO interrupt.
+        * If rfkill bit on eeprom is 1, setupeeprommap routine has already
+        * verified that it is a later version of eeprom, it has a place for
+        * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
+        * connection is present.
+        */
+       ath_hal_gpioSetIntr(ah, select,
+           (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity));
+}
+
+/*
+ * Change the LED blinking pattern to correspond to the connectivity
+ */
+void
+ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
+{
+       static const uint32_t ledbits[8] = {
+               AR_PCICFG_LEDCTL_NONE,  /* HAL_LED_INIT */
+               AR_PCICFG_LEDCTL_PEND,  /* HAL_LED_SCAN */
+               AR_PCICFG_LEDCTL_PEND,  /* HAL_LED_AUTH */
+               AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/
+               AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */
+               AR_PCICFG_LEDCTL_NONE,
+               AR_PCICFG_LEDCTL_NONE,
+               AR_PCICFG_LEDCTL_NONE,
+       };
+       uint32_t bits;
+
+       bits = OS_REG_READ(ah, AR_PCICFG);
+       if (IS_2417(ah)) {
+               /*
+                * Enable LED for Nala. There is a bit marked reserved
+                * that must be set and we also turn on the power led.
+                * Because we mark s/w LED control setting the control
+                * status bits below is meangless (the driver must flash
+                * the LED(s) using the GPIO lines).
+                */
+               bits = (bits &~ AR_PCICFG_LEDMODE)
+                    | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE)
+#if 0
+                    | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE)
+#endif
+                    | 0x08000000;
+       }
+       bits = (bits &~ AR_PCICFG_LEDCTL)
+            | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL);
+       OS_REG_WRITE(ah, AR_PCICFG, bits);
+}
+
+/*
+ * Change association related fields programmed into the hardware.
+ * Writing a valid BSSID to the hardware effectively enables the hardware
+ * to synchronize its TSF to the correct beacons and receive frames coming
+ * from that BSSID. It is called by the SME JOIN operation.
+ */
+void
+ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       /* XXX save bssid for possible re-use on reset */
+       OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
+                                    ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
+}
+
+/*
+ * Get the current hardware tsf for stamlme
+ */
+uint64_t
+ar5212GetTsf64(struct ath_hal *ah)
+{
+       uint32_t low1, low2, u32;
+
+       /* sync multi-word read */
+       low1 = OS_REG_READ(ah, AR_TSF_L32);
+       u32 = OS_REG_READ(ah, AR_TSF_U32);
+       low2 = OS_REG_READ(ah, AR_TSF_L32);
+       if (low2 < low1) {      /* roll over */
+               /*
+                * If we are not preempted this will work.  If we are
+                * then we re-reading AR_TSF_U32 does no good as the
+                * low bits will be meaningless.  Likewise reading
+                * L32, U32, U32, then comparing the last two reads
+                * to check for rollover doesn't help if preempted--so
+                * we take this approach as it costs one less PCI read
+                * which can be noticeable when doing things like
+                * timestamping packets in monitor mode.
+                */
+               u32++;
+       }
+       return (((uint64_t) u32) << 32) | ((uint64_t) low2);
+}
+
+/*
+ * Get the current hardware tsf for stamlme
+ */
+uint32_t
+ar5212GetTsf32(struct ath_hal *ah)
+{
+       return OS_REG_READ(ah, AR_TSF_L32);
+}
+
+/*
+ * Reset the current hardware tsf for stamlme.
+ */
+void
+ar5212ResetTsf(struct ath_hal *ah)
+{
+
+       uint32_t val = OS_REG_READ(ah, AR_BEACON);
+
+       OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
+       /*
+        * When resetting the TSF, write twice to the
+        * corresponding register; each write to the RESET_TSF bit toggles
+        * the internal signal to cause a reset of the TSF - but if the signal
+        * is left high, it will reset the TSF on the next chip reset also!
+        * writing the bit an even number of times fixes this issue
+        */
+       OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
+}
+
+/*
+ * Set or clear hardware basic rate bit
+ * Set hardware basic rate set if basic rate is found
+ * and basic rate is equal or less than 2Mbps
+ */
+void
+ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs)
+{
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       uint32_t reg;
+       uint8_t xset;
+       int i;
+
+       if (chan == AH_NULL || !IS_CHAN_CCK(chan))
+               return;
+       xset = 0;
+       for (i = 0; i < rs->rs_count; i++) {
+               uint8_t rset = rs->rs_rates[i];
+               /* Basic rate defined? */
+               if ((rset & 0x80) && (rset &= 0x7f) >= xset)
+                       xset = rset;
+       }
+       /*
+        * Set the h/w bit to reflect whether or not the basic
+        * rate is found to be equal or less than 2Mbps.
+        */
+       reg = OS_REG_READ(ah, AR_STA_ID1);
+       if (xset && xset/2 <= 2)
+               OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B);
+       else
+               OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B);
+}
+
+/*
+ * Grab a semi-random value from hardware registers - may not
+ * change often
+ */
+uint32_t
+ar5212GetRandomSeed(struct ath_hal *ah)
+{
+       uint32_t nf;
+
+       nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
+       if (nf & 0x100)
+               nf = 0 - ((nf ^ 0x1ff) + 1);
+       return (OS_REG_READ(ah, AR_TSF_U32) ^
+               OS_REG_READ(ah, AR_TSF_L32) ^ nf);
+}
+
+/*
+ * Detect if our card is present
+ */
+HAL_BOOL
+ar5212DetectCardPresent(struct ath_hal *ah)
+{
+       uint16_t macVersion, macRev;
+       uint32_t v;
+
+       /*
+        * Read the Silicon Revision register and compare that
+        * to what we read at attach time.  If the same, we say
+        * a card/device is present.
+        */
+       v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
+       macVersion = v >> AR_SREV_ID_S;
+       macRev = v & AR_SREV_REVISION;
+       return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
+               AH_PRIVATE(ah)->ah_macRev == macRev);
+}
+
+void
+ar5212EnableMibCounters(struct ath_hal *ah)
+{
+       /* NB: this just resets the mib counter machinery */
+       OS_REG_WRITE(ah, AR_MIBC,
+           ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f);
+}
+
+void
+ar5212DisableMibCounters(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_MIBC,  AR_MIBC | AR_MIBC_CMC);
+}
+
+/*
+ * Update MIB Counters
+ */
+void
+ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats)
+{
+       stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
+       stats->rts_bad    += OS_REG_READ(ah, AR_RTS_FAIL);
+       stats->fcs_bad    += OS_REG_READ(ah, AR_FCS_FAIL);
+       stats->rts_good   += OS_REG_READ(ah, AR_RTS_OK);
+       stats->beacons    += OS_REG_READ(ah, AR_BEACON_CNT);
+}
+
+/*
+ * Detect if the HW supports spreading a CCK signal on channel 14
+ */
+HAL_BOOL
+ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah)
+{
+       return AH_TRUE;
+}
+
+/*
+ * Get the rssi of frame curently being received.
+ */
+uint32_t
+ar5212GetCurRssi(struct ath_hal *ah)
+{
+       return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
+}
+
+u_int
+ar5212GetDefAntenna(struct ath_hal *ah)
+{
+       return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
+}
+
+void
+ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna)
+{
+       OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
+}
+
+HAL_ANT_SETTING
+ar5212GetAntennaSwitch(struct ath_hal *ah)
+{
+       return AH5212(ah)->ah_antControl;
+}
+
+HAL_BOOL
+ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_CHANNEL_INTERNAL *ichan = AH_PRIVATE(ah)->ah_curchan;
+
+       if (!ahp->ah_phyPowerOn || ichan == AH_NULL) {
+               /* PHY powered off, just stash settings */
+               ahp->ah_antControl = setting;
+               ahp->ah_diversity = (setting == HAL_ANT_VARIABLE);
+               return AH_TRUE;
+       }
+       return ar5212SetAntennaSwitchInternal(ah, setting, ichan);
+}
+
+HAL_BOOL
+ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah)
+{
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5212SetSifsTime(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       if (us > ath_hal_mac_usec(ah, 0xffff)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
+                   __func__, us);
+               ahp->ah_sifstime = (u_int) -1;  /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us));
+               ahp->ah_slottime = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5212GetSifsTime(struct ath_hal *ah)
+{
+       u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+HAL_BOOL
+ar5212SetSlotTime(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
+                   __func__, us);
+               ahp->ah_slottime = (u_int) -1;  /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
+               ahp->ah_slottime = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5212GetSlotTime(struct ath_hal *ah)
+{
+       u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+HAL_BOOL
+ar5212SetAckTimeout(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
+                   __func__, us);
+               ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
+                       AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
+               ahp->ah_acktimeout = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5212GetAckTimeout(struct ath_hal *ah)
+{
+       u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+u_int
+ar5212GetAckCTSRate(struct ath_hal *ah)
+{
+       return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
+}
+
+HAL_BOOL
+ar5212SetAckCTSRate(struct ath_hal *ah, u_int high)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       if (high) {
+               OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
+               ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
+       } else {
+               OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
+               ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5212SetCTSTimeout(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
+                   __func__, us);
+               ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
+                       AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
+               ahp->ah_ctstimeout = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5212GetCTSTimeout(struct ath_hal *ah)
+{
+       u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+/* Setup decompression for given key index */
+HAL_BOOL
+ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+        if (keyidx >= HAL_DECOMP_MASK_SIZE)
+                return HAL_EINVAL;
+        OS_REG_WRITE(ah, AR_DCM_A, keyidx);
+        OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0);
+        ahp->ah_decompMask[keyidx] = en;
+
+        return AH_TRUE;
+}
+
+/* Setup coverage class */
+void
+ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
+{
+       uint32_t slot, timeout, eifs;
+       u_int clkRate;
+
+       AH_PRIVATE(ah)->ah_coverageClass = coverageclass;
+
+       if (now) {
+               if (AH_PRIVATE(ah)->ah_coverageClass == 0)
+                       return;
+
+               /* Don't apply coverage class to non A channels */
+               if (!IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan))
+                       return;
+
+               /* Get core clock rate */
+               clkRate = ath_hal_mac_clks(ah, 1);
+
+               /* Compute EIFS */
+               slot = coverageclass * 3 * clkRate;
+               eifs = coverageclass * 6 * clkRate;
+               if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+                       slot += IFS_SLOT_HALF_RATE;
+                       eifs += IFS_EIFS_HALF_RATE;
+               } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+                       slot += IFS_SLOT_QUARTER_RATE;
+                       eifs += IFS_EIFS_QUARTER_RATE;
+               } else { /* full rate */
+                       slot += IFS_SLOT_FULL_RATE;
+                       eifs += IFS_EIFS_FULL_RATE;
+               }
+
+               /*
+                * Add additional time for air propagation for ACK and CTS
+                * timeouts. This value is in core clocks.
+                */
+               timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate);
+
+               /*
+                * Write the values: slot, eifs, ack/cts timeouts.
+                */
+               OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
+               OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
+               OS_REG_WRITE(ah, AR_TIME_OUT,
+                         SM(timeout, AR_TIME_OUT_CTS)
+                       | SM(timeout, AR_TIME_OUT_ACK));
+       }
+}
+
+void
+ar5212SetPCUConfig(struct ath_hal *ah)
+{
+       ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
+}
+
+/*
+ * Return whether an external 32KHz crystal should be used
+ * to reduce power consumption when sleeping.  We do so if
+ * the crystal is present (obtained from EEPROM) and if we
+ * are not running as an AP and are configured to use it.
+ */
+HAL_BOOL
+ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode)
+{
+       if (opmode != HAL_M_HOSTAP) {
+               struct ath_hal_5212 *ahp = AH5212(ah);
+               return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) &&
+                      (ahp->ah_enable32kHzClock == USE_32KHZ ||
+                       ahp->ah_enable32kHzClock == AUTO_32KHZ);
+       } else
+               return AH_FALSE;
+}
+
+/*
+ * If 32KHz clock exists, use it to lower power consumption during sleep
+ *
+ * Note: If clock is set to 32 KHz, delays on accessing certain
+ *       baseband registers (27-31, 124-127) are required.
+ */
+void
+ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode)
+{
+       if (ar5212Use32KHzclock(ah, opmode)) {
+               /*
+                * Enable clocks to be turned OFF in BB during sleep
+                * and also enable turning OFF 32MHz/40MHz Refclk
+                * from A2.
+                */
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
+               OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
+                   IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18);
+               OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1);
+               OS_REG_WRITE(ah, AR_TSF_PARM, 61);  /* 32 KHz TSF incr */
+               OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1);
+
+               if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) {
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x26);
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0d);
+                       OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x07);
+                       OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0x3f);
+                       /* # Set sleep clock rate to 32 KHz. */
+                       OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x0a);
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0c);
+                       OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x03);
+                       OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0x20);
+                       OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3);
+               }
+       } else {
+               OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0);
+               OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
+
+               OS_REG_WRITE(ah, AR_TSF_PARM, 1);       /* 32MHz TSF inc */
+
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x7f);
+
+               if (IS_2417(ah))
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a);
+               else if (IS_HB63(ah))
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32);
+               else
+                       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
+               OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x0c);
+               OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0xff);
+               OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
+                   IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18);
+               OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
+                   IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
+       }
+}
+
+/*
+ * If 32KHz clock exists, turn it off and turn back on the 32Mhz
+ */
+void
+ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode)
+{
+       if (ar5212Use32KHzclock(ah, opmode)) {
+               /* # Set sleep clock rate back to 32 MHz. */
+               OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0);
+               OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
+
+               OS_REG_WRITE(ah, AR_TSF_PARM, 1);       /* 32 MHz TSF incr */
+               OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
+                   IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
+
+               /*
+                * Restore BB registers to power-on defaults
+                */
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT,   0x7f);
+               OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL,        0x0e);
+               OS_REG_WRITE(ah, AR_PHY_M_SLEEP,           0x0c);
+               OS_REG_WRITE(ah, AR_PHY_REFCLKDLY,         0xff);
+               OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
+                   IS_RAD5112_ANY(ah) || IS_5413(ah) ?  0x14 : 0x18);
+       }
+}
+
+/*
+ * Adjust NF based on statistical values for 5GHz frequencies.
+ * Default method: this may be overridden by the rf backend.
+ */
+int16_t
+ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
+{
+       static const struct {
+               uint16_t freqLow;
+               int16_t   adjust;
+       } adjustDef[] = {
+               { 5790, 11 },   /* NB: ordered high -> low */
+               { 5730, 10 },
+               { 5690,  9 },
+               { 5660,  8 },
+               { 5610,  7 },
+               { 5530,  5 },
+               { 5450,  4 },
+               { 5379,  2 },
+               { 5209,  0 },
+               { 3000,  1 },
+               {    0,  0 },
+       };
+       int i;
+
+       for (i = 0; c->channel <= adjustDef[i].freqLow; i++)
+               ;
+       return adjustDef[i].adjust;
+}
+
+HAL_STATUS
+ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+       uint32_t capability, uint32_t *result)
+{
+#define        MACVERSION(ah)  AH_PRIVATE(ah)->ah_macVersion
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+       const struct ar5212AniState *ani;
+
+       switch (type) {
+       case HAL_CAP_CIPHER:            /* cipher handled in hardware */
+               switch (capability) {
+               case HAL_CIPHER_AES_CCM:
+                       return pCap->halCipherAesCcmSupport ?
+                               HAL_OK : HAL_ENOTSUPP;
+               case HAL_CIPHER_AES_OCB:
+               case HAL_CIPHER_TKIP:
+               case HAL_CIPHER_WEP:
+               case HAL_CIPHER_MIC:
+               case HAL_CIPHER_CLR:
+                       return HAL_OK;
+               default:
+                       return HAL_ENOTSUPP;
+               }
+       case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
+               switch (capability) {
+               case 0:                 /* hardware capability */
+                       return HAL_OK;
+               case 1:
+                       return (ahp->ah_staId1Defaults &
+                           AR_STA_ID1_CRPT_MIC_ENABLE) ?  HAL_OK : HAL_ENXIO;
+               }
+       case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
+               switch (capability) {
+               case 0:                 /* hardware capability */
+                       return pCap->halTkipMicTxRxKeySupport ?
+                               HAL_ENXIO : HAL_OK;
+               case 1:                 /* current setting */
+                       return (ahp->ah_miscMode &
+                           AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK;
+               }
+               return HAL_EINVAL;
+       case HAL_CAP_WME_TKIPMIC:       /* hardware can do TKIP MIC w/ WMM */
+               /* XXX move to capability bit */
+               return MACVERSION(ah) > AR_SREV_VERSION_VENICE ||
+                   (MACVERSION(ah) == AR_SREV_VERSION_VENICE &&
+                    AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_DIVERSITY:         /* hardware supports fast diversity */
+               switch (capability) {
+               case 0:                 /* hardware capability */
+                       return HAL_OK;
+               case 1:                 /* current setting */
+                       return ahp->ah_diversity ? HAL_OK : HAL_ENXIO;
+               }
+               return HAL_EINVAL;
+       case HAL_CAP_DIAG:
+               *result = AH_PRIVATE(ah)->ah_diagreg;
+               return HAL_OK;
+       case HAL_CAP_TPC:
+               switch (capability) {
+               case 0:                 /* hardware capability */
+                       return HAL_OK;
+               case 1:
+                       return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO;
+               }
+               return HAL_OK;
+       case HAL_CAP_PHYDIAG:           /* radar pulse detection capability */
+               switch (capability) {
+               case HAL_CAP_RADAR:
+                       return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ?
+                           HAL_OK: HAL_ENXIO;
+               case HAL_CAP_AR:
+                       return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) ||
+                           ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ?
+                              HAL_OK: HAL_ENXIO;
+               }
+               return HAL_ENXIO;
+       case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
+               switch (capability) {
+               case 0:                 /* hardware capability */
+                       return HAL_OK;
+               case 1:
+                       return (ahp->ah_staId1Defaults &
+                           AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO;
+               }
+               return HAL_EINVAL;
+       case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
+               switch (capability) {
+               case 0:                 /* hardware capability */
+                       return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP;
+               case 1:
+                       return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ?
+                               HAL_OK : HAL_ENXIO;
+               }
+               return HAL_EINVAL;
+       case HAL_CAP_TPC_ACK:
+               *result = MS(ahp->ah_macTPC, AR_TPC_ACK);
+               return HAL_OK;
+       case HAL_CAP_TPC_CTS:
+               *result = MS(ahp->ah_macTPC, AR_TPC_CTS);
+               return HAL_OK;
+       case HAL_CAP_INTMIT:            /* interference mitigation */
+               switch (capability) {
+               case 0:                 /* hardware capability */
+                       return HAL_OK;
+               case 1:
+                       return (ahp->ah_procPhyErr & HAL_ANI_ENA) ?
+                               HAL_OK : HAL_ENXIO;
+               case 2:                 /* HAL_ANI_NOISE_IMMUNITY_LEVEL */
+               case 3:                 /* HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION */
+               case 4:                 /* HAL_ANI_CCK_WEAK_SIGNAL_THR */
+               case 5:                 /* HAL_ANI_FIRSTEP_LEVEL */
+               case 6:                 /* HAL_ANI_SPUR_IMMUNITY_LEVEL */
+                       ani = ar5212AniGetCurrentState(ah);
+                       if (ani == AH_NULL)
+                               return HAL_ENXIO;
+                       switch (capability) {
+                       case 2: *result = ani->noiseImmunityLevel; break;
+                       case 3: *result = !ani->ofdmWeakSigDetectOff; break;
+                       case 4: *result = ani->cckWeakSigThreshold; break;
+                       case 5: *result = ani->firstepLevel; break;
+                       case 6: *result = ani->spurImmunityLevel; break;
+                       }
+                       return HAL_OK;
+               }
+               return HAL_EINVAL;
+       default:
+               return ath_hal_getcapability(ah, type, capability, result);
+       }
+#undef MACVERSION
+}
+
+HAL_BOOL
+ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+       uint32_t capability, uint32_t setting, HAL_STATUS *status)
+{
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+       uint32_t v;
+
+       switch (type) {
+       case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
+               if (setting)
+                       ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE;
+               else
+                       ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE;
+               return AH_TRUE;
+       case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
+               if (!pCap->halTkipMicTxRxKeySupport)
+                       return AH_FALSE;
+               /* NB: true =>'s use split key cache layout */
+               if (setting)
+                       ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
+               else
+                       ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
+               /* NB: write here so keys can be setup w/o a reset */
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+               return AH_TRUE;
+       case HAL_CAP_DIVERSITY:
+               if (ahp->ah_phyPowerOn) {
+                       v = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
+                       if (setting)
+                               v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+                       else
+                               v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+                       OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+               }
+               ahp->ah_diversity = (setting != 0);
+               return AH_TRUE;
+       case HAL_CAP_DIAG:              /* hardware diagnostic support */
+               /*
+                * NB: could split this up into virtual capabilities,
+                *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
+                *     seems worth the additional complexity.
+                */
+               AH_PRIVATE(ah)->ah_diagreg = setting;
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+               return AH_TRUE;
+       case HAL_CAP_TPC:
+               ahp->ah_tpcEnabled = (setting != 0);
+               return AH_TRUE;
+       case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
+               if (setting)
+                       ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
+               else
+                       ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
+               return AH_TRUE;
+       case HAL_CAP_TPC_ACK:
+       case HAL_CAP_TPC_CTS:
+               setting += ahp->ah_txPowerIndexOffset;
+               if (setting > 63)
+                       setting = 63;
+               if (type == HAL_CAP_TPC_ACK) {
+                       ahp->ah_macTPC &= AR_TPC_ACK;
+                       ahp->ah_macTPC |= MS(setting, AR_TPC_ACK);
+               } else {
+                       ahp->ah_macTPC &= AR_TPC_CTS;
+                       ahp->ah_macTPC |= MS(setting, AR_TPC_CTS);
+               }
+               OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC);
+               return AH_TRUE;
+       case HAL_CAP_INTMIT: {          /* interference mitigation */
+               static const HAL_ANI_CMD cmds[] = {
+                       HAL_ANI_PRESENT,
+                       HAL_ANI_MODE,
+                       HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                       HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                       HAL_ANI_CCK_WEAK_SIGNAL_THR,
+                       HAL_ANI_FIRSTEP_LEVEL,
+                       HAL_ANI_SPUR_IMMUNITY_LEVEL,
+               };
+               return capability < N(cmds) ?
+                       ar5212AniControl(ah, cmds[capability], setting) :
+                       AH_FALSE;
+       }
+       case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
+               if (pCap->halTsfAddSupport) {
+                       if (setting)
+                               ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF;
+                       else
+                               ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF;
+                       return AH_TRUE;
+               }
+               /* fall thru... */
+       default:
+               return ath_hal_setcapability(ah, type, capability,
+                               setting, status);
+       }
+#undef N
+}
+
+HAL_BOOL
+ar5212GetDiagState(struct ath_hal *ah, int request,
+       const void *args, uint32_t argsize,
+       void **result, uint32_t *resultsize)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       (void) ahp;
+       if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
+               return AH_TRUE;
+       switch (request) {
+       case HAL_DIAG_EEPROM:
+       case HAL_DIAG_EEPROM_EXP_11A:
+       case HAL_DIAG_EEPROM_EXP_11B:
+       case HAL_DIAG_EEPROM_EXP_11G:
+       case HAL_DIAG_RFGAIN:
+               return ath_hal_eepromDiag(ah, request,
+                   args, argsize, result, resultsize);
+       case HAL_DIAG_RFGAIN_CURSTEP:
+               *result = __DECONST(void *, ahp->ah_gainValues.currStep);
+               *resultsize = (*result == AH_NULL) ?
+                       0 : sizeof(GAIN_OPTIMIZATION_STEP);
+               return AH_TRUE;
+       case HAL_DIAG_PCDAC:
+               *result = ahp->ah_pcdacTable;
+               *resultsize = ahp->ah_pcdacTableSize;
+               return AH_TRUE;
+       case HAL_DIAG_TXRATES:
+               *result = &ahp->ah_ratesArray[0];
+               *resultsize = sizeof(ahp->ah_ratesArray);
+               return AH_TRUE;
+       case HAL_DIAG_ANI_CURRENT:
+               *result = ar5212AniGetCurrentState(ah);
+               *resultsize = (*result == AH_NULL) ?
+                       0 : sizeof(struct ar5212AniState);
+               return AH_TRUE;
+       case HAL_DIAG_ANI_STATS:
+               *result = ar5212AniGetCurrentStats(ah);
+               *resultsize = (*result == AH_NULL) ?
+                       0 : sizeof(struct ar5212Stats);
+               return AH_TRUE;
+       case HAL_DIAG_ANI_CMD:
+               if (argsize != 2*sizeof(uint32_t))
+                       return AH_FALSE;
+               ar5212AniControl(ah, ((const uint32_t *)args)[0],
+                       ((const uint32_t *)args)[1]);
+               return AH_TRUE;
+       case HAL_DIAG_ANI_PARAMS:
+               /*
+                * NB: We assume struct ar5212AniParams is identical
+                * to HAL_ANI_PARAMS; if they diverge then we'll need
+                * to handle it here
+                */
+               if (argsize == 0 && args == AH_NULL) {
+                       struct ar5212AniState *aniState =
+                           ar5212AniGetCurrentState(ah);
+                       if (aniState == AH_NULL)
+                               return AH_FALSE;
+                       *result = __DECONST(void *, aniState->params);
+                       *resultsize = sizeof(struct ar5212AniParams);
+                       return AH_TRUE;
+               } else {
+                       if (argsize != sizeof(struct ar5212AniParams))
+                               return AH_FALSE;
+                       return ar5212AniSetParams(ah, args, args);
+               }
+       }
+       return AH_FALSE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_phy.c       2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_phy.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+
+/* shorthands to compact tables for readability */
+#define        OFDM    IEEE80211_T_OFDM
+#define        CCK     IEEE80211_T_CCK
+#define        TURBO   IEEE80211_T_TURBO
+
+HAL_RATE_TABLE ar5212_11a_table = {
+       8,  /* number of rates */
+       { 0 },
+       {
+/*                                                  short            ctrl  */
+/*                valid                 rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, OFDM,    6000,     0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, OFDM,    9000,     0x0f,    0x00,        18,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,   12000,     0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,   18000,     0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   24000,     0x09,    0x00, (0x80|48),   4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   36000,     0x0d,    0x00,        72,   4, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   48000,     0x08,    0x00,        96,   4, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   54000,     0x0c,    0x00,       108,   4, 0, 0 }
+       },
+};
+
+HAL_RATE_TABLE ar5212_half_table = {
+       8,  /* number of rates */
+       { 0 },
+       {
+/*                                                  short            ctrl  */
+/*                valid                 rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, OFDM,    3000,     0x0b,    0x00, (0x80|6),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, OFDM,    4500,     0x0f,    0x00,        9,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,    6000,     0x0a,    0x00, (0x80|12),  2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,    9000,     0x0e,    0x00,        18,  2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   12000,     0x09,    0x00, (0x80|24),  4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   18000,     0x0d,    0x00,        36,  4, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   24000,     0x08,    0x00,        48,  4, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   27000,     0x0c,    0x00,       54,   4, 0, 0 }
+       },
+};
+
+HAL_RATE_TABLE ar5212_quarter_table = {
+       8,  /* number of rates */
+       { 0 },
+       {
+/*                                                  short            ctrl  */
+/*                valid                 rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, OFDM,    1500,     0x0b,    0x00, (0x80|3),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, OFDM,    2250,     0x0f,    0x00,        4,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,    3000,     0x0a,    0x00, (0x80|6),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,    4500,     0x0e,    0x00,        9,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,    6000,     0x09,    0x00, (0x80|12),  4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,    9000,     0x0d,    0x00,        18,  4, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   12000,     0x08,    0x00,        24,  4, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   13500,     0x0c,    0x00,       27,   4, 0, 0 }
+       },
+};
+
+HAL_RATE_TABLE ar5212_turbog_table = {
+       7,  /* number of rates */
+       { 0 },
+       {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, TURBO,   6000,    0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, TURBO,  12000,    0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, TURBO,  18000,    0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, TURBO,  24000,    0x09,    0x00, (0x80|48),   3, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, TURBO,  36000,    0x0d,    0x00,        72,   3, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, TURBO,  48000,    0x08,    0x00,        96,   3, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, TURBO,  54000,    0x0c,    0x00,       108,   3, 0, 0 }
+       },
+};
+
+HAL_RATE_TABLE ar5212_turboa_table = {
+       8,  /* number of rates */
+       { 0 },
+       {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, TURBO,   6000,    0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, TURBO,   9000,    0x0f,    0x00,        18,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, TURBO,  12000,    0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, TURBO,  18000,    0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, TURBO,  24000,    0x09,    0x00, (0x80|48),   4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, TURBO,  36000,    0x0d,    0x00,        72,   4, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, TURBO,  48000,    0x08,    0x00,        96,   4, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, TURBO,  54000,    0x0c,    0x00,       108,   4, 0, 0 }
+       },
+};
+
+HAL_RATE_TABLE ar5212_11b_table = {
+       4,  /* number of rates */
+       { 0 },
+       {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   1 Mb */ {  AH_TRUE,  CCK,    1000,    0x1b,    0x00, (0x80| 2),   0, 0, 0 },
+/*   2 Mb */ {  AH_TRUE,  CCK,    2000,    0x1a,    0x04, (0x80| 4),   1, 0, 0 },
+/* 5.5 Mb */ {  AH_TRUE,  CCK,    5500,    0x19,    0x04, (0x80|11),   1, 0, 0 },
+/*  11 Mb */ {  AH_TRUE,  CCK,   11000,    0x18,    0x04, (0x80|22),   1, 0, 0 }
+       },
+};
+
+
+/* Venice TODO: roundUpRate() is broken when the rate table does not represent rates
+ * in increasing order  e.g.  5.5, 11, 6, 9.
+ * An average rate of 6 Mbps will currently map to 11 Mbps.
+ */
+HAL_RATE_TABLE ar5212_11g_table = {
+       12,  /* number of rates */
+       { 0 },
+       {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   1 Mb */ {  AH_TRUE, CCK,     1000,    0x1b,    0x00, (0x80| 2),   0, 0, 0 },
+/*   2 Mb */ {  AH_TRUE, CCK,     2000,    0x1a,    0x04, (0x80| 4),   1, 0, 0 },
+/* 5.5 Mb */ {  AH_TRUE, CCK,     5500,    0x19,    0x04, (0x80|11),   2, 0, 0 },
+/*  11 Mb */ {  AH_TRUE, CCK,    11000,    0x18,    0x04, (0x80|22),   3, 0, 0 },
+/* remove rates 6, 9 from rate ctrl */
+/*   6 Mb */ { AH_FALSE, OFDM,    6000,    0x0b,    0x00,        12,   4, 0, 0 },
+/*   9 Mb */ { AH_FALSE, OFDM,    9000,    0x0f,    0x00,        18,   4, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,   12000,    0x0a,    0x00,        24,   6, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,   18000,    0x0e,    0x00,        36,   6, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   24000,    0x09,    0x00,        48,   8, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   36000,    0x0d,    0x00,        72,   8, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   48000,    0x08,    0x00,        96,   8, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   54000,    0x0c,    0x00,       108,   8, 0, 0 }
+       },
+};
+
+#undef OFDM
+#undef CCK
+#undef TURBO
+#undef XR
+
+const HAL_RATE_TABLE *
+ar5212GetRateTable(struct ath_hal *ah, u_int mode)
+{
+       HAL_RATE_TABLE *rt;
+       switch (mode) {
+       case HAL_MODE_11A:
+               rt = &ar5212_11a_table;
+               break;
+       case HAL_MODE_11B:
+               rt = &ar5212_11b_table;
+               break;
+       case HAL_MODE_11G:
+#ifdef notdef
+       case HAL_MODE_PUREG:
+#endif
+               rt =  &ar5212_11g_table;
+               break;
+       case HAL_MODE_108A:
+       case HAL_MODE_TURBO:
+               rt =  &ar5212_turboa_table;
+               break;
+       case HAL_MODE_108G:
+               rt =  &ar5212_turbog_table;
+               break;
+       case HAL_MODE_11A_HALF_RATE:
+       case HAL_MODE_11G_HALF_RATE:
+               rt = &ar5212_half_table;
+               break;
+       case HAL_MODE_11A_QUARTER_RATE:
+       case HAL_MODE_11G_QUARTER_RATE:
+               rt = &ar5212_quarter_table;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
+                   __func__, mode);
+               return AH_NULL;
+       }
+       ath_hal_setupratetable(ah, rt);
+       return rt;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_power.c     2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_power.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212desc.h"
+
+/*
+ * Notify Power Mgt is enabled in self-generated frames.
+ * If requested, force chip awake.
+ *
+ * Returns A_OK if chip is awake or successfully forced awake.
+ *
+ * WARNING WARNING WARNING
+ * There is a problem with the chip where sometimes it will not wake up.
+ */
+static HAL_BOOL
+ar5212SetPowerModeAwake(struct ath_hal *ah, int setChip)
+{
+#define        AR_SCR_MASK \
+    (AR_SCR_SLDUR|AR_SCR_SLE|AR_SCR_SLE|AR_SCR_SLDTP|AR_SCR_SLDWP|\
+     AR_SCR_SLEPOL|AR_SCR_MIBIE)
+#define        POWER_UP_TIME   2000
+       uint32_t scr, val;
+       int i;
+
+       if (setChip) {
+               /*
+                * Be careful setting the AWAKE mode.  When we are called
+                * with the chip powered down the read returns 0xffffffff
+                * which when blindly written back with OS_REG_RMW_FIELD
+                * enables the MIB interrupt for the sleep performance
+                * counters.  This can result in an interrupt storm when
+                * ANI is in operation as noone knows to turn off the MIB
+                * interrupt cause.
+                */
+               scr = OS_REG_READ(ah, AR_SCR);
+               if (scr & ~AR_SCR_MASK) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: bogus SCR 0x%x, PCICFG 0x%x\n",
+                           __func__, scr, OS_REG_READ(ah, AR_PCICFG));
+                       scr = 0;
+               }
+               scr = (scr &~ AR_SCR_SLE) | AR_SCR_SLE_WAKE;
+               OS_REG_WRITE(ah, AR_SCR, scr);
+               OS_DELAY(10);   /* Give chip the chance to awake */
+
+               for (i = POWER_UP_TIME / 50; i != 0; i--) {
+                       val = OS_REG_READ(ah, AR_PCICFG);
+                       if ((val & AR_PCICFG_SPWR_DN) == 0)
+                               break;
+                       OS_DELAY(50);
+                       OS_REG_WRITE(ah, AR_SCR, scr);
+               }
+               if (i == 0) {
+#ifdef AH_DEBUG
+                       ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n",
+                               __func__, POWER_UP_TIME/50);
+#endif
+                       return AH_FALSE;
+               }
+       }
+
+       OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       return AH_TRUE;
+#undef POWER_UP_TIME
+#undef AR_SCR_MASK
+}
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
+static void
+ar5212SetPowerModeSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       if (setChip)
+               OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP);
+}
+
+/*
+ * Notify Power Management is enabled in self-generating
+ * fames.  If request, set power mode of chip to
+ * auto/normal.  Duration in units of 128us (1/8 TU).
+ */
+static void
+ar5212SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       if (setChip)
+               OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_NORM);
+}
+
+/*
+ * Set power mgt to the requested mode, and conditionally set
+ * the chip as well
+ */
+HAL_BOOL
+ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+#ifdef AH_DEBUG
+       static const char* modes[] = {
+               "AWAKE",
+               "FULL-SLEEP",
+               "NETWORK SLEEP",
+               "UNDEFINED"
+       };
+#endif
+       int status = AH_TRUE;
+
+       HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
+               modes[ahp->ah_powerMode], modes[mode],
+               setChip ? "set chip " : "");
+       switch (mode) {
+       case HAL_PM_AWAKE:
+               status = ar5212SetPowerModeAwake(ah, setChip);
+               break;
+       case HAL_PM_FULL_SLEEP:
+               ar5212SetPowerModeSleep(ah, setChip);
+               break;
+       case HAL_PM_NETWORK_SLEEP:
+               ar5212SetPowerModeNetworkSleep(ah, setChip);
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n",
+                   __func__, mode);
+               return AH_FALSE;
+       }
+       ahp->ah_powerMode = mode;
+       return status;
+}
+
+/*
+ * Return the current sleep mode of the chip
+ */
+HAL_POWER_MODE
+ar5212GetPowerMode(struct ath_hal *ah)
+{
+       /* Just so happens the h/w maps directly to the abstracted value */
+       return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE);
+}
+
+#if 0
+/*
+ * Return the current sleep state of the chip
+ * TRUE = sleeping
+ */
+HAL_BOOL
+ar5212GetPowerStatus(struct ath_hal *ah)
+{
+       return (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_SPWR_DN) != 0;
+}
+#endif
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_recv.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_recv.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212desc.h"
+
+/*
+ * Get the RXDP.
+ */
+uint32_t
+ar5212GetRxDP(struct ath_hal *ath)
+{
+       return OS_REG_READ(ath, AR_RXDP);
+}
+
+/*
+ * Set the RxDP.
+ */
+void
+ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp)
+{
+       OS_REG_WRITE(ah, AR_RXDP, rxdp);
+       HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp);
+}
+
+/*
+ * Set Receive Enable bits.
+ */
+void
+ar5212EnableReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+/*
+ * Stop Receive at the DMA engine
+ */
+HAL_BOOL
+ar5212StopDmaReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);     /* Set receive disable bit */
+       if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s: dma failed to stop in 10ms\n"
+                       "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
+                       __func__,
+                       OS_REG_READ(ah, AR_CR),
+                       OS_REG_READ(ah, AR_DIAG_SW));
+#endif
+               return AH_FALSE;
+       } else {
+               return AH_TRUE;
+       }
+}
+
+/*
+ * Start Transmit at the PCU engine (unpause receive)
+ */
+void
+ar5212StartPcuReceive(struct ath_hal *ah)
+{
+       struct ath_hal_private *ahp = AH_PRIVATE(ah);
+
+       OS_REG_WRITE(ah, AR_DIAG_SW,
+               OS_REG_READ(ah, AR_DIAG_SW) &~ AR_DIAG_RX_DIS);
+       ar5212EnableMibCounters(ah);
+       /* NB: restore current settings */
+       ar5212AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE);
+}
+
+/*
+ * Stop Transmit at the PCU engine (pause receive)
+ */
+void
+ar5212StopPcuReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_DIAG_SW,
+               OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_RX_DIS);
+       ar5212DisableMibCounters(ah);
+}
+
+/*
+ * Set multicast filter 0 (lower 32-bits)
+ *               filter 1 (upper 32-bits)
+ */
+void
+ar5212SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1)
+{
+       OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+       OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);
+}
+
+/*
+ * Clear multicast filter by index
+ */
+HAL_BOOL
+ar5212ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
+{
+       uint32_t val;
+
+       if (ix >= 64)
+               return AH_FALSE;
+       if (ix >= 32) {
+               val = OS_REG_READ(ah, AR_MCAST_FIL1);
+               OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32))));
+       } else {
+               val = OS_REG_READ(ah, AR_MCAST_FIL0);
+               OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<<ix)));
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Set multicast filter by index
+ */
+HAL_BOOL
+ar5212SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
+{
+       uint32_t val;
+
+       if (ix >= 64)
+               return AH_FALSE;
+       if (ix >= 32) {
+               val = OS_REG_READ(ah, AR_MCAST_FIL1);
+               OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32))));
+       } else {
+               val = OS_REG_READ(ah, AR_MCAST_FIL0);
+               OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<<ix)));
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Get the receive filter.
+ */
+uint32_t
+ar5212GetRxFilter(struct ath_hal *ah)
+{
+       uint32_t bits = OS_REG_READ(ah, AR_RX_FILTER);
+       uint32_t phybits = OS_REG_READ(ah, AR_PHY_ERR);
+       if (phybits & AR_PHY_ERR_RADAR)
+               bits |= HAL_RX_FILTER_PHYRADAR;
+       if (phybits & (AR_PHY_ERR_OFDM_TIMING|AR_PHY_ERR_CCK_TIMING))
+               bits |= HAL_RX_FILTER_PHYERR;
+       return bits;
+}
+
+/*
+ * Set the receive filter.
+ */
+void
+ar5212SetRxFilter(struct ath_hal *ah, uint32_t bits)
+{
+       uint32_t phybits;
+
+       OS_REG_WRITE(ah, AR_RX_FILTER,
+           bits &~ (HAL_RX_FILTER_PHYRADAR|HAL_RX_FILTER_PHYERR));
+       phybits = 0;
+       if (bits & HAL_RX_FILTER_PHYRADAR)
+               phybits |= AR_PHY_ERR_RADAR;
+       if (bits & HAL_RX_FILTER_PHYERR)
+               phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
+       OS_REG_WRITE(ah, AR_PHY_ERR, phybits);
+       if (phybits) {
+               OS_REG_WRITE(ah, AR_RXCFG,
+                       OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
+       } else {
+               OS_REG_WRITE(ah, AR_RXCFG,
+                       OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA);
+       }
+}
+
+/*
+ * Initialize RX descriptor, by clearing the status and setting
+ * the size (and any other flags).
+ */
+HAL_BOOL
+ar5212SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       uint32_t size, u_int flags)
+{
+       struct ar5212_desc *ads = AR5212DESC(ds);
+
+       HALASSERT((size &~ AR_BufLen) == 0);
+
+       ads->ds_ctl0 = 0;
+       ads->ds_ctl1 = size & AR_BufLen;
+
+       if (flags & HAL_RXDESC_INTREQ)
+               ads->ds_ctl1 |= AR_RxInterReq;
+       ads->ds_rxstatus0 = ads->ds_rxstatus1 = 0;
+
+       return AH_TRUE;
+}
+
+/*
+ * Process an RX descriptor, and return the status to the caller.
+ * Copy some hardware specific items into the software portion
+ * of the descriptor.
+ *
+ * NB: the caller is responsible for validating the memory contents
+ *     of the descriptor (e.g. flushing any cached copy).
+ */
+HAL_STATUS
+ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       uint32_t pa, struct ath_desc *nds, uint64_t tsf,
+       struct ath_rx_status *rs)
+{
+       struct ar5212_desc *ads = AR5212DESC(ds);
+       struct ar5212_desc *ands = AR5212DESC(nds);
+
+       if ((ads->ds_rxstatus1 & AR_Done) == 0)
+               return HAL_EINPROGRESS;
+       /*
+        * Given the use of a self-linked tail be very sure that the hw is
+        * done with this descriptor; the hw may have done this descriptor
+        * once and picked it up again...make sure the hw has moved on.
+        */
+       if ((ands->ds_rxstatus1&AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa)
+               return HAL_EINPROGRESS;
+
+       rs->rs_datalen = ads->ds_rxstatus0 & AR_DataLen;
+       rs->rs_tstamp = MS(ads->ds_rxstatus1, AR_RcvTimestamp);
+       rs->rs_status = 0;
+       /* XXX what about KeyCacheMiss? */
+       rs->rs_rssi = MS(ads->ds_rxstatus0, AR_RcvSigStrength);
+       /* discard invalid h/w rssi data */
+       if (rs->rs_rssi == -128)
+               rs->rs_rssi = 0;
+       if (ads->ds_rxstatus1 & AR_KeyIdxValid)
+               rs->rs_keyix = MS(ads->ds_rxstatus1, AR_KeyIdx);
+       else
+               rs->rs_keyix = HAL_RXKEYIX_INVALID;
+       /* NB: caller expected to do rate table mapping */
+       rs->rs_rate = MS(ads->ds_rxstatus0, AR_RcvRate);
+       rs->rs_antenna  = MS(ads->ds_rxstatus0, AR_RcvAntenna);
+       rs->rs_more = (ads->ds_rxstatus0 & AR_More) ? 1 : 0;
+
+       if ((ads->ds_rxstatus1 & AR_FrmRcvOK) == 0) {
+               /*
+                * These four bits should not be set together.  The
+                * 5212 spec states a Michael error can only occur if
+                * DecryptCRCErr not set (and TKIP is used).  Experience
+                * indicates however that you can also get Michael errors
+                * when a CRC error is detected, but these are specious.
+                * Consequently we filter them out here so we don't
+                * confuse and/or complicate drivers.
+                */
+               if (ads->ds_rxstatus1 & AR_CRCErr)
+                       rs->rs_status |= HAL_RXERR_CRC;
+               else if (ads->ds_rxstatus1 & AR_PHYErr) {
+                       u_int phyerr;
+
+                       rs->rs_status |= HAL_RXERR_PHY;
+                       phyerr = MS(ads->ds_rxstatus1, AR_PHYErrCode);
+                       rs->rs_phyerr = phyerr;
+                       if (!AH5212(ah)->ah_hasHwPhyCounters &&
+                           phyerr != HAL_PHYERR_RADAR)
+                               ar5212AniPhyErrReport(ah, rs);
+               } else if (ads->ds_rxstatus1 & AR_DecryptCRCErr)
+                       rs->rs_status |= HAL_RXERR_DECRYPT;
+               else if (ads->ds_rxstatus1 & AR_MichaelErr)
+                       rs->rs_status |= HAL_RXERR_MIC;
+       }
+       return HAL_OK;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212phy.h        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212phy.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5212PHY_H_
+#define _DEV_ATH_AR5212PHY_H_
+
+/* PHY registers */
+#define        AR_PHY_BASE             0x9800          /* base address of phy regs */
+#define        AR_PHY(_n)              (AR_PHY_BASE + ((_n)<<2))
+
+#define AR_PHY_TEST             0x9800          /* PHY test control */
+#define PHY_AGC_CLR             0x10000000      /* disable AGC to A2 */
+
+#define        AR_PHY_TESTCTRL         0x9808          /* PHY Test Control/Status */
+#define        AR_PHY_TESTCTRL_TXHOLD  0x3800          /* Select Tx hold */
+#define AR_PHY_TESTCTRL_TXSRC_ALT      0x00000080      /* Select input to tsdac along with bit 1 */
+#define AR_PHY_TESTCTRL_TXSRC_ALT_S    7
+#define AR_PHY_TESTCTRL_TXSRC_SRC      0x00000002      /* Used with bit 7 */
+#define AR_PHY_TESTCTRL_TXSRC_SRC_S    1
+
+#define        AR_PHY_TURBO            0x9804          /* frame control register */
+#define        AR_PHY_FC_TURBO_MODE    0x00000001      /* Set turbo mode bits */
+#define        AR_PHY_FC_TURBO_SHORT   0x00000002      /* Set short symbols to turbo mode setting */
+#define AR_PHY_FC_TURBO_MIMO    0x00000004      /* Set turbo for mimo mode */
+
+#define        AR_PHY_TIMING3          0x9814          /* Timing control 3 */
+#define        AR_PHY_TIMING3_DSC_MAN  0xFFFE0000
+#define        AR_PHY_TIMING3_DSC_MAN_S        17
+#define        AR_PHY_TIMING3_DSC_EXP  0x0001E000
+#define        AR_PHY_TIMING3_DSC_EXP_S        13
+
+#define        AR_PHY_CHIP_ID          0x9818          /* PHY chip revision ID */
+#define        AR_PHY_CHIP_ID_REV_2    0x42            /* 5212 Rev 2 BB w. TPC fix */
+#define        AR_PHY_CHIP_ID_REV_3    0x43            /* 5212 Rev 3 5213 */
+#define        AR_PHY_CHIP_ID_REV_4    0x44            /* 5212 Rev 4 2313 and up */
+
+#define        AR_PHY_ACTIVE           0x981C          /* activation register */
+#define        AR_PHY_ACTIVE_EN        0x00000001      /* Activate PHY chips */
+#define        AR_PHY_ACTIVE_DIS       0x00000000      /* Deactivate PHY chips */
+
+#define AR_PHY_TX_CTL          0x9824
+#define AR_PHY_TX_FRAME_TO_TX_DATA_START       0x0000000f
+#define AR_PHY_TX_FRAME_TO_TX_DATA_START_S     0
+
+#define        AR_PHY_ADC_CTL          0x982C
+#define        AR_PHY_ADC_CTL_OFF_INBUFGAIN    0x00000003
+#define        AR_PHY_ADC_CTL_OFF_INBUFGAIN_S  0
+#define        AR_PHY_ADC_CTL_OFF_PWDDAC       0x00002000
+#define        AR_PHY_ADC_CTL_OFF_PWDBANDGAP   0x00004000 /* BB Rev 4.2+ only */
+#define        AR_PHY_ADC_CTL_OFF_PWDADC       0x00008000 /* BB Rev 4.2+ only */
+#define        AR_PHY_ADC_CTL_ON_INBUFGAIN     0x00030000
+#define        AR_PHY_ADC_CTL_ON_INBUFGAIN_S   16
+
+#define        AR_PHY_BB_XP_PA_CTL     0x9838
+#define AR_PHY_BB_XPAA_ACTIVE_HIGH     0x00000001
+#define        AR_PHY_BB_XPAB_ACTIVE_HIGH      0x00000002
+#define        AR_PHY_BB_XPAB_ACTIVE_HIGH_S    1
+
+#define AR_PHY_TSTDAC_CONST    0x983C
+#define AR_PHY_TSTDAC_CONST_Q  0x0003FE00
+#define AR_PHY_TSTDAC_CONST_Q_S        9
+#define AR_PHY_TSTDAC_CONST_I  0x000001FF
+
+
+#define        AR_PHY_SETTLING         0x9844
+#define AR_PHY_SETTLING_AGC 0x0000007F
+#define AR_PHY_SETTLING_AGC_S   0
+#define        AR_PHY_SETTLING_SWITCH  0x00003F80
+#define        AR_PHY_SETTLING_SWITCH_S        7
+
+#define        AR_PHY_RXGAIN           0x9848
+#define        AR_PHY_RXGAIN_TXRX_ATTEN        0x0003F000
+#define        AR_PHY_RXGAIN_TXRX_ATTEN_S      12
+#define        AR_PHY_RXGAIN_TXRX_RF_MAX       0x007C0000
+#define        AR_PHY_RXGAIN_TXRX_RF_MAX_S     18
+
+#define        AR_PHY_DESIRED_SZ       0x9850
+#define        AR_PHY_DESIRED_SZ_ADC           0x000000FF
+#define        AR_PHY_DESIRED_SZ_ADC_S         0
+#define        AR_PHY_DESIRED_SZ_PGA           0x0000FF00
+#define        AR_PHY_DESIRED_SZ_PGA_S         8
+#define        AR_PHY_DESIRED_SZ_TOT_DES       0x0FF00000
+#define        AR_PHY_DESIRED_SZ_TOT_DES_S     20
+
+#define        AR_PHY_FIND_SIG          0x9858
+#define        AR_PHY_FIND_SIG_FIRSTEP  0x0003F000
+#define        AR_PHY_FIND_SIG_FIRSTEP_S                12
+#define        AR_PHY_FIND_SIG_FIRPWR   0x03FC0000
+#define        AR_PHY_FIND_SIG_FIRPWR_S                 18
+
+#define        AR_PHY_AGC_CTL1          0x985C
+#define        AR_PHY_AGC_CTL1_COARSE_LOW               0x00007F80
+#define        AR_PHY_AGC_CTL1_COARSE_LOW_S             7
+#define        AR_PHY_AGC_CTL1_COARSE_HIGH              0x003F8000
+#define        AR_PHY_AGC_CTL1_COARSE_HIGH_S            15
+
+#define        AR_PHY_AGC_CONTROL      0x9860          /* chip calibration and noise floor setting */
+#define        AR_PHY_AGC_CONTROL_CAL  0x00000001      /* do internal calibration */
+#define        AR_PHY_AGC_CONTROL_NF   0x00000002      /* do noise-floor calculation */
+#define AR_PHY_AGC_CONTROL_ENABLE_NF     0x00008000 /* Enable noise floor calibration to happen */
+#define        AR_PHY_AGC_CONTROL_FLTR_CAL     0x00010000  /* Allow Filter calibration */
+#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF  0x00020000 /* Don't update noise floor automatically */
+
+#define        AR_PHY_SFCORR_LOW        0x986C
+#define        AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW      0x00000001
+#define        AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW        0x00003F00
+#define        AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S      8
+#define        AR_PHY_SFCORR_LOW_M1_THRESH_LOW  0x001FC000
+#define        AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S        14
+#define        AR_PHY_SFCORR_LOW_M2_THRESH_LOW  0x0FE00000
+#define        AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S        21
+
+#define        AR_PHY_SFCORR           0x9868
+#define        AR_PHY_SFCORR_M2COUNT_THR        0x0000001F
+#define        AR_PHY_SFCORR_M2COUNT_THR_S      0
+#define        AR_PHY_SFCORR_M1_THRESH  0x00FE0000
+#define        AR_PHY_SFCORR_M1_THRESH_S        17
+#define        AR_PHY_SFCORR_M2_THRESH  0x7F000000
+#define        AR_PHY_SFCORR_M2_THRESH_S        24
+
+#define        AR_PHY_SLEEP_CTR_CONTROL        0x9870
+#define        AR_PHY_SLEEP_CTR_LIMIT          0x9874
+#define        AR_PHY_SLEEP_SCAL               0x9878
+
+#define        AR_PHY_PLL_CTL          0x987c  /* PLL control register */
+#define        AR_PHY_PLL_CTL_40       0xaa    /* 40 MHz */
+#define        AR_PHY_PLL_CTL_44       0xab    /* 44 MHz for 11b, 11g */
+#define        AR_PHY_PLL_CTL_44_5112  0xeb    /* 44 MHz for 11b, 11g */
+#define        AR_PHY_PLL_CTL_40_5112  0xea    /* 40 MHz for 11a, turbos */
+#define        AR_PHY_PLL_CTL_40_5413  0x04    /* 40 MHz for 11a, turbos with 5413 */
+#define        AR_PHY_PLL_CTL_HALF     0x100   /* Half clock for 1/2 chan width */
+#define        AR_PHY_PLL_CTL_QUARTER  0x200   /* Quarter clock for 1/4 chan width */
+
+#define        AR_PHY_BIN_MASK_1       0x9900
+#define        AR_PHY_BIN_MASK_2       0x9904
+#define        AR_PHY_BIN_MASK_3       0x9908
+
+#define        AR_PHY_MASK_CTL         0x990c          /* What are these for?? */
+#define        AR_PHY_MASK_CTL_MASK_4  0x00003FFF
+#define        AR_PHY_MASK_CTL_MASK_4_S        0
+#define        AR_PHY_MASK_CTL_RATE    0xFF000000
+#define        AR_PHY_MASK_CTL_RATE_S  24
+
+#define        AR_PHY_RX_DELAY         0x9914          /* analog pow-on time (100ns) */
+#define        AR_PHY_RX_DELAY_DELAY   0x00003FFF      /* delay from wakeup to rx ena */
+
+#define        AR_PHY_TIMING_CTRL4             0x9920          /* timing control */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF     0x01F   /* Mask for kcos_theta-1 for q correction */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S   0       /* shift for Q_COFF */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF     0x7E0   /* Mask for sin_theta for i correction */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5       /* Shift for sin_theta for i correction */
+#define        AR_PHY_TIMING_CTRL4_IQCORR_ENABLE       0x800   /* enable IQ correction */
+#define        AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000  /* Mask for max number of samples (logarithmic) */
+#define        AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S       12      /* Shift for max number of samples */
+#define        AR_PHY_TIMING_CTRL4_DO_IQCAL    0x10000         /* perform IQ calibration */
+#define        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER  0x40000000      /* Enable spur filter */
+#define        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK    0x20000000
+#define        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK   0x10000000
+
+#define        AR_PHY_TIMING5          0x9924
+#define        AR_PHY_TIMING5_CYCPWR_THR1      0x000000FE
+#define        AR_PHY_TIMING5_CYCPWR_THR1_S    1
+
+#define        AR_PHY_PAPD_PROBE       0x9930
+#define        AR_PHY_PAPD_PROBE_POWERTX       0x00007E00
+#define        AR_PHY_PAPD_PROBE_POWERTX_S     9
+#define        AR_PHY_PAPD_PROBE_NEXT_TX       0x00008000      /* command to take next reading */
+#define        AR_PHY_PAPD_PROBE_TYPE  0x01800000
+#define        AR_PHY_PAPD_PROBE_TYPE_S        23
+#define        AR_PHY_PAPD_PROBE_TYPE_OFDM     0
+#define        AR_PHY_PAPD_PROBE_TYPE_CCK      2
+#define        AR_PHY_PAPD_PROBE_GAINF 0xFE000000
+#define        AR_PHY_PAPD_PROBE_GAINF_S       25
+
+#define        AR_PHY_POWER_TX_RATE1   0x9934
+#define        AR_PHY_POWER_TX_RATE2   0x9938
+#define        AR_PHY_POWER_TX_RATE_MAX        0x993c
+#define        AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE     0x00000040
+
+#define        AR_PHY_FRAME_CTL        0x9944
+#define        AR_PHY_FRAME_CTL_TX_CLIP        0x00000038
+#define        AR_PHY_FRAME_CTL_TX_CLIP_S      3
+#define AR_PHY_FRAME_CTL_ERR_SERV      0x20000000
+#define AR_PHY_FRAME_CTL_ERR_SERV_S    29
+#define AR_PHY_FRAME_CTL_EMU_M         0x80000000
+#define AR_PHY_FRAME_CTL_EMU_S         31
+#define AR_PHY_FRAME_CTL_WINLEN                0x00000003
+#define AR_PHY_FRAME_CTL_WINLEN_S      0
+
+#define        AR_PHY_TXPWRADJ         0x994C          /* BB Rev 4.2+ only */
+#define        AR_PHY_TXPWRADJ_CCK_GAIN_DELTA  0x00000FC0
+#define        AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S        6
+#define        AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000
+#define        AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S       18
+
+#define        AR_PHY_RADAR_0          0x9954          /* radar detection settings */
+#define        AR_PHY_RADAR_0_ENA      0x00000001      /* Enable radar detection */
+#define AR_PHY_RADAR_0_INBAND  0x0000003e      /* Inband pulse threshold */
+#define AR_PHY_RADAR_0_INBAND_S        1
+#define AR_PHY_RADAR_0_PRSSI   0x00000FC0      /* Pulse rssi threshold */
+#define AR_PHY_RADAR_0_PRSSI_S 6
+#define AR_PHY_RADAR_0_HEIGHT  0x0003F000      /* Pulse height threshold */
+#define AR_PHY_RADAR_0_HEIGHT_S        12
+#define AR_PHY_RADAR_0_RRSSI   0x00FC0000      /* Radar rssi threshold */
+#define AR_PHY_RADAR_0_RRSSI_S 18
+#define AR_PHY_RADAR_0_FIRPWR  0x7F000000      /* Radar firpwr threshold */
+#define AR_PHY_RADAR_0_FIRPWR_S        24
+
+
+#define        AR_PHY_SIGMA_DELTA      0x996C      /* AR5312 only */
+#define        AR_PHY_SIGMA_DELTA_ADC_SEL      0x00000003
+#define        AR_PHY_SIGMA_DELTA_ADC_SEL_S    0
+#define        AR_PHY_SIGMA_DELTA_FILT2        0x000000F8
+#define        AR_PHY_SIGMA_DELTA_FILT2_S      3
+#define        AR_PHY_SIGMA_DELTA_FILT1        0x00001F00
+#define        AR_PHY_SIGMA_DELTA_FILT1_S      8
+#define        AR_PHY_SIGMA_DELTA_ADC_CLIP     0x01FFE000
+#define        AR_PHY_SIGMA_DELTA_ADC_CLIP_S   13
+
+#define        AR_PHY_RESTART          0x9970          /* restart */
+#define        AR_PHY_RESTART_DIV_GC   0x001C0000      /* bb_ant_fast_div_gc_limit */
+#define        AR_PHY_RESTART_DIV_GC_S 18
+
+#define AR_PHY_RFBUS_REQ    0x997C
+#define AR_PHY_RFBUS_REQ_REQUEST    0x00000001
+
+#define        AR_PHY_TIMING7          0x9980          /* Spur mitigation masks */
+#define        AR_PHY_TIMING8          0x9984
+#define        AR_PHY_TIMING8_PILOT_MASK_2     0x000FFFFF
+#define        AR_PHY_TIMING8_PILOT_MASK_2_S   0
+
+#define        AR_PHY_BIN_MASK2_1      0x9988
+#define        AR_PHY_BIN_MASK2_2      0x998c
+#define        AR_PHY_BIN_MASK2_3      0x9990
+#define        AR_PHY_BIN_MASK2_4      0x9994
+#define        AR_PHY_BIN_MASK2_4_MASK_4       0x00003FFF
+#define        AR_PHY_BIN_MASK2_4_MASK_4_S     0
+
+#define        AR_PHY_TIMING9          0x9998
+#define        AR_PHY_TIMING10         0x999c
+#define        AR_PHY_TIMING10_PILOT_MASK_2    0x000FFFFF
+#define        AR_PHY_TIMING10_PILOT_MASK_2_S  0
+
+#define        AR_PHY_TIMING11                 0x99a0          /* Spur Mitigation control */
+#define        AR_PHY_TIMING11_SPUR_DELTA_PHASE        0x000FFFFF
+#define        AR_PHY_TIMING11_SPUR_DELTA_PHASE_S      0
+#define        AR_PHY_TIMING11_SPUR_FREQ_SD            0x3FF00000
+#define        AR_PHY_TIMING11_SPUR_FREQ_SD_S          20
+#define AR_PHY_TIMING11_USE_SPUR_IN_AGC                0x40000000
+#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR    0x80000000
+
+#define        AR_PHY_HEAVY_CLIP_ENABLE        0x99E0
+
+#define        AR_PHY_M_SLEEP          0x99f0          /* sleep control registers */
+#define        AR_PHY_REFCLKDLY        0x99f4
+#define        AR_PHY_REFCLKPD         0x99f8
+
+/* PHY IQ calibration results */
+#define        AR_PHY_IQCAL_RES_PWR_MEAS_I     0x9c10  /* power measurement for I */
+#define        AR_PHY_IQCAL_RES_PWR_MEAS_Q     0x9c14  /* power measurement for Q */
+#define        AR_PHY_IQCAL_RES_IQ_CORR_MEAS   0x9c18  /* IQ correlation measurement */
+
+#define        AR_PHY_CURRENT_RSSI     0x9c1c          /* rssi of current frame rx'd */
+
+#define AR_PHY_RFBUS_GNT    0x9c20
+#define AR_PHY_RFBUS_GNT_GRANT  0x1
+
+#define        AR_PHY_PCDAC_TX_POWER_0 0xA180
+#define        AR_PHY_PCDAC_TX_POWER(_n)       (AR_PHY_PCDAC_TX_POWER_0 + ((_n)<<2))
+
+#define        AR_PHY_MODE             0xA200  /* Mode register */
+#define AR_PHY_MODE_QUARTER    0x40    /* Quarter Rate */
+#define AR_PHY_MODE_HALF       0x20    /* Half Rate */
+#define        AR_PHY_MODE_AR5112      0x08    /* AR5112 */
+#define        AR_PHY_MODE_AR5111      0x00    /* AR5111/AR2111 */
+#define        AR_PHY_MODE_DYNAMIC     0x04    /* dynamic CCK/OFDM mode */
+#define        AR_PHY_MODE_RF2GHZ      0x02    /* 2.4 GHz */
+#define        AR_PHY_MODE_RF5GHZ      0x00    /* 5 GHz */
+#define        AR_PHY_MODE_CCK         0x01    /* CCK */
+#define        AR_PHY_MODE_OFDM        0x00    /* OFDM */
+#define        AR_PHY_MODE_DYN_CCK_DISABLE 0x100 /* Disable dynamic CCK detection */
+
+#define        AR_PHY_CCK_TX_CTRL      0xA204
+#define        AR_PHY_CCK_TX_CTRL_JAPAN        0x00000010
+
+#define        AR_PHY_CCK_DETECT       0xA208
+#define        AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK      0x0000003F
+#define        AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S    0
+#define        AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV        0x2000
+
+#define        AR_PHY_GAIN_2GHZ        0xA20C
+#define        AR_PHY_GAIN_2GHZ_RXTX_MARGIN    0x00FC0000
+#define        AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S  18
+
+#define        AR_PHY_CCK_RXCTRL4      0xA21C
+#define        AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT       0x01F80000
+#define        AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S     19
+
+#define        AR_PHY_DAG_CTRLCCK      0xA228
+#define        AR_PHY_DAG_CTRLCCK_EN_RSSI_THR  0x00000200 /* BB Rev 4.2+ only */
+#define        AR_PHY_DAG_CTRLCCK_RSSI_THR     0x0001FC00 /* BB Rev 4.2+ only */
+#define        AR_PHY_DAG_CTRLCCK_RSSI_THR_S   10         /* BB Rev 4.2+ only */
+
+#define        AR_PHY_POWER_TX_RATE3   0xA234
+#define        AR_PHY_POWER_TX_RATE4   0xA238
+
+#define        AR_PHY_FAST_ADC         0xA24C
+#define        AR_PHY_BLUETOOTH        0xA254
+
+#define        AR_PHY_TPCRG1   0xA258  /* ar2413 power control */
+#define        AR_PHY_TPCRG1_NUM_PD_GAIN       0x0000c000
+#define        AR_PHY_TPCRG1_NUM_PD_GAIN_S     14
+#define        AR_PHY_TPCRG1_PDGAIN_SETTING1   0x00030000
+#define        AR_PHY_TPCRG1_PDGAIN_SETTING1_S 16
+#define        AR_PHY_TPCRG1_PDGAIN_SETTING2   0x000c0000
+#define        AR_PHY_TPCRG1_PDGAIN_SETTING2_S 18
+#define        AR_PHY_TPCRG1_PDGAIN_SETTING3   0x00300000
+#define        AR_PHY_TPCRG1_PDGAIN_SETTING3_S 20
+
+#define        AR_PHY_TPCRG5   0xA26C /* ar2413 power control */
+#define        AR_PHY_TPCRG5_PD_GAIN_OVERLAP   0x0000000F
+#define        AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S         0
+#define        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1        0x000003F0
+#define        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S      4
+#define        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2        0x0000FC00
+#define        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S      10
+#define        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3        0x003F0000
+#define        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S      16
+#define        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4        0x0FC00000
+#define        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S      22
+
+#endif /* _DEV_ATH_AR5212PHY_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_reset.c     2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,2659 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_reset.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#include "ah_eeprom_v3.h"
+
+/* Additional Time delay to wait after activiting the Base band */
+#define BASE_ACTIVATE_DELAY    100     /* 100 usec */
+#define PLL_SETTLE_DELAY       300     /* 300 usec */
+
+static HAL_BOOL ar5212SetResetReg(struct ath_hal *, uint32_t resetMask);
+/* NB: public for 5312 use */
+HAL_BOOL       ar5212IsSpurChannel(struct ath_hal *, HAL_CHANNEL *);
+HAL_BOOL       ar5212ChannelChange(struct ath_hal *, HAL_CHANNEL *);
+int16_t                ar5212GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+HAL_BOOL       ar5212SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+void           ar5212SetDeltaSlope(struct ath_hal *, HAL_CHANNEL *);
+HAL_BOOL       ar5212SetTransmitPower(struct ath_hal *ah,
+               HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain);
+static HAL_BOOL ar5212SetRateTable(struct ath_hal *,
+                  HAL_CHANNEL *, int16_t tpcScaleReduction, int16_t powerLimit,
+                  HAL_BOOL commit, int16_t *minPower, int16_t *maxPower);
+static void ar5212CorrectGainDelta(struct ath_hal *, int twiceOfdmCckDelta);
+static void ar5212GetTargetPowers(struct ath_hal *, HAL_CHANNEL *,
+                  const TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels,
+                  TRGT_POWER_INFO *pNewPower);
+static uint16_t ar5212GetMaxEdgePower(uint16_t channel,
+                  const RD_EDGES_POWER  *pRdEdgesPower);
+void           ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *);
+void           ar5212SetIFSTiming(struct ath_hal *, HAL_CHANNEL *);
+
+/* NB: public for RF backend use */
+void           ar5212GetLowerUpperValues(uint16_t value,
+                  uint16_t *pList, uint16_t listSize,
+                  uint16_t *pLowerValue, uint16_t *pUpperValue);
+void           ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+                  uint32_t numBits, uint32_t firstBit, uint32_t column);
+
+static int
+write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
+       HAL_BOOL bChannelChange, int writes)
+{
+#define IS_NO_RESET_TIMER_ADDR(x)                      \
+    ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \
+      (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3)))
+#define        V(r, c) (ia)->data[((r)*(ia)->cols) + (c)]
+       int r;
+
+       /* Write Common Array Parameters */
+       for (r = 0; r < ia->rows; r++) {
+               uint32_t reg = V(r, 0);
+               /* XXX timer/beacon setup registers? */
+               /* On channel change, don't reset the PCU registers */
+               if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) {
+                       OS_REG_WRITE(ah, reg, V(r, 1));
+                       DMA_YIELD(writes);
+               }
+       }
+       return writes;
+#undef IS_NO_RESET_TIMER_ADDR
+#undef V
+}
+
+#define IS_DISABLE_FAST_ADC_CHAN(x) (((x) == 2462) || ((x) == 2467))
+
+/*
+ * Places the device in and out of reset and then places sane
+ * values in the registers based on EEPROM config, initialization
+ * vectors (as determined by the mode), and station configuration
+ *
+ * bChannelChange is used to preserve DMA/PCU registers across
+ * a HW Reset during channel change.
+ */
+HAL_BOOL
+ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+       HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+#define        FAIL(_code)     do { ecode = _code; goto bad; } while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *ichan = AH_NULL;
+       const HAL_EEPROM *ee;
+       uint32_t softLedCfg, softLedState;
+       uint32_t saveFrameSeqCount, saveDefAntenna, saveLedState;
+       uint32_t macStaId1, synthDelay, txFrm2TxDStart;
+       uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
+       int16_t cckOfdmPwrDelta = 0;
+       u_int modesIndex, freqIndex;
+       HAL_STATUS ecode;
+       int i, regWrites;
+       uint32_t testReg, powerVal;
+       int8_t twiceAntennaGain, twiceAntennaReduction;
+       uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow;
+       HAL_BOOL isBmode = AH_FALSE;
+       HAL_BOOL ichan_isBmode = AH_FALSE;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+       ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       OS_MARK(ah, AH_MARK_RESET, bChannelChange);
+#define        IS(_c,_f)       (((_c)->channelFlags & _f) || 0)
+       if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+#undef IS
+
+       /* Bring out of sleep mode */
+       if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n",
+                   __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       switch (opmode) {
+       case HAL_M_STA:
+       case HAL_M_IBSS:
+       case HAL_M_HOSTAP:
+       case HAL_M_MONITOR:
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
+                   __func__, opmode);
+               FAIL(HAL_EINVAL);
+               break;
+       }
+       HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3);
+
+       SAVE_CCK(ah, ichan, ichan_isBmode);
+       SAVE_CCK(ah, chan, isBmode);
+
+       /* Preserve certain DMA hardware registers on a channel change */
+       if (bChannelChange) {
+               /*
+                * On Venice, the TSF is almost preserved across a reset;
+                * it requires doubling writes to the RESET_TSF
+                * bit in the AR_BEACON register; it also has the quirk
+                * of the TSF going back in time on the station (station
+                * latches onto the last beacon's tsf during a reset 50%
+                * of the times); the latter is not a problem for adhoc
+                * stations since as long as the TSF is behind, it will
+                * get resynchronized on receiving the next beacon; the
+                * TSF going backwards in time could be a problem for the
+                * sleep operation (supported on infrastructure stations
+                * only) - the best and most general fix for this situation
+                * is to resynchronize the various sleep/beacon timers on
+                * the receipt of the next beacon i.e. when the TSF itself
+                * gets resynchronized to the AP's TSF - power save is
+                * needed to be temporarily disabled until that time
+                *
+                * Need to save the sequence number to restore it after
+                * the reset!
+                */
+               saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);
+       } else
+               saveFrameSeqCount = 0;          /* NB: silence compiler */
+#if 0
+       /*
+        * XXX disable for now; this appears to sometimes cause OFDM
+        * XXX timing error floods when ani is enabled and bg scanning
+        * XXX kicks in
+        */
+       /* If the channel change is across the same mode - perform a fast channel change */
+       if (IS_2413(ah) || IS_5413(ah)) {
+               /*
+                * Fast channel change can only be used when:
+                *  -channel change requested - so it's not the initial reset.
+                *  -it's not a change to the current channel -
+                *      often called when switching modes on a channel
+                *  -the modes of the previous and requested channel are the
+                *      same
+                * XXX opmode shouldn't change either?
+                */
+               if (bChannelChange &&
+                   (AH_PRIVATE(ah)->ah_curchan != AH_NULL) &&
+                   (chan->channel != AH_PRIVATE(ah)->ah_curchan->channel) &&
+                   ((chan->channelFlags & CHANNEL_ALL) ==
+                    (AH_PRIVATE(ah)->ah_curchan->channelFlags & CHANNEL_ALL))) {
+                       if (ar5212ChannelChange(ah, chan)) {
+                               /* If ChannelChange completed - skip the rest of reset */
+                               /* XXX ani? */
+                               return AH_TRUE;
+                       }
+               }
+       }
+#endif
+       /*
+        * Preserve the antenna on a channel change
+        */
+       saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
+       if (saveDefAntenna == 0)                /* XXX magic constants */
+               saveDefAntenna = 1;
+
+       /* Save hardware flag before chip reset clears the register */
+       macStaId1 = OS_REG_READ(ah, AR_STA_ID1) &
+               (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);
+
+       /* Save led state from pci config register */
+       saveLedState = OS_REG_READ(ah, AR_PCICFG) &
+               (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
+                AR_PCICFG_LEDSLOW);
+       softLedCfg = OS_REG_READ(ah, AR_GPIOCR);
+       softLedState = OS_REG_READ(ah, AR_GPIODO);
+
+       ar5212RestoreClock(ah, opmode);         /* move to refclk operation */
+
+       /*
+        * Adjust gain parameters before reset if
+        * there's an outstanding gain updated.
+        */
+       (void) ar5212GetRfgain(ah);
+
+       if (!ar5212ChipReset(ah, chan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Setup the indices for the next set of register array writes */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+               modesIndex = 1;
+               freqIndex  = 1;
+               break;
+       case CHANNEL_T:
+               modesIndex = 2;
+               freqIndex  = 1;
+               break;
+       case CHANNEL_B:
+               modesIndex = 3;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_PUREG:
+               modesIndex = 4;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_108G:
+               modesIndex = 5;
+               freqIndex  = 2;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       /* Set correct Baseband to analog shift setting to access analog chips. */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
+       regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
+               regWrites);
+       ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) {
+               ar5212SetIFSTiming(ah, chan);
+               if (IS_5413(ah)) {
+                       /*
+                        * Force window_length for 1/2 and 1/4 rate channels,
+                        * the ini file sets this to zero otherwise.
+                        */
+                       OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
+                               AR_PHY_FRAME_CTL_WINLEN, 3);
+               }
+       }
+
+       /* Overwrite INI values for revised chipsets */
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
+               /* ADC_CTL */
+               OS_REG_WRITE(ah, AR_PHY_ADC_CTL,
+                       SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |
+                       SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |
+                       AR_PHY_ADC_CTL_OFF_PWDDAC |
+                       AR_PHY_ADC_CTL_OFF_PWDADC);
+
+               /* TX_PWR_ADJ */
+               if (chan->channel == 2484) {
+                       cckOfdmPwrDelta = SCALE_OC_DELTA(
+                           ee->ee_cckOfdmPwrDelta -
+                           ee->ee_scaledCh14FilterCckDelta);
+               } else {
+                       cckOfdmPwrDelta = SCALE_OC_DELTA(
+                           ee->ee_cckOfdmPwrDelta);
+               }
+
+               if (IS_CHAN_G(chan)) {
+                   OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,
+                       SM((ee->ee_cckOfdmPwrDelta*-1),
+                           AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |
+                       SM((cckOfdmPwrDelta*-1),
+                           AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);
+               }
+
+               /* Add barker RSSI thresh enable as disabled */
+               OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,
+                       AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);
+               OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,
+                       AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);
+
+               /* Set the mute mask to the correct default */
+               OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
+       }
+
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
+               /* Clear reg to alllow RX_CLEAR line debug */
+               OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
+       }
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
+#ifdef notyet
+               /* Enable burst prefetch for the data queues */
+               OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
+               /* Enable double-buffering */
+               OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
+#endif
+       }
+
+       /* Set ADC/DAC select values */
+       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
+
+       if (IS_5413(ah) || IS_2417(ah)) {
+               uint32_t newReg=1;
+               if (IS_DISABLE_FAST_ADC_CHAN(chan->channel))
+                       newReg = 0;
+               /* As it's a clock changing register, only write when the value needs to be changed */
+               if (OS_REG_READ(ah, AR_PHY_FAST_ADC) != newReg)
+                       OS_REG_WRITE(ah, AR_PHY_FAST_ADC, newReg);
+       }
+
+       /* Setup the transmit power values. */
+       if (!ar5212SetTransmitPower(ah, ichan, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Write the analog registers */
+       if (!ahp->ah_rfHal->setRfRegs(ah, ichan, modesIndex, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n",
+                   __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
+       if (IS_CHAN_OFDM(chan)) {
+               if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) &&
+                   (!IS_CHAN_B(chan)))
+                       ar5212SetSpurMitigation(ah, ichan);
+               ar5212SetDeltaSlope(ah, chan);
+       }
+
+       /* Setup board specific options for EEPROM version 3 */
+       if (!ar5212SetBoardValues(ah, ichan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error setting board options\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Restore certain DMA hardware registers on a channel change */
+       if (bChannelChange)
+               OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
+       OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
+               | macStaId1
+               | AR_STA_ID1_RTS_USE_DEF
+               | ahp->ah_staId1Defaults
+       );
+       ar5212SetOperatingMode(ah, opmode);
+
+       /* Set Venice BSSID mask according to current state */
+       OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
+       OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
+
+       /* Restore previous led state */
+       OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);
+
+       /* Restore soft Led state to GPIO */
+       OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg);
+       OS_REG_WRITE(ah, AR_GPIODO, softLedState);
+
+       /* Restore previous antenna */
+       OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+
+       /* then our BSSID */
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
+
+       /* Restore bmiss rssi & count thresholds */
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+
+       OS_REG_WRITE(ah, AR_ISR, ~0);           /* cleared on write */
+
+       if (!ar5212SetChannel(ah, ichan))
+               FAIL(HAL_EIO);
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
+
+       ar5212SetRateDurationTable(ah, chan);
+
+       /* Set Tx frame start to tx data start delay */
+       if (IS_RAD5112_ANY(ah) &&
+           (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) ||
+            IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) {
+               txFrm2TxDStart =
+                       (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) ?
+                                       TX_FRAME_D_START_HALF_RATE:
+                                       TX_FRAME_D_START_QUARTER_RATE;
+               OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL,
+                       AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart);
+       }
+
+       /*
+        * Setup fast diversity.
+        * Fast diversity can be enabled or disabled via regadd.txt.
+        * Default is enabled.
+        * For reference,
+        *    Disable: reg        val
+        *             0x00009860 0x00009d18 (if 11a / 11g, else no change)
+        *             0x00009970 0x192bb514
+        *             0x0000a208 0xd03e4648
+        *
+        *    Enable:  0x00009860 0x00009d10 (if 11a / 11g, else no change)
+        *             0x00009970 0x192fb514
+        *             0x0000a208 0xd03e6788
+        */
+
+       /* XXX Setup pre PHY ENABLE EAR additions */
+       /*
+        * Wait for the frequency synth to settle (synth goes on
+        * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
+        * Value is in 100ns increments.
+        */
+       synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_CCK(chan)) {
+               synthDelay = (4 * synthDelay) / 22;
+       } else {
+               synthDelay /= 10;
+       }
+
+       /* Activate the PHY (includes baseband activate and synthesizer on) */
+       OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+       /*
+        * There is an issue if the AP starts the calibration before
+        * the base band timeout completes.  This could result in the
+        * rx_clear false triggering.  As a workaround we add delay an
+        * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
+        * does not happen.
+        */
+       if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+               OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
+       } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+               OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
+       } else {
+               OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
+       }
+
+       /*
+        * The udelay method is not reliable with notebooks.
+        * Need to check to see if the baseband is ready
+        */
+       testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL);
+       /* Selects the Tx hold */
+       OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD);
+       i = 0;
+       while ((i++ < 20) &&
+              (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */               OS_DELAY(200);
+       OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg);
+
+       /* Calibrate the AGC and start a NF calculation */
+       OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                 OS_REG_READ(ah, AR_PHY_AGC_CONTROL)
+               | AR_PHY_AGC_CONTROL_CAL
+               | AR_PHY_AGC_CONTROL_NF);
+
+       if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) {
+               /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
+               OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+                       AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+                       INIT_IQCAL_LOG_COUNT_MAX);
+               OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
+                       AR_PHY_TIMING_CTRL4_DO_IQCAL);
+               ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
+       } else
+               ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
+
+       /* Setup compression registers */
+       ar5212SetCompRegs(ah);
+
+       /* Set 1:1 QCU to DCU mapping for all queues */
+       for (i = 0; i < AR_NUM_DCU; i++)
+               OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+       ahp->ah_intrTxqs = 0;
+       for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
+               ar5212ResetTxQueue(ah, i);
+
+       /*
+        * Setup interrupt handling.  Note that ar5212ResetTxQueue
+        * manipulates the secondary IMR's as queues are enabled
+        * and disabled.  This is done with RMW ops to insure the
+        * settings we make here are preserved.
+        */
+       ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN
+                       | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN
+                       | AR_IMR_HIUERR
+                       ;
+       if (opmode == HAL_M_HOSTAP)
+               ahp->ah_maskReg |= AR_IMR_MIB;
+       OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
+       /* Enable bus errors that are OR'd to set the HIUERR bit */
+       OS_REG_WRITE(ah, AR_IMR_S2,
+               OS_REG_READ(ah, AR_IMR_S2)
+               | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);
+
+       if (AH_PRIVATE(ah)->ah_rfkillEnabled)
+               ar5212EnableRfKill(ah);
+
+       if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: offset calibration failed to complete in 1ms;"
+                   " noisy environment?\n", __func__);
+       }
+
+       /*
+        * Set clocks back to 32kHz if they had been using refClk, then
+        * use an external 32kHz crystal when sleeping, if one exists.
+        */
+       ar5212SetupClock(ah, opmode);
+
+       /*
+        * Writing to AR_BEACON will start timers. Hence it should
+        * be the last register to be written. Do not reset tsf, do
+        * not enable beacons at this point, but preserve other values
+        * like beaconInterval.
+        */
+       OS_REG_WRITE(ah, AR_BEACON,
+               (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));
+
+       /* XXX Setup post reset EAR additions */
+
+       /* QoS support */
+       if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE ||
+           (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
+            AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) {
+               OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);      /* XXX magic */
+               OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);        /* XXX magic */
+       }
+
+       /* Turn on NOACK Support for QoS packets */
+       OS_REG_WRITE(ah, AR_NOACK,
+               SM(2, AR_NOACK_2BIT_VALUE) |
+               SM(5, AR_NOACK_BIT_OFFSET) |
+               SM(0, AR_NOACK_BYTE_OFFSET));
+
+       /* Get Antenna Gain reduction */
+       if (IS_CHAN_5GHZ(chan)) {
+               ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_5, &twiceAntennaGain);
+       } else {
+               ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_2, &twiceAntennaGain);
+       }
+       twiceAntennaReduction =
+               ath_hal_getantennareduction(ah, chan, twiceAntennaGain);
+
+       /* TPC for self-generated frames */
+
+       ackTpcPow = MS(ahp->ah_macTPC, AR_TPC_ACK);
+       if ((ackTpcPow-ahp->ah_txPowerIndexOffset) > ichan->maxTxPower)
+               ackTpcPow = ichan->maxTxPower+ahp->ah_txPowerIndexOffset;
+
+       if (ackTpcPow > (2*ichan->maxRegTxPower - twiceAntennaReduction))
+               ackTpcPow = (2*ichan->maxRegTxPower - twiceAntennaReduction)
+                       + ahp->ah_txPowerIndexOffset;
+
+       ctsTpcPow = MS(ahp->ah_macTPC, AR_TPC_CTS);
+       if ((ctsTpcPow-ahp->ah_txPowerIndexOffset) > ichan->maxTxPower)
+               ctsTpcPow = ichan->maxTxPower+ahp->ah_txPowerIndexOffset;
+
+       if (ctsTpcPow > (2*ichan->maxRegTxPower - twiceAntennaReduction))
+               ctsTpcPow = (2*ichan->maxRegTxPower - twiceAntennaReduction)
+                       + ahp->ah_txPowerIndexOffset;
+
+       chirpTpcPow = MS(ahp->ah_macTPC, AR_TPC_CHIRP);
+       if ((chirpTpcPow-ahp->ah_txPowerIndexOffset) > ichan->maxTxPower)
+               chirpTpcPow = ichan->maxTxPower+ahp->ah_txPowerIndexOffset;
+
+       if (chirpTpcPow > (2*ichan->maxRegTxPower - twiceAntennaReduction))
+               chirpTpcPow = (2*ichan->maxRegTxPower - twiceAntennaReduction)
+                       + ahp->ah_txPowerIndexOffset;
+
+       if (ackTpcPow > 63)
+               ackTpcPow = 63;
+       if (ctsTpcPow > 63)
+               ctsTpcPow = 63;
+       if (chirpTpcPow > 63)
+               chirpTpcPow = 63;
+
+       powerVal = SM(ackTpcPow, AR_TPC_ACK) |
+               SM(ctsTpcPow, AR_TPC_CTS) |
+               SM(chirpTpcPow, AR_TPC_CHIRP);
+
+       OS_REG_WRITE(ah, AR_TPC, powerVal);
+
+       /* Restore user-specified settings */
+       if (ahp->ah_miscMode != 0)
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+       if (ahp->ah_sifstime != (u_int) -1)
+               ar5212SetSifsTime(ah, ahp->ah_sifstime);
+       if (ahp->ah_slottime != (u_int) -1)
+               ar5212SetSlotTime(ah, ahp->ah_slottime);
+       if (ahp->ah_acktimeout != (u_int) -1)
+               ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
+       if (ahp->ah_ctstimeout != (u_int) -1)
+               ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
+       if (AH_PRIVATE(ah)->ah_diagreg != 0)
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+
+       AH_PRIVATE(ah)->ah_opmode = opmode;     /* record operating mode */
+
+       if (bChannelChange) {
+               if (!(ichan->privFlags & CHANNEL_DFS))
+                       ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+               chan->channelFlags = ichan->channelFlags;
+               chan->privFlags = ichan->privFlags;
+               chan->maxRegTxPower = ichan->maxRegTxPower;
+               chan->maxTxPower = ichan->maxTxPower;
+               chan->minTxPower = ichan->minTxPower;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
+
+       RESTORE_CCK(ah, ichan, ichan_isBmode);
+       RESTORE_CCK(ah, chan, isBmode);
+
+       OS_MARK(ah, AH_MARK_RESET_DONE, 0);
+
+       return AH_TRUE;
+bad:
+       if (ichan != AH_NULL)
+               RESTORE_CCK(ah, ichan, ichan_isBmode);
+       RESTORE_CCK(ah, chan, isBmode);
+
+       OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
+       if (*status)
+               *status = ecode;
+       return AH_FALSE;
+#undef FAIL
+#undef N
+}
+
+/*
+ * Call the rf backend to change the channel.
+ */
+HAL_BOOL
+ar5212SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       /* Change the synth */
+       if (!ahp->ah_rfHal->setChannel(ah, chan))
+               return AH_FALSE;
+       return AH_TRUE;
+}
+
+/*
+ * This channel change evaluates whether the selected hardware can
+ * perform a synthesizer-only channel change (no reset).  If the
+ * TX is not stopped, or the RFBus cannot be granted in the given
+ * time, the function returns false as a reset is necessary
+ */
+HAL_BOOL
+ar5212ChannelChange(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t       ulCount;
+       uint32_t   data, synthDelay, qnum;
+       uint16_t   rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
+       HAL_BOOL    txStopped = AH_TRUE;
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+
+       /* TX must be stopped or RF Bus grant will not work */
+       for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) {
+               if (ar5212NumTxPending(ah, qnum)) {
+                       txStopped = AH_FALSE;
+                       break;
+               }
+       }
+       if (!txStopped)
+               return AH_FALSE;
+
+       /* Kill last Baseband Rx Frame */
+       OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST); /* Request analog bus grant */
+       for (ulCount = 0; ulCount < 100; ulCount++) {
+               if (OS_REG_READ(ah, AR_PHY_RFBUS_GNT))
+                       break;
+               OS_DELAY(5);
+       }
+       if (ulCount >= 100)
+               return AH_FALSE;
+
+       /* Change the synth */
+       if (!ar5212SetChannel(ah, ichan))
+               return AH_FALSE;
+
+       /*
+        * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN).
+        * Read the phy active delay register. Value is in 100ns increments.
+        */
+       data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_CCK(ichan)) {
+               synthDelay = (4 * data) / 22;
+       } else {
+               synthDelay = data / 10;
+       }
+       OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
+
+       /* Setup the transmit power values. */
+       if (!ar5212SetTransmitPower(ah, ichan, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               return AH_FALSE;
+       }
+
+       /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
+       if (IS_CHAN_OFDM(ichan)) {
+               if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) &&
+                   (!IS_CHAN_B(chan)))
+                       ar5212SetSpurMitigation(ah, ichan);
+               ar5212SetDeltaSlope(ah, chan);
+       }
+
+       /* Release the RFBus Grant */
+       OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+
+       /* Start Noise Floor Cal */
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+       if (!(ichan->privFlags & CHANNEL_DFS))
+               ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+       chan->channelFlags = ichan->channelFlags;
+       chan->privFlags = ichan->privFlags;
+       chan->maxRegTxPower = ichan->maxRegTxPower;
+       chan->maxTxPower = ichan->maxTxPower;
+       chan->minTxPower = ichan->minTxPower;
+       return AH_TRUE;
+}
+
+void
+ar5212SetOperatingMode(struct ath_hal *ah, int opmode)
+{
+       uint32_t val;
+
+       val = OS_REG_READ(ah, AR_STA_ID1);
+       val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
+       switch (opmode) {
+       case HAL_M_HOSTAP:
+               OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
+                                       | AR_STA_ID1_KSRCH_MODE);
+               OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+               break;
+       case HAL_M_IBSS:
+               OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
+                                       | AR_STA_ID1_KSRCH_MODE);
+               OS_REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+               break;
+       case HAL_M_STA:
+       case HAL_M_MONITOR:
+               OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
+               break;
+       }
+}
+
+/*
+ * Places the PHY and Radio chips into reset.  A full reset
+ * must be called to leave this state.  The PCI/MAC/PCU are
+ * not placed into reset as we must receive interrupt to
+ * re-enable the hardware.
+ */
+HAL_BOOL
+ar5212PhyDisable(struct ath_hal *ah)
+{
+       return ar5212SetResetReg(ah, AR_RC_BB);
+}
+
+/*
+ * Places all of hardware into reset
+ */
+HAL_BOOL
+ar5212Disable(struct ath_hal *ah)
+{
+       if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+       /*
+        * Reset the HW - PCI must be reset after the rest of the
+        * device has been reset.
+        */
+       return ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI);
+}
+
+/*
+ * Places the hardware into reset and then pulls it out of reset
+ *
+ * TODO: Only write the PLL if we're changing to or from CCK mode
+ *
+ * WARNING: The order of the PLL and mode registers must be correct.
+ */
+HAL_BOOL
+ar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+
+       OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0);
+
+       /*
+        * Reset the HW - PCI must be reset after the rest of the
+        * device has been reset
+        */
+       if (!ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))
+               return AH_FALSE;
+
+       /* Bring out of sleep mode (AGAIN) */
+       if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+
+       /* Clear warm reset register */
+       if (!ar5212SetResetReg(ah, 0))
+               return AH_FALSE;
+
+       /*
+        * Perform warm reset before the mode/PLL/turbo registers
+        * are changed in order to deactivate the radio.  Mode changes
+        * with an active radio can result in corrupted shifts to the
+        * radio device.
+        */
+
+       /*
+        * Set CCK and Turbo modes correctly.
+        */
+       if (chan != AH_NULL) {          /* NB: can be null during attach */
+               uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;
+
+               if (IS_5413(ah)) {      /* NB: =>'s 5424 also */
+                       rfMode = AR_PHY_MODE_AR5112;
+                       if (IS_CHAN_HALF_RATE(chan))
+                               rfMode |= AR_PHY_MODE_HALF;
+                       else if (IS_CHAN_QUARTER_RATE(chan))
+                               rfMode |= AR_PHY_MODE_QUARTER;
+
+                       if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))
+                               phyPLL = AR_PHY_PLL_CTL_44_5112;
+                       else
+                               phyPLL = AR_PHY_PLL_CTL_40_5413;
+               } else if (IS_RAD5111(ah)) {
+                       rfMode = AR_PHY_MODE_AR5111;
+                       if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))
+                               phyPLL = AR_PHY_PLL_CTL_44;
+                       else
+                               phyPLL = AR_PHY_PLL_CTL_40;
+                       if (IS_CHAN_HALF_RATE(chan))
+                               phyPLL = AR_PHY_PLL_CTL_HALF;
+                       else if (IS_CHAN_QUARTER_RATE(chan))
+                               phyPLL = AR_PHY_PLL_CTL_QUARTER;
+               } else {                /* 5112, 2413, 2316, 2317 */
+                       rfMode = AR_PHY_MODE_AR5112;
+                       if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))
+                               phyPLL = AR_PHY_PLL_CTL_44_5112;
+                       else
+                               phyPLL = AR_PHY_PLL_CTL_40_5112;
+                       if (IS_CHAN_HALF_RATE(chan))
+                               phyPLL |= AR_PHY_PLL_CTL_HALF;
+                       else if (IS_CHAN_QUARTER_RATE(chan))
+                               phyPLL |= AR_PHY_PLL_CTL_QUARTER;
+               }
+               if (IS_CHAN_OFDM(chan) && (IS_CHAN_CCK(chan) ||
+                                          IS_CHAN_G(chan)))
+                       rfMode |= AR_PHY_MODE_DYNAMIC;
+               else if (IS_CHAN_OFDM(chan))
+                       rfMode |= AR_PHY_MODE_OFDM;
+               else
+                       rfMode |= AR_PHY_MODE_CCK;
+               if (IS_CHAN_5GHZ(chan))
+                       rfMode |= AR_PHY_MODE_RF5GHZ;
+               else
+                       rfMode |= AR_PHY_MODE_RF2GHZ;
+               turbo = IS_CHAN_TURBO(chan) ?
+                       (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;
+               curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);
+               /*
+                * PLL, Mode, and Turbo values must be written in the correct
+                * order to ensure:
+                * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
+                *   mode bit is set
+                * - Turbo cannot be set at the same time as CCK or DYNAMIC
+                */
+               if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) {
+                       OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
+                       OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
+                       if (curPhyPLL != phyPLL) {
+                               OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
+                               /* Wait for the PLL to settle */
+                               OS_DELAY(PLL_SETTLE_DELAY);
+                       }
+               } else {
+                       if (curPhyPLL != phyPLL) {
+                               OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
+                               /* Wait for the PLL to settle */
+                               OS_DELAY(PLL_SETTLE_DELAY);
+                       }
+                       OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
+                       OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
+               }
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+HAL_BOOL
+ar5212PerCalibrationN(struct ath_hal *ah,  HAL_CHANNEL *chan, u_int chainMask,
+       HAL_BOOL longCal, HAL_BOOL *isCalDone)
+{
+#define IQ_CAL_TRIES    10
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *ichan;
+       int32_t qCoff, qCoffDenom;
+       int32_t iqCorrMeas, iCoff, iCoffDenom;
+       uint32_t powerMeasQ, powerMeasI;
+       HAL_BOOL ichan_isBmode = AH_FALSE;
+       HAL_BOOL isBmode = AH_FALSE;
+
+       OS_MARK(ah, AH_MARK_PERCAL, chan->channel);
+       *isCalDone = AH_FALSE;
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               return AH_FALSE;
+       }
+       SAVE_CCK(ah, ichan, ichan_isBmode);
+       SAVE_CCK(ah, chan, isBmode);
+
+       if (ahp->ah_bIQCalibration == IQ_CAL_DONE ||
+           ahp->ah_bIQCalibration == IQ_CAL_INACTIVE)
+               *isCalDone = AH_TRUE;
+
+       /* IQ calibration in progress. Check to see if it has finished. */
+       if (ahp->ah_bIQCalibration == IQ_CAL_RUNNING &&
+           !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) {
+               int i;
+
+               /* IQ Calibration has finished. */
+               ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
+               *isCalDone = AH_TRUE;
+
+               /* workaround for misgated IQ Cal results */
+               i = 0;
+               do {
+                       /* Read calibration results. */
+                       powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I);
+                       powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q);
+                       iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS);
+                       if (powerMeasI && powerMeasQ)
+                               break;
+                       /* Do we really need this??? */
+                       OS_REG_WRITE (ah,  AR_PHY_TIMING_CTRL4,
+                                     OS_REG_READ(ah,  AR_PHY_TIMING_CTRL4) |
+                                     AR_PHY_TIMING_CTRL4_DO_IQCAL);
+               } while (++i < IQ_CAL_TRIES);
+
+               /*
+                * Prescale these values to remove 64-bit operation
+                * requirement at the loss of a little precision.
+                */
+               iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
+               qCoffDenom = powerMeasQ / 128;
+
+               /* Protect against divide-by-0 and loss of sign bits. */
+               if (iCoffDenom != 0 && qCoffDenom >= 2) {
+                       iCoff = (int8_t)(-iqCorrMeas) / iCoffDenom;
+                       /* IQCORR_Q_I_COFF is a signed 6 bit number */
+                       if (iCoff < -32) {
+                               iCoff = -32;
+                       } else if (iCoff > 31) {
+                               iCoff = 31;
+                       }
+
+                       /* IQCORR_Q_Q_COFF is a signed 5 bit number */
+                       qCoff = (powerMeasI / qCoffDenom) - 128;
+                       if (qCoff < -16) {
+                               qCoff = -16;
+                       } else if (qCoff > 15) {
+                               qCoff = 15;
+                       }
+
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "****************** MISGATED IQ CAL! *******************\n");
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "time       = %d, i = %d, \n", OS_GETUPTIME(ah), i);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "powerMeasI = 0x%08x\n", powerMeasI);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "powerMeasQ = 0x%08x\n", powerMeasQ);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "iqCorrMeas = 0x%08x\n", iqCorrMeas);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "iCoff      = %d\n", iCoff);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "qCoff      = %d\n", qCoff);
+
+                       /* Write values and enable correction */
+                       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+                               AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff);
+                       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+                               AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff);
+                       OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
+                               AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+
+                       ahp->ah_bIQCalibration = IQ_CAL_DONE;
+                       ichan->iqCalValid = AH_TRUE;
+                       ichan->iCoff = iCoff;
+                       ichan->qCoff = qCoff;
+               }
+       } else if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration == IQ_CAL_DONE &&
+           !ichan->iqCalValid) {
+               /*
+                * Start IQ calibration if configured channel has changed.
+                * Use a magic number of 15 based on default value.
+                */
+               OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+                       AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+                       INIT_IQCAL_LOG_COUNT_MAX);
+               OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
+                       AR_PHY_TIMING_CTRL4_DO_IQCAL);
+               ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
+       }
+       /* XXX EAR */
+
+       if (longCal) {
+               /* Check noise floor results */
+               ar5212GetNf(ah, ichan);
+
+               if ((ichan->channelFlags & CHANNEL_CW_INT) == 0) {
+                       /* Perform cal for 5Ghz channels and any OFDM on 5112 */
+                       if (IS_CHAN_5GHZ(chan) ||
+                           (IS_RAD5112(ah) && IS_CHAN_OFDM(chan)))
+                               ar5212RequestRfgain(ah);
+               } else {
+                       /* report up and clear internal state */
+                       chan->channelFlags |= CHANNEL_CW_INT;
+                       ichan->channelFlags &= ~CHANNEL_CW_INT;
+               }
+       }
+       RESTORE_CCK(ah, ichan, ichan_isBmode);
+       RESTORE_CCK(ah, chan, isBmode);
+
+       return AH_TRUE;
+#undef IQ_CAL_TRIES
+}
+
+HAL_BOOL
+ar5212PerCalibration(struct ath_hal *ah,  HAL_CHANNEL *chan, HAL_BOOL *isIQdone)
+{
+       return ar5212PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone);
+}
+
+HAL_BOOL
+ar5212ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       /* XXX */
+       return AH_TRUE;
+}
+
+/*
+ * Write the given reset bit mask into the reset register
+ */
+static HAL_BOOL
+ar5212SetResetReg(struct ath_hal *ah, uint32_t resetMask)
+{
+       uint32_t mask = resetMask ? resetMask : ~0;
+       HAL_BOOL rt;
+
+       /* XXX ar5212MacStop & co. */
+
+       if (IS_PCIE(ah)) {
+               resetMask &= ~AR_RC_PCI;
+       }
+
+       (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */
+       OS_REG_WRITE(ah, AR_RC, resetMask);
+       OS_DELAY(15);                   /* need to wait at least 128 clocks
+                                          when reseting PCI before read */
+       mask &= (AR_RC_MAC | AR_RC_BB);
+       resetMask &= (AR_RC_MAC | AR_RC_BB);
+       rt = ath_hal_wait(ah, AR_RC, mask, resetMask);
+        if ((resetMask & AR_RC_MAC) == 0) {
+               if (isBigEndian()) {
+                       /*
+                        * Set CFG, little-endian for register
+                        * and descriptor accesses.
+                        */
+                       mask = INIT_CONFIG_STATUS | AR_CFG_SWRD | AR_CFG_SWRG;
+#ifndef AH_NEED_DESC_SWAP
+                       mask |= AR_CFG_SWTD;
+#endif
+                       OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));
+               } else
+                       OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
+               if (ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+                       (void) OS_REG_READ(ah, AR_ISR_RAC);
+       }
+
+       /* track PHY power state so we don't try to r/w BB registers */
+       AH5212(ah)->ah_phyPowerOn = ((resetMask & AR_RC_BB) == 0);
+       return rt;
+}
+
+int16_t
+ar5212GetNoiseFloor(struct ath_hal *ah)
+{
+       int16_t nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
+       if (nf & 0x100)
+               nf = 0 - ((nf ^ 0x1ff) + 1);
+       return nf;
+}
+
+static HAL_BOOL
+getNoiseFloorThresh(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *chan,
+       int16_t *nft)
+{
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:
+               *nft = ee->ee_noiseFloorThresh[headerInfo11A];
+               break;
+       case CHANNEL_B:
+               *nft = ee->ee_noiseFloorThresh[headerInfo11B];
+               break;
+       case CHANNEL_PUREG:
+               *nft = ee->ee_noiseFloorThresh[headerInfo11G];
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Setup the noise floor cal history buffer.
+ */
+void
+ar5212InitNfCalHistBuffer(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       int i;
+
+       ahp->ah_nfCalHist.first_run = 1;
+       ahp->ah_nfCalHist.currIndex = 0;
+       ahp->ah_nfCalHist.privNF = AR5212_CCA_MAX_GOOD_VALUE;
+       ahp->ah_nfCalHist.invalidNFcount = AR512_NF_CAL_HIST_MAX;
+       for (i = 0; i < AR512_NF_CAL_HIST_MAX; i ++)
+               ahp->ah_nfCalHist.nfCalBuffer[i] = AR5212_CCA_MAX_GOOD_VALUE;
+}
+
+/*
+ * Add a noise floor value to the ring buffer.
+ */
+static __inline void
+updateNFHistBuff(struct ar5212NfCalHist *h, int16_t nf)
+{
+       h->nfCalBuffer[h->currIndex] = nf;
+       if (++h->currIndex >= AR512_NF_CAL_HIST_MAX)
+               h->currIndex = 0;
+}
+
+/*
+ * Return the median noise floor value in the ring buffer.
+ */
+int16_t
+ar5212GetNfHistMid(const int16_t calData[AR512_NF_CAL_HIST_MAX])
+{
+       int16_t sort[AR512_NF_CAL_HIST_MAX];
+       int i, j;
+
+       OS_MEMCPY(sort, calData, AR512_NF_CAL_HIST_MAX*sizeof(int16_t));
+       for (i = 0; i < AR512_NF_CAL_HIST_MAX-1; i ++) {
+               for (j = 1; j < AR512_NF_CAL_HIST_MAX-i; j ++) {
+                       if (sort[j] > sort[j-1]) {
+                               int16_t nf = sort[j];
+                               sort[j] = sort[j-1];
+                               sort[j-1] = nf;
+                       }
+               }
+       }
+       return sort[(AR512_NF_CAL_HIST_MAX-1)>>1];
+}
+
+/*
+ * Read the NF and check it against the noise floor threshhold
+ */
+int16_t
+ar5212GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212NfCalHist *h = &ahp->ah_nfCalHist;
+       int16_t nf, nfThresh;
+       int32_t val;
+
+       if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: NF did not complete in calibration window\n", __func__);
+               chan->rawNoiseFloor = h->privNF;        /* most recent value */
+               return chan->rawNoiseFloor;
+       }
+
+       /*
+        * Finished NF cal, check against threshold.
+        */
+       nf = ar5212GetNoiseFloor(ah);
+       if (getNoiseFloorThresh(ah, chan, &nfThresh)) {
+               if (nf > nfThresh) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: noise floor failed detected; detected %u, "
+                           "threshold %u\n", __func__, nf, nfThresh);
+                       /*
+                        * NB: Don't discriminate 2.4 vs 5Ghz, if this
+                        *     happens it indicates a problem regardless
+                        *     of the band.
+                        */
+                       chan->channelFlags |= CHANNEL_CW_INT;
+                       nf = 0;
+               }
+       } else
+               nf = 0;
+
+       /*
+        * Pass through histogram and write median value as
+        * calculated from the accrued window.  We require a
+        * full window of in-range values to be seen before we
+        * start using the history.
+        */
+       updateNFHistBuff(h, nf);
+       if (h->first_run) {
+               if (nf < AR5212_CCA_MIN_BAD_VALUE ||
+                   nf > AR5212_CCA_MAX_HIGH_VALUE) {
+                       nf = AR5212_CCA_MAX_GOOD_VALUE;
+                       h->invalidNFcount = AR512_NF_CAL_HIST_MAX;
+               } else if (--(h->invalidNFcount) == 0) {
+                       h->first_run = 0;
+                       h->privNF = nf = ar5212GetNfHistMid(h->nfCalBuffer);
+               } else {
+                       nf = AR5212_CCA_MAX_GOOD_VALUE;
+               }
+       } else {
+               h->privNF = nf = ar5212GetNfHistMid(h->nfCalBuffer);
+       }
+
+       val = OS_REG_READ(ah, AR_PHY(25));
+       val &= 0xFFFFFE00;
+       val |= (((uint32_t)nf << 1) & 0x1FF);
+       OS_REG_WRITE(ah, AR_PHY(25), val);
+       OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
+       OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+       if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF, 0)) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s: AGC not ready AGC_CONTROL 0x%x\n",
+                   __func__, OS_REG_READ(ah, AR_PHY_AGC_CONTROL));
+#endif
+       }
+
+       /*
+        * Now load a high maxCCAPower value again so that we're
+        * not capped by the median we just loaded
+        */
+       val &= 0xFFFFFE00;
+       val |= (((uint32_t)(-50) << 1) & 0x1FF);
+       OS_REG_WRITE(ah, AR_PHY(25), val);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+       return (chan->rawNoiseFloor = nf);
+}
+
+/*
+ * Set up compression configuration registers
+ */
+void
+ar5212SetCompRegs(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       int i;
+
+        /* Check if h/w supports compression */
+       if (!AH_PRIVATE(ah)->ah_caps.halCompressSupport)
+               return;
+
+       OS_REG_WRITE(ah, AR_DCCFG, 1);
+
+       OS_REG_WRITE(ah, AR_CCFG,
+               (AR_COMPRESSION_WINDOW_SIZE >> 8) & AR_CCFG_WIN_M);
+
+       OS_REG_WRITE(ah, AR_CCFG,
+               OS_REG_READ(ah, AR_CCFG) | AR_CCFG_MIB_INT_EN);
+       OS_REG_WRITE(ah, AR_CCUCFG,
+               AR_CCUCFG_RESET_VAL | AR_CCUCFG_CATCHUP_EN);
+
+       OS_REG_WRITE(ah, AR_CPCOVF, 0);
+
+       /* reset decompression mask */
+       for (i = 0; i < HAL_DECOMP_MASK_SIZE; i++) {
+               OS_REG_WRITE(ah, AR_DCM_A, i);
+               OS_REG_WRITE(ah, AR_DCM_D, ahp->ah_decompMask[i]);
+       }
+}
+
+HAL_BOOL
+ar5212SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings,
+       const HAL_CHANNEL_INTERNAL *chan)
+{
+#define        ANT_SWITCH_TABLE1       AR_PHY(88)
+#define        ANT_SWITCH_TABLE2       AR_PHY(89)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint32_t antSwitchA, antSwitchB;
+       int ix;
+       HAL_BOOL isBmode = AH_FALSE;
+       /* NB: need local copy for SAVE/RESTORE 'cuz chan is const */
+       HAL_CHANNEL_INTERNAL ichan = *chan;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+       HALASSERT(ahp->ah_phyPowerOn);
+
+       SAVE_CCK(ah, &ichan, isBmode);
+       switch (ichan.channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:         ix = 0; break;
+       case CHANNEL_B:         ix = 1; break;
+       case CHANNEL_PUREG:     ix = 2; break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, ichan.channelFlags);
+               RESTORE_CCK(ah, &ichan, isBmode);
+               return AH_FALSE;
+       }
+       RESTORE_CCK(ah, &ichan, isBmode);
+
+       antSwitchA =  ee->ee_antennaControl[1][ix]
+                  | (ee->ee_antennaControl[2][ix] << 6)
+                  | (ee->ee_antennaControl[3][ix] << 12)
+                  | (ee->ee_antennaControl[4][ix] << 18)
+                  | (ee->ee_antennaControl[5][ix] << 24)
+                  ;
+       antSwitchB =  ee->ee_antennaControl[6][ix]
+                  | (ee->ee_antennaControl[7][ix] << 6)
+                  | (ee->ee_antennaControl[8][ix] << 12)
+                  | (ee->ee_antennaControl[9][ix] << 18)
+                  | (ee->ee_antennaControl[10][ix] << 24)
+                  ;
+       /*
+        * For fixed antenna, give the same setting for both switch banks
+        */
+       switch (settings) {
+       case HAL_ANT_FIXED_A:
+               antSwitchB = antSwitchA;
+               break;
+       case HAL_ANT_FIXED_B:
+               antSwitchA = antSwitchB;
+               break;
+       case HAL_ANT_VARIABLE:
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n",
+                   __func__, settings);
+               return AH_FALSE;
+       }
+       if (antSwitchB == antSwitchA) {
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                   "%s: Setting fast diversity off.\n", __func__);
+               OS_REG_CLR_BIT(ah,AR_PHY_CCK_DETECT,
+                              AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+               ahp->ah_diversity = AH_FALSE;
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                   "%s: Setting fast diversity on.\n", __func__);
+               OS_REG_SET_BIT(ah,AR_PHY_CCK_DETECT,
+                              AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+               ahp->ah_diversity = AH_TRUE;
+       }
+       ahp->ah_antControl = settings;
+
+       OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA);
+       OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB);
+
+       return AH_TRUE;
+#undef ANT_SWITCH_TABLE2
+#undef ANT_SWITCH_TABLE1
+}
+
+HAL_BOOL
+ar5212IsSpurChannel(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+    uint32_t clockFreq =
+       ((IS_5413(ah) || IS_RAD5112_ANY(ah) || IS_2417(ah)) ? 40 : 32);
+    return ( ((chan->channel % clockFreq) != 0)
+          && (((chan->channel % clockFreq) < 10)
+         || (((chan->channel) % clockFreq) > 22)) );
+}
+
+/*
+ * Read EEPROM header info and program the device for correct operation
+ * given the channel value.
+ */
+HAL_BOOL
+ar5212SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+#define NO_FALSE_DETECT_BACKOFF   2
+#define CB22_FALSE_DETECT_BACKOFF 6
+#define        AR_PHY_BIS(_ah, _reg, _mask, _val) \
+       OS_REG_WRITE(_ah, AR_PHY(_reg), \
+               (OS_REG_READ(_ah, AR_PHY(_reg)) & _mask) | (_val));
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       int arrayMode, falseDectectBackoff;
+       int is2GHz = IS_CHAN_2GHZ(chan);
+       int8_t adcDesiredSize, pgaDesiredSize;
+       uint16_t switchSettling, txrxAtten, rxtxMargin;
+       int iCoff, qCoff;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+       case CHANNEL_T:
+               arrayMode = headerInfo11A;
+               if (!IS_RAD5112_ANY(ah) && !IS_2413(ah) && !IS_5413(ah))
+                       OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
+                               AR_PHY_FRAME_CTL_TX_CLIP,
+                               ahp->ah_gainValues.currStep->paramVal[GP_TXCLIP]);
+               break;
+       case CHANNEL_B:
+               arrayMode = headerInfo11B;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               arrayMode = headerInfo11G;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /* Set the antenna register(s) correctly for the chip revision */
+       AR_PHY_BIS(ah, 68, 0xFFFFFC06,
+               (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1);
+
+       ar5212SetAntennaSwitchInternal(ah, ahp->ah_antControl, chan);
+
+       /* Set the Noise Floor Thresh on ar5211 devices */
+       OS_REG_WRITE(ah, AR_PHY(90),
+               (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF)
+               | (1 << 9));
+
+       if (ee->ee_version >= AR_EEPROM_VER5_0 && IS_CHAN_TURBO(chan)) {
+               switchSettling = ee->ee_switchSettlingTurbo[is2GHz];
+               adcDesiredSize = ee->ee_adcDesiredSizeTurbo[is2GHz];
+               pgaDesiredSize = ee->ee_pgaDesiredSizeTurbo[is2GHz];
+               txrxAtten = ee->ee_txrxAttenTurbo[is2GHz];
+               rxtxMargin = ee->ee_rxtxMarginTurbo[is2GHz];
+       } else {
+               switchSettling = ee->ee_switchSettling[arrayMode];
+               adcDesiredSize = ee->ee_adcDesiredSize[arrayMode];
+               pgaDesiredSize = ee->ee_pgaDesiredSize[is2GHz];
+               txrxAtten = ee->ee_txrxAtten[is2GHz];
+               rxtxMargin = ee->ee_rxtxMargin[is2GHz];
+       }
+
+       OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+                        AR_PHY_SETTLING_SWITCH, switchSettling);
+       OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+                        AR_PHY_DESIRED_SZ_ADC, adcDesiredSize);
+       OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+                        AR_PHY_DESIRED_SZ_PGA, pgaDesiredSize);
+       OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
+                        AR_PHY_RXGAIN_TXRX_ATTEN, txrxAtten);
+       OS_REG_WRITE(ah, AR_PHY(13),
+               (ee->ee_txEndToXPAOff[arrayMode] << 24)
+               | (ee->ee_txEndToXPAOff[arrayMode] << 16)
+               | (ee->ee_txFrameToXPAOn[arrayMode] << 8)
+               | ee->ee_txFrameToXPAOn[arrayMode]);
+       AR_PHY_BIS(ah, 10, 0xFFFF00FF,
+               ee->ee_txEndToXLNAOn[arrayMode] << 8);
+       AR_PHY_BIS(ah, 25, 0xFFF80FFF,
+               (ee->ee_thresh62[arrayMode] << 12) & 0x7F000);
+
+       /*
+        * False detect backoff - suspected 32 MHz spur causes false
+        * detects in OFDM, causing Tx Hangs.  Decrease weak signal
+        * sensitivity for this card.
+        */
+       falseDectectBackoff = NO_FALSE_DETECT_BACKOFF;
+       if (ee->ee_version < AR_EEPROM_VER3_3) {
+               /* XXX magic number */
+               if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 &&
+                   IS_CHAN_OFDM(chan))
+                       falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF;
+       } else {
+               if (ar5212IsSpurChannel(ah, (HAL_CHANNEL *)chan)) {
+                       falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode];
+               }
+       }
+       AR_PHY_BIS(ah, 73, 0xFFFFFF01, (falseDectectBackoff << 1) & 0xFE);
+
+       if (chan->iqCalValid) {
+               iCoff = chan->iCoff;
+               qCoff = chan->qCoff;
+       } else {
+               iCoff = ee->ee_iqCalI[is2GHz];
+               qCoff = ee->ee_iqCalQ[is2GHz];
+       }
+
+       /* write previous IQ results */
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+               AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff);
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+               AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff);
+       OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
+               AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+
+       if (ee->ee_version >= AR_EEPROM_VER4_1) {
+               if (!IS_CHAN_108G(chan) || ee->ee_version >= AR_EEPROM_VER5_0)
+                       OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+                               AR_PHY_GAIN_2GHZ_RXTX_MARGIN, rxtxMargin);
+       }
+       if (ee->ee_version >= AR_EEPROM_VER5_1) {
+               /* for now always disabled */
+               OS_REG_WRITE(ah,  AR_PHY_HEAVY_CLIP_ENABLE,  0);
+       }
+
+       return AH_TRUE;
+#undef AR_PHY_BIS
+#undef NO_FALSE_DETECT_BACKOFF
+#undef CB22_FALSE_DETECT_BACKOFF
+}
+
+/*
+ * Apply Spur Immunity to Boards that require it.
+ * Applies only to OFDM RX operation.
+ */
+
+void
+ar5212SetSpurMitigation(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
+{
+       uint32_t pilotMask[2] = {0, 0}, binMagMask[4] = {0, 0, 0 , 0};
+       uint16_t i, finalSpur, curChanAsSpur, binWidth = 0, spurDetectWidth, spurChan;
+       int32_t spurDeltaPhase = 0, spurFreqSd = 0, spurOffset, binOffsetNumT16, curBinOffset;
+       int16_t numBinOffsets;
+       static const uint16_t magMapFor4[4] = {1, 2, 2, 1};
+       static const uint16_t magMapFor3[3] = {1, 2, 1};
+       const uint16_t *pMagMap;
+       HAL_BOOL is2GHz = IS_CHAN_2GHZ(ichan);
+       uint32_t val;
+
+#define CHAN_TO_SPUR(_f, _freq)   ( ((_freq) - ((_f) ? 2300 : 4900)) * 10 )
+       if (IS_2417(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: no spur mitigation\n",
+                   __func__);
+               return;
+       }
+
+       curChanAsSpur = CHAN_TO_SPUR(is2GHz, ichan->channel);
+
+       if (ichan->mainSpur) {
+               /* Pull out the saved spur value */
+               finalSpur = ichan->mainSpur;
+       } else {
+               /*
+                * Check if spur immunity should be performed for this channel
+                * Should only be performed once per channel and then saved
+                */
+               finalSpur = AR_NO_SPUR;
+               spurDetectWidth = HAL_SPUR_CHAN_WIDTH;
+               if (IS_CHAN_TURBO(ichan))
+                       spurDetectWidth *= 2;
+
+               /* Decide if any spur affects the current channel */
+               for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+                       spurChan = ath_hal_getSpurChan(ah, i, is2GHz);
+                       if (spurChan == AR_NO_SPUR) {
+                               break;
+                       }
+                       if ((curChanAsSpur - spurDetectWidth <= (spurChan & HAL_SPUR_VAL_MASK)) &&
+                           (curChanAsSpur + spurDetectWidth >= (spurChan & HAL_SPUR_VAL_MASK))) {
+                               finalSpur = spurChan & HAL_SPUR_VAL_MASK;
+                               break;
+                       }
+               }
+               /* Save detected spur (or no spur) for this channel */
+               ichan->mainSpur = finalSpur;
+       }
+
+       /* Write spur immunity data */
+       if (finalSpur == AR_NO_SPUR) {
+               /* Disable Spur Immunity Regs if they appear set */
+               if (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER) {
+                       /* Clear Spur Delta Phase, Spur Freq, and enable bits */
+                       OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_RATE, 0);
+                       val = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4);
+                       val &= ~(AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+                                AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+                                AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+                       OS_REG_WRITE(ah, AR_PHY_MASK_CTL, val);
+                       OS_REG_WRITE(ah, AR_PHY_TIMING11, 0);
+
+                       /* Clear pilot masks */
+                       OS_REG_WRITE(ah, AR_PHY_TIMING7, 0);
+                       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING8, AR_PHY_TIMING8_PILOT_MASK_2, 0);
+                       OS_REG_WRITE(ah, AR_PHY_TIMING9, 0);
+                       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING10, AR_PHY_TIMING10_PILOT_MASK_2, 0);
+
+                       /* Clear magnitude masks */
+                       OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, 0);
+                       OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, 0);
+                       OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, 0);
+                       OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_MASK_4, 0);
+                       OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, 0);
+                       OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, 0);
+                       OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, 0);
+                       OS_REG_RMW_FIELD(ah, AR_PHY_BIN_MASK2_4, AR_PHY_BIN_MASK2_4_MASK_4, 0);
+               }
+       } else {
+               spurOffset = finalSpur - curChanAsSpur;
+               /*
+                * Spur calculations:
+                * spurDeltaPhase is (spurOffsetIn100KHz / chipFrequencyIn100KHz) << 21
+                * spurFreqSd is (spurOffsetIn100KHz / sampleFrequencyIn100KHz) << 11
+                */
+               switch (ichan->channelFlags & CHANNEL_ALL) {
+               case CHANNEL_A: /* Chip Frequency & sampleFrequency are 40 MHz */
+                       spurDeltaPhase = (spurOffset << 17) / 25;
+                       spurFreqSd = spurDeltaPhase >> 10;
+                       binWidth = HAL_BIN_WIDTH_BASE_100HZ;
+                       break;
+               case CHANNEL_G: /* Chip Frequency is 44MHz, sampleFrequency is 40 MHz */
+                       spurFreqSd = (spurOffset << 8) / 55;
+                       spurDeltaPhase = (spurOffset << 17) / 25;
+                       binWidth = HAL_BIN_WIDTH_BASE_100HZ;
+                       break;
+               case CHANNEL_T: /* Chip Frequency & sampleFrequency are 80 MHz */
+               case CHANNEL_108G:
+                       spurDeltaPhase = (spurOffset << 16) / 25;
+                       spurFreqSd = spurDeltaPhase >> 10;
+                       binWidth = HAL_BIN_WIDTH_TURBO_100HZ;
+                       break;
+               }
+
+               /* Compute Pilot Mask */
+               binOffsetNumT16 = ((spurOffset * 1000) << 4) / binWidth;
+               /* The spur is on a bin if it's remainder at times 16 is 0 */
+               if (binOffsetNumT16 & 0xF) {
+                       numBinOffsets = 4;
+                       pMagMap = magMapFor4;
+               } else {
+                       numBinOffsets = 3;
+                       pMagMap = magMapFor3;
+               }
+               for (i = 0; i < numBinOffsets; i++) {
+                       if ((binOffsetNumT16 >> 4) > HAL_MAX_BINS_ALLOWED) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "Too man bins in spur mitigation\n");
+                               return;
+                       }
+
+                       /* Get Pilot Mask values */
+                       curBinOffset = (binOffsetNumT16 >> 4) + i + 25;
+                       if ((curBinOffset >= 0) && (curBinOffset <= 32)) {
+                               if (curBinOffset <= 25)
+                                       pilotMask[0] |= 1 << curBinOffset;
+                               else if (curBinOffset >= 27)
+                                       pilotMask[0] |= 1 << (curBinOffset - 1);
+                       } else if ((curBinOffset >= 33) && (curBinOffset <= 52))
+                               pilotMask[1] |= 1 << (curBinOffset - 33);
+
+                       /* Get viterbi values */
+                       if ((curBinOffset >= -1) && (curBinOffset <= 14))
+                               binMagMask[0] |= pMagMap[i] << (curBinOffset + 1) * 2;
+                       else if ((curBinOffset >= 15) && (curBinOffset <= 30))
+                               binMagMask[1] |= pMagMap[i] << (curBinOffset - 15) * 2;
+                       else if ((curBinOffset >= 31) && (curBinOffset <= 46))
+                               binMagMask[2] |= pMagMap[i] << (curBinOffset -31) * 2;
+                       else if((curBinOffset >= 47) && (curBinOffset <= 53))
+                               binMagMask[3] |= pMagMap[i] << (curBinOffset -47) * 2;
+               }
+
+               /* Write Spur Delta Phase, Spur Freq, and enable bits */
+               OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_RATE, 0xFF);
+               val = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4);
+               val |= (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+                       AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+                       AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+               OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, val);
+               OS_REG_WRITE(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+                            SM(spurFreqSd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+                            SM(spurDeltaPhase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+
+               /* Write pilot masks */
+               OS_REG_WRITE(ah, AR_PHY_TIMING7, pilotMask[0]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_TIMING8, AR_PHY_TIMING8_PILOT_MASK_2, pilotMask[1]);
+               OS_REG_WRITE(ah, AR_PHY_TIMING9, pilotMask[0]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_TIMING10, AR_PHY_TIMING10_PILOT_MASK_2, pilotMask[1]);
+
+               /* Write magnitude masks */
+               OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, binMagMask[0]);
+               OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, binMagMask[1]);
+               OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, binMagMask[2]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_MASK_4, binMagMask[3]);
+               OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, binMagMask[0]);
+               OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, binMagMask[1]);
+               OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, binMagMask[2]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_BIN_MASK2_4, AR_PHY_BIN_MASK2_4_MASK_4, binMagMask[3]);
+       }
+#undef CHAN_TO_SPUR
+}
+
+
+/*
+ * Delta slope coefficient computation.
+ * Required for OFDM operation.
+ */
+void
+ar5212SetDeltaSlope(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+#define COEF_SCALE_S 24
+#define INIT_CLOCKMHZSCALED    0x64000000
+       unsigned long coef_scaled, coef_exp, coef_man, ds_coef_exp, ds_coef_man;
+       unsigned long clockMhzScaled = INIT_CLOCKMHZSCALED;
+
+       if (IS_CHAN_TURBO(chan))
+               clockMhzScaled *= 2;
+       /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */
+       /* scale for selected channel bandwidth */
+       if (IS_CHAN_HALF_RATE(chan)) {
+               clockMhzScaled = clockMhzScaled >> 1;
+       } else if (IS_CHAN_QUARTER_RATE(chan)) {
+               clockMhzScaled = clockMhzScaled >> 2;
+       }
+
+       /*
+        * ALGO -> coef = 1e8/fcarrier*fclock/40;
+        * scaled coef to provide precision for this floating calculation
+        */
+       coef_scaled = clockMhzScaled / chan->channel;
+
+       /*
+        * ALGO -> coef_exp = 14-floor(log2(coef));
+        * floor(log2(x)) is the highest set bit position
+        */
+       for (coef_exp = 31; coef_exp > 0; coef_exp--)
+               if ((coef_scaled >> coef_exp) & 0x1)
+                       break;
+       /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */
+       HALASSERT(coef_exp);
+       coef_exp = 14 - (coef_exp - COEF_SCALE_S);
+
+       /*
+        * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5);
+        * The coefficient is already shifted up for scaling
+        */
+       coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
+       ds_coef_man = coef_man >> (COEF_SCALE_S - coef_exp);
+       ds_coef_exp = coef_exp - 16;
+
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+               AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+               AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+#undef INIT_CLOCKMHZSCALED
+#undef COEF_SCALE_S
+}
+
+/*
+ * Set a limit on the overall output power.  Used for dynamic
+ * transmit power control and the like.
+ *
+ * NB: limit is in units of 0.5 dbM.
+ */
+HAL_BOOL
+ar5212SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
+{
+       uint16_t dummyXpdGains[2];
+       HAL_BOOL ret, isBmode = AH_FALSE;
+
+       SAVE_CCK(ah, AH_PRIVATE(ah)->ah_curchan, isBmode);
+       AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
+       ret = ar5212SetTransmitPower(ah, AH_PRIVATE(ah)->ah_curchan,
+                       dummyXpdGains);
+       RESTORE_CCK(ah, AH_PRIVATE(ah)->ah_curchan, isBmode);
+       return ret;
+}
+
+/*
+ * Set the transmit power in the baseband for the given
+ * operating channel and mode.
+ */
+HAL_BOOL
+ar5212SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t *rfXpdGain)
+{
+#define        POW_OFDM(_r, _s)        (((0 & 1)<< ((_s)+6)) | (((_r) & 0x3f) << (_s)))
+#define        POW_CCK(_r, _s)         (((_r) & 0x3f) << (_s))
+#define        N(a)                    (sizeof (a) / sizeof (a[0]))
+       static const uint16_t tpcScaleReductionTable[5] =
+               { 0, 3, 6, 9, MAX_RATE_POWER };
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       int16_t minPower, maxPower, tpcInDb, powerLimit;
+       int i;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       OS_MEMZERO(ahp->ah_pcdacTable, ahp->ah_pcdacTableSize);
+       OS_MEMZERO(ahp->ah_ratesArray, sizeof(ahp->ah_ratesArray));
+
+       powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit);
+       if (powerLimit >= MAX_RATE_POWER || powerLimit == 0)
+               tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale];
+       else
+               tpcInDb = 0;
+       if (!ar5212SetRateTable(ah, (HAL_CHANNEL *) chan, tpcInDb, powerLimit,
+                               AH_TRUE, &minPower, &maxPower)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set rate table\n",
+                   __func__);
+               return AH_FALSE;
+       }
+       if (!ahp->ah_rfHal->setPowerTable(ah,
+               &minPower, &maxPower, chan, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n",
+                   __func__);
+               return AH_FALSE;
+       }
+
+       /*
+        * Adjust XR power/rate up by 2 dB to account for greater peak
+        * to avg ratio - except in newer avg power designs
+        */
+       if (!IS_2413(ah) && !IS_5413(ah))
+               ahp->ah_ratesArray[15] += 4;
+       /*
+        * txPowerIndexOffset is set by the SetPowerTable() call -
+        *  adjust the rate table
+        */
+       for (i = 0; i < N(ahp->ah_ratesArray); i++) {
+               ahp->ah_ratesArray[i] += ahp->ah_txPowerIndexOffset;
+               if (ahp->ah_ratesArray[i] > 63)
+                       ahp->ah_ratesArray[i] = 63;
+       }
+
+       if (ee->ee_eepMap < 2) {
+               /*
+                * Correct gain deltas for 5212 G operation -
+                * Removed with revised chipset
+                */
+               if (AH_PRIVATE(ah)->ah_phyRev < AR_PHY_CHIP_ID_REV_2 &&
+                   IS_CHAN_G(chan)) {
+                       uint16_t cckOfdmPwrDelta;
+
+                       if (chan->channel == 2484)
+                               cckOfdmPwrDelta = SCALE_OC_DELTA(
+                                       ee->ee_cckOfdmPwrDelta -
+                                       ee->ee_scaledCh14FilterCckDelta);
+                       else
+                               cckOfdmPwrDelta = SCALE_OC_DELTA(
+                                       ee->ee_cckOfdmPwrDelta);
+                       ar5212CorrectGainDelta(ah, cckOfdmPwrDelta);
+               }
+               /*
+                * Finally, write the power values into the
+                * baseband power table
+                */
+               for (i = 0; i < (PWR_TABLE_SIZE/2); i++) {
+                       OS_REG_WRITE(ah, AR_PHY_PCDAC_TX_POWER(i),
+                                ((((ahp->ah_pcdacTable[2*i + 1] << 8) | 0xff) & 0xffff) << 16)
+                               | (((ahp->ah_pcdacTable[2*i]     << 8) | 0xff) & 0xffff)
+                       );
+               }
+       }
+
+       /* Write the OFDM power per rate set */
+       OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+               POW_OFDM(ahp->ah_ratesArray[3], 24)
+             | POW_OFDM(ahp->ah_ratesArray[2], 16)
+             | POW_OFDM(ahp->ah_ratesArray[1],  8)
+             | POW_OFDM(ahp->ah_ratesArray[0],  0)
+       );
+       OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+               POW_OFDM(ahp->ah_ratesArray[7], 24)
+             | POW_OFDM(ahp->ah_ratesArray[6], 16)
+             | POW_OFDM(ahp->ah_ratesArray[5],  8)
+             | POW_OFDM(ahp->ah_ratesArray[4],  0)
+       );
+
+       /* Write the CCK power per rate set */
+       OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+               POW_CCK(ahp->ah_ratesArray[10], 24)
+             | POW_CCK(ahp->ah_ratesArray[9],  16)
+             | POW_CCK(ahp->ah_ratesArray[15],  8)     /* XR target power */
+             | POW_CCK(ahp->ah_ratesArray[8],   0)
+       );
+       OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+               POW_CCK(ahp->ah_ratesArray[14], 24)
+             | POW_CCK(ahp->ah_ratesArray[13], 16)
+             | POW_CCK(ahp->ah_ratesArray[12],  8)
+             | POW_CCK(ahp->ah_ratesArray[11],  0)
+       );
+
+       /*
+        * Set max power to 30 dBm and, optionally,
+        * enable TPC in tx descriptors.
+        */
+       OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER |
+               (ahp->ah_tpcEnabled ? AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE : 0));
+
+       return AH_TRUE;
+#undef N
+#undef POW_CCK
+#undef POW_OFDM
+}
+
+/*
+ * Sets the transmit power in the baseband for the given
+ * operating channel and mode.
+ */
+static HAL_BOOL
+ar5212SetRateTable(struct ath_hal *ah, HAL_CHANNEL *chan,
+                  int16_t tpcScaleReduction, int16_t powerLimit, HAL_BOOL commit,
+                   int16_t *pMinPower, int16_t *pMaxPower)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t *rpow = ahp->ah_ratesArray;
+       uint16_t twiceMaxEdgePower = MAX_RATE_POWER;
+       uint16_t twiceMaxEdgePowerCck = MAX_RATE_POWER;
+       uint16_t twiceMaxRDPower = MAX_RATE_POWER;
+       int i;
+       uint8_t cfgCtl;
+       int8_t twiceAntennaGain, twiceAntennaReduction;
+       const RD_EDGES_POWER *rep;
+       TRGT_POWER_INFO targetPowerOfdm, targetPowerCck;
+       int16_t scaledPower, maxAvailPower = 0;
+       int16_t r13, r9, r7, r0;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       twiceMaxRDPower = chan->maxRegTxPower * 2;
+       *pMaxPower = -MAX_RATE_POWER;
+       *pMinPower = MAX_RATE_POWER;
+
+       /* Get conformance test limit maximum for this channel */
+       cfgCtl = ath_hal_getctl(ah, chan);
+       for (i = 0; i < ee->ee_numCtls; i++) {
+               uint16_t twiceMinEdgePower;
+
+               if (ee->ee_ctl[i] == 0)
+                       continue;
+               if (ee->ee_ctl[i] == cfgCtl ||
+                   cfgCtl == ((ee->ee_ctl[i] & CTL_MODE_M) | SD_NO_CTL)) {
+                       rep = &ee->ee_rdEdgesPower[i * NUM_EDGES];
+                       twiceMinEdgePower = ar5212GetMaxEdgePower(chan->channel, rep);
+                       if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+                               /* Find the minimum of all CTL edge powers that apply to this channel */
+                               twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower);
+                       } else {
+                               twiceMaxEdgePower = twiceMinEdgePower;
+                               break;
+                       }
+               }
+       }
+
+       if (IS_CHAN_G(chan)) {
+               /* Check for a CCK CTL for 11G CCK powers */
+               cfgCtl = (cfgCtl & ~CTL_MODE_M) | CTL_11B;
+               for (i = 0; i < ee->ee_numCtls; i++) {
+                       uint16_t twiceMinEdgePowerCck;
+
+                       if (ee->ee_ctl[i] == 0)
+                               continue;
+                       if (ee->ee_ctl[i] == cfgCtl ||
+                           cfgCtl == ((ee->ee_ctl[i] & CTL_MODE_M) | SD_NO_CTL)) {
+                               rep = &ee->ee_rdEdgesPower[i * NUM_EDGES];
+                               twiceMinEdgePowerCck = ar5212GetMaxEdgePower(chan->channel, rep);
+                               if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+                                       /* Find the minimum of all CTL edge powers that apply to this channel */
+                                       twiceMaxEdgePowerCck = AH_MIN(twiceMaxEdgePowerCck, twiceMinEdgePowerCck);
+                               } else {
+                                       twiceMaxEdgePowerCck = twiceMinEdgePowerCck;
+                                       break;
+                               }
+                       }
+               }
+       } else {
+               /* Set the 11B cck edge power to the one found before */
+               twiceMaxEdgePowerCck = twiceMaxEdgePower;
+       }
+
+       /* Get Antenna Gain reduction */
+       if (IS_CHAN_5GHZ(chan)) {
+               ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_5, &twiceAntennaGain);
+       } else {
+               ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_2, &twiceAntennaGain);
+       }
+       twiceAntennaReduction =
+               ath_hal_getantennareduction(ah, chan, twiceAntennaGain);
+
+       if (IS_CHAN_OFDM(chan)) {
+               /* Get final OFDM target powers */
+               if (IS_CHAN_2GHZ(chan)) {
+                       ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11g,
+                               ee->ee_numTargetPwr_11g, &targetPowerOfdm);
+               } else {
+                       ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11a,
+                               ee->ee_numTargetPwr_11a, &targetPowerOfdm);
+               }
+
+               /* Get Maximum OFDM power */
+               /* Minimum of target and edge powers */
+               scaledPower = AH_MIN(twiceMaxEdgePower,
+                               twiceMaxRDPower - twiceAntennaReduction);
+
+               /*
+                * If turbo is set, reduce power to keep power
+                * consumption under 2 Watts.  Note that we always do
+                * this unless specially configured.  Then we limit
+                * power only for non-AP operation.
+                */
+               if (IS_CHAN_TURBO(chan)
+#ifdef AH_ENABLE_AP_SUPPORT
+                   && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP
+#endif
+               ) {
+                       /*
+                        * If turbo is set, reduce power to keep power
+                        * consumption under 2 Watts
+                        */
+                       if (ee->ee_version >= AR_EEPROM_VER3_1)
+                               scaledPower = AH_MIN(scaledPower,
+                                       ee->ee_turbo2WMaxPower5);
+                       /*
+                        * EEPROM version 4.0 added an additional
+                        * constraint on 2.4GHz channels.
+                        */
+                       if (ee->ee_version >= AR_EEPROM_VER4_0 &&
+                           IS_CHAN_2GHZ(chan))
+                               scaledPower = AH_MIN(scaledPower,
+                                       ee->ee_turbo2WMaxPower2);
+               }
+
+               maxAvailPower = AH_MIN(scaledPower,
+                                       targetPowerOfdm.twicePwr6_24);
+
+               /* Reduce power by max regulatory domain allowed restrictions */
+               scaledPower = maxAvailPower - (tpcScaleReduction * 2);
+               scaledPower = (scaledPower < 0) ? 0 : scaledPower;
+               scaledPower = AH_MIN(scaledPower, powerLimit);
+
+               if (commit) {
+                       /* Set OFDM rates 9, 12, 18, 24 */
+                       r0 = rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower;
+
+                       /* Set OFDM rates 36, 48, 54, XR */
+                       rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36);
+                       rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48);
+                       r7 = rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54);
+
+                       if (ee->ee_version >= AR_EEPROM_VER4_0) {
+                               /* Setup XR target power from EEPROM */
+                               rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ?
+                                                 ee->ee_xrTargetPower2 : ee->ee_xrTargetPower5);
+                       } else {
+                               /* XR uses 6mb power */
+                               rpow[15] = rpow[0];
+                       }
+                       ahp->ah_ofdmTxPower = *pMaxPower;
+
+               } else {
+                       r0 = scaledPower;
+                       r7 = AH_MIN(r0, targetPowerOfdm.twicePwr54);
+               }
+               *pMinPower = r7;
+               *pMaxPower = r0;
+
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                   "%s: MaxRD: %d TurboMax: %d MaxCTL: %d "
+                   "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n",
+                   __func__, twiceMaxRDPower, ee->ee_turbo2WMaxPower5,
+                   twiceMaxEdgePower, tpcScaleReduction * 2,
+                   chan->channel, chan->channelFlags,
+                   maxAvailPower, targetPowerOfdm.twicePwr6_24, *pMaxPower);
+       }
+
+       if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) {
+               /* Get final CCK target powers */
+               ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11b,
+                       ee->ee_numTargetPwr_11b, &targetPowerCck);
+
+               /* Reduce power by max regulatory domain allowed restrictions */
+               scaledPower = AH_MIN(twiceMaxEdgePowerCck,
+                       twiceMaxRDPower - twiceAntennaReduction);
+               if (maxAvailPower < AH_MIN(scaledPower, targetPowerCck.twicePwr6_24))
+                       maxAvailPower = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24);
+
+               /* Reduce power by user selection */
+               scaledPower = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24) - (tpcScaleReduction * 2);
+               scaledPower = (scaledPower < 0) ? 0 : scaledPower;
+               scaledPower = AH_MIN(scaledPower, powerLimit);
+
+               if (commit) {
+                       /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */
+                       rpow[8]  = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24);
+                       r9 = rpow[9]  = AH_MIN(scaledPower, targetPowerCck.twicePwr36);
+                       rpow[10] = rpow[9];
+                       rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48);
+                       rpow[12] = rpow[11];
+                       r13 = rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54);
+                       rpow[14] = rpow[13];
+               } else {
+                       r9 = AH_MIN(scaledPower, targetPowerCck.twicePwr36);
+                       r13 = AH_MIN(scaledPower, targetPowerCck.twicePwr54);
+               }
+
+               /* Set min/max power based off OFDM values or initialization */
+               if (r13 < *pMinPower)
+                       *pMinPower = r13;
+               if (r9 > *pMaxPower)
+                       *pMaxPower = r9;
+
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                   "%s: cck: MaxRD: %d MaxCTL: %d "
+                   "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n",
+                   __func__, twiceMaxRDPower, twiceMaxEdgePowerCck,
+                   tpcScaleReduction * 2, chan->channel, chan->channelFlags,
+                   maxAvailPower, targetPowerCck.twicePwr6_24, *pMaxPower);
+       }
+       if (commit) {
+               ahp->ah_tx6PowerInHalfDbm = *pMaxPower;
+               AH_PRIVATE(ah)->ah_maxPowerLevel = ahp->ah_tx6PowerInHalfDbm;
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5212GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       static const uint16_t tpcScaleReductionTable[5] =
+               { 0, 3, 6, 9, MAX_RATE_POWER };
+       int16_t minPower, maxPower, tpcInDb, powerLimit;
+       HAL_CHANNEL *chan;
+       int i;
+
+       /*
+        * Get Pier table max and min powers.
+        */
+       for (i = 0; i < nchans; i++) {
+               chan = &chans[i];
+               if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) {
+                       /* NB: rf code returns 1/4 dBm units, convert */
+                       chan->maxTxPower = maxPower / 2;
+                       chan->minTxPower = minPower / 2;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: no min/max power for %u/0x%x\n",
+                           __func__, chan->channel, chan->channelFlags);
+                       chan->maxTxPower = MAX_RATE_POWER;
+                       chan->minTxPower = 0;
+               }
+       }
+       /*
+        * Now adjust to reflect any global scale and/or CTL's.
+        * (XXX is that correct?)
+        */
+       powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit);
+       if (powerLimit >= MAX_RATE_POWER || powerLimit == 0)
+               tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale];
+       else
+               tpcInDb = 0;
+       for (i=0; i<nchans; i++) {
+               chan = &chans[i];
+               if (!ar5212SetRateTable(ah, (HAL_CHANNEL *) chan, tpcInDb, powerLimit,
+                                       AH_FALSE, &minPower, &maxPower)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: unable to find max/min power\n",__func__);
+                       return AH_FALSE;
+               }
+               if (maxPower < chan->maxTxPower)
+                       chan->maxTxPower = maxPower;
+               if (minPower < chan->minTxPower)
+                       chan->minTxPower = minPower;
+       }
+#ifdef AH_DEBUG
+       for (i=0; i<nchans; i++) {
+               HALDEBUG(ah, HAL_DEBUG_RESET,
+                   "Chan %d: MaxPow = %d MinPow = %d\n",
+                   chans[i].channel,chans[i].maxTxPower, chans[i].minTxPower);
+       }
+#endif
+       return AH_TRUE;
+}
+
+/*
+ * Correct for the gain-delta between ofdm and cck mode target
+ * powers. Write the results to the rate table and the power table.
+ *
+ *   Conventions :
+ *   1. rpow[ii] is the integer value of 2*(desired power
+ *    for the rate ii in dBm) to provide 0.5dB resolution. rate
+ *    mapping is as following :
+ *     [0..7]  --> ofdm 6, 9, .. 48, 54
+ *     [8..14] --> cck 1L, 2L, 2S, .. 11L, 11S
+ *     [15]    --> XR (all rates get the same power)
+ *   2. powv[ii]  is the pcdac corresponding to ii/2 dBm.
+ */
+static void
+ar5212CorrectGainDelta(struct ath_hal *ah, int twiceOfdmCckDelta)
+{
+#define        N(_a)   (sizeof(_a) / sizeof(_a[0]))
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       int16_t ratesIndex[N(ahp->ah_ratesArray)];
+       uint16_t ii, jj, iter;
+       int32_t cckIndex;
+       int16_t gainDeltaAdjust;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       gainDeltaAdjust = ee->ee_cckOfdmGainDelta;
+
+       /* make a local copy of desired powers as initial indices */
+       OS_MEMCPY(ratesIndex, ahp->ah_ratesArray, sizeof(ratesIndex));
+
+       /* fix only the CCK indices */
+       for (ii = 8; ii < 15; ii++) {
+               /* apply a gain_delta correction of -15 for CCK */
+               ratesIndex[ii] -= gainDeltaAdjust;
+
+               /* Now check for contention with all ofdm target powers */
+               jj = 0;
+               iter = 0;
+               /* indicates not all ofdm rates checked forcontention yet */
+               while (jj < 16) {
+                       if (ratesIndex[ii] < 0)
+                               ratesIndex[ii] = 0;
+                       if (jj == 8) {          /* skip CCK rates */
+                               jj = 15;
+                               continue;
+                       }
+                       if (ratesIndex[ii] == ahp->ah_ratesArray[jj]) {
+                               if (ahp->ah_ratesArray[jj] == 0)
+                                       ratesIndex[ii]++;
+                               else if (iter > 50) {
+                                       /*
+                                        * To avoid pathological case of of
+                                        * dm target powers 0 and 0.5dBm
+                                        */
+                                       ratesIndex[ii]++;
+                               } else
+                                       ratesIndex[ii]--;
+                               /* check with all rates again */
+                               jj = 0;
+                               iter++;
+                       } else
+                               jj++;
+               }
+               if (ratesIndex[ii] >= PWR_TABLE_SIZE)
+                       ratesIndex[ii] = PWR_TABLE_SIZE -1;
+               cckIndex = ahp->ah_ratesArray[ii] - twiceOfdmCckDelta;
+               if (cckIndex < 0)
+                       cckIndex = 0;
+
+               /*
+                * Validate that the indexes for the powv are not
+                * out of bounds.
+                */
+               HALASSERT(cckIndex < PWR_TABLE_SIZE);
+               HALASSERT(ratesIndex[ii] < PWR_TABLE_SIZE);
+               ahp->ah_pcdacTable[ratesIndex[ii]] =
+                       ahp->ah_pcdacTable[cckIndex];
+       }
+       /* Override rate per power table with new values */
+       for (ii = 8; ii < 15; ii++)
+               ahp->ah_ratesArray[ii] = ratesIndex[ii];
+#undef N
+}
+
+/*
+ * Find the maximum conformance test limit for the given channel and CTL info
+ */
+static uint16_t
+ar5212GetMaxEdgePower(uint16_t channel, const RD_EDGES_POWER *pRdEdgesPower)
+{
+       /* temp array for holding edge channels */
+       uint16_t tempChannelList[NUM_EDGES];
+       uint16_t clo = 0, chi = 0, twiceMaxEdgePower;
+       int i, numEdges;
+
+       /* Get the edge power */
+       for (i = 0; i < NUM_EDGES; i++) {
+               if (pRdEdgesPower[i].rdEdge == 0)
+                       break;
+               tempChannelList[i] = pRdEdgesPower[i].rdEdge;
+       }
+       numEdges = i;
+
+       ar5212GetLowerUpperValues(channel, tempChannelList,
+               numEdges, &clo, &chi);
+       /* Get the index for the lower channel */
+       for (i = 0; i < numEdges && clo != tempChannelList[i]; i++)
+               ;
+       /* Is lower channel ever outside the rdEdge? */
+       HALASSERT(i != numEdges);
+
+       if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) {
+               /*
+                * If there's an exact channel match or an inband flag set
+                * on the lower channel use the given rdEdgePower
+                */
+               twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower;
+               HALASSERT(twiceMaxEdgePower > 0);
+       } else
+               twiceMaxEdgePower = MAX_RATE_POWER;
+       return twiceMaxEdgePower;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+static uint16_t
+interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+       uint16_t targetLeft, uint16_t targetRight)
+{
+       uint16_t rv;
+       int16_t lRatio;
+
+       /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */
+       if ((targetLeft * targetRight) == 0)
+               return 0;
+
+       if (srcRight != srcLeft) {
+               /*
+                * Note the ratio always need to be scaled,
+                * since it will be a fraction.
+                */
+               lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft);
+               if (lRatio < 0) {
+                   /* Return as Left target if value would be negative */
+                   rv = targetLeft;
+               } else if (lRatio > EEP_SCALE) {
+                   /* Return as Right target if Ratio is greater than 100% (SCALE) */
+                   rv = targetRight;
+               } else {
+                       rv = (lRatio * targetRight + (EEP_SCALE - lRatio) *
+                                       targetLeft) / EEP_SCALE;
+               }
+       } else {
+               rv = targetLeft;
+       }
+       return rv;
+}
+
+/*
+ * Return the four rates of target power for the given target power table
+ * channel, and number of channels
+ */
+static void
+ar5212GetTargetPowers(struct ath_hal *ah, HAL_CHANNEL *chan,
+       const TRGT_POWER_INFO *powInfo,
+       uint16_t numChannels, TRGT_POWER_INFO *pNewPower)
+{
+       /* temp array for holding target power channels */
+       uint16_t tempChannelList[NUM_TEST_FREQUENCIES];
+       uint16_t clo = 0, chi = 0, ixlo, ixhi;
+       int i;
+
+       /* Copy the target powers into the temp channel list */
+       for (i = 0; i < numChannels; i++)
+               tempChannelList[i] = powInfo[i].testChannel;
+
+       ar5212GetLowerUpperValues(chan->channel, tempChannelList,
+               numChannels, &clo, &chi);
+
+       /* Get the indices for the channel */
+       ixlo = ixhi = 0;
+       for (i = 0; i < numChannels; i++) {
+               if (clo == tempChannelList[i]) {
+                       ixlo = i;
+               }
+               if (chi == tempChannelList[i]) {
+                       ixhi = i;
+                       break;
+               }
+       }
+
+       /*
+        * Get the lower and upper channels, target powers,
+        * and interpolate between them.
+        */
+       pNewPower->twicePwr6_24 = interpolate(chan->channel, clo, chi,
+               powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24);
+       pNewPower->twicePwr36 = interpolate(chan->channel, clo, chi,
+               powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36);
+       pNewPower->twicePwr48 = interpolate(chan->channel, clo, chi,
+               powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48);
+       pNewPower->twicePwr54 = interpolate(chan->channel, clo, chi,
+               powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54);
+}
+
+/*
+ * Search a list for a specified value v that is within
+ * EEP_DELTA of the search values.  Return the closest
+ * values in the list above and below the desired value.
+ * EEP_DELTA is a factional value; everything is scaled
+ * so only integer arithmetic is used.
+ *
+ * NB: the input list is assumed to be sorted in ascending order
+ */
+void
+ar5212GetLowerUpperValues(uint16_t v, uint16_t *lp, uint16_t listSize,
+                          uint16_t *vlo, uint16_t *vhi)
+{
+       uint32_t target = v * EEP_SCALE;
+       uint16_t *ep = lp+listSize;
+
+       /*
+        * Check first and last elements for out-of-bounds conditions.
+        */
+       if (target < (uint32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) {
+               *vlo = *vhi = lp[0];
+               return;
+       }
+       if (target > (uint32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) {
+               *vlo = *vhi = ep[-1];
+               return;
+       }
+
+       /* look for value being near or between 2 values in list */
+       for (; lp < ep; lp++) {
+               /*
+                * If value is close to the current value of the list
+                * then target is not between values, it is one of the values
+                */
+               if (abs(lp[0] * EEP_SCALE - target) < EEP_DELTA) {
+                       *vlo = *vhi = lp[0];
+                       return;
+               }
+               /*
+                * Look for value being between current value and next value
+                * if so return these 2 values
+                */
+               if (target < (uint32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) {
+                       *vlo = lp[0];
+                       *vhi = lp[1];
+                       return;
+               }
+       }
+       HALASSERT(AH_FALSE);            /* should not reach here */
+}
+
+/*
+ * Perform analog "swizzling" of parameters into their location
+ *
+ * NB: used by RF backends
+ */
+void
+ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, uint32_t numBits,
+                     uint32_t firstBit, uint32_t column)
+{
+#define        MAX_ANALOG_START        319             /* XXX */
+       uint32_t tmp32, mask, arrayEntry, lastBit;
+       int32_t bitPosition, bitsLeft;
+
+       HALASSERT(column <= 3);
+       HALASSERT(numBits <= 32);
+       HALASSERT(firstBit + numBits <= MAX_ANALOG_START);
+
+       tmp32 = ath_hal_reverseBits(reg32, numBits);
+       arrayEntry = (firstBit - 1) / 8;
+       bitPosition = (firstBit - 1) % 8;
+       bitsLeft = numBits;
+       while (bitsLeft > 0) {
+               lastBit = (bitPosition + bitsLeft > 8) ?
+                       8 : bitPosition + bitsLeft;
+               mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
+                       (column * 8);
+               rfBuf[arrayEntry] &= ~mask;
+               rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
+                       (column * 8)) & mask;
+               bitsLeft -= 8 - bitPosition;
+               tmp32 = tmp32 >> (8 - bitPosition);
+               bitPosition = 0;
+               arrayEntry++;
+       }
+#undef MAX_ANALOG_START
+}
+
+/*
+ * Sets the rate to duration values in MAC - used for multi-
+ * rate retry.
+ * The rate duration table needs to cover all valid rate codes;
+ * the 11g table covers all ofdm rates, while the 11b table
+ * covers all cck rates => all valid rates get covered between
+ * these two mode's ratetables!
+ * But if we're turbo, the ofdm phy is replaced by the turbo phy
+ * and cck is not valid with turbo => all rates get covered
+ * by the turbo ratetable only
+ */
+void
+ar5212SetRateDurationTable(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       const HAL_RATE_TABLE *rt;
+       int i;
+
+       /* NB: band doesn't matter for 1/2 and 1/4 rate */
+       if (IS_CHAN_HALF_RATE(chan)) {
+               rt = ar5212GetRateTable(ah, HAL_MODE_11A_HALF_RATE);
+       } else if (IS_CHAN_QUARTER_RATE(chan)) {
+               rt = ar5212GetRateTable(ah, HAL_MODE_11A_QUARTER_RATE);
+       } else {
+               rt = ar5212GetRateTable(ah,
+                       IS_CHAN_TURBO(chan) ? HAL_MODE_TURBO : HAL_MODE_11G);
+       }
+
+       for (i = 0; i < rt->rateCount; ++i)
+               OS_REG_WRITE(ah,
+                       AR_RATE_DURATION(rt->info[i].rateCode),
+                       ath_hal_computetxtime(ah, rt,
+                               WLAN_CTRL_FRAME_SIZE,
+                               rt->info[i].controlRate, AH_FALSE));
+       if (!IS_CHAN_TURBO(chan)) {
+               /* 11g Table is used to cover the CCK rates. */
+               rt = ar5212GetRateTable(ah, HAL_MODE_11G);
+               for (i = 0; i < rt->rateCount; ++i) {
+                       uint32_t reg = AR_RATE_DURATION(rt->info[i].rateCode);
+
+                       if (rt->info[i].phy != IEEE80211_T_CCK)
+                               continue;
+
+                       OS_REG_WRITE(ah, reg,
+                               ath_hal_computetxtime(ah, rt,
+                                       WLAN_CTRL_FRAME_SIZE,
+                                       rt->info[i].controlRate, AH_FALSE));
+                       /* cck rates have short preamble option also */
+                       if (rt->info[i].shortPreamble) {
+                               reg += rt->info[i].shortPreamble << 2;
+                               OS_REG_WRITE(ah, reg,
+                                       ath_hal_computetxtime(ah, rt,
+                                               WLAN_CTRL_FRAME_SIZE,
+                                               rt->info[i].controlRate,
+                                               AH_TRUE));
+                       }
+               }
+       }
+}
+
+/* Adjust various register settings based on half/quarter rate clock setting.
+ * This includes: +USEC, TX/RX latency,
+ *                + IFS params: slot, eifs, misc etc.
+ */
+void
+ar5212SetIFSTiming(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t txLat, rxLat, usec, slot, refClock, eifs, init_usec;
+
+       HALASSERT(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan));
+
+       refClock = OS_REG_READ(ah, AR_USEC) & AR_USEC_USEC32;
+       if (IS_CHAN_HALF_RATE(chan)) {
+               slot = IFS_SLOT_HALF_RATE;
+               rxLat = RX_NON_FULL_RATE_LATENCY << AR5212_USEC_RX_LAT_S;
+               txLat = TX_HALF_RATE_LATENCY << AR5212_USEC_TX_LAT_S;
+               usec = HALF_RATE_USEC;
+               eifs = IFS_EIFS_HALF_RATE;
+               init_usec = INIT_USEC >> 1;
+       } else { /* quarter rate */
+               slot = IFS_SLOT_QUARTER_RATE;
+               rxLat = RX_NON_FULL_RATE_LATENCY << AR5212_USEC_RX_LAT_S;
+               txLat = TX_QUARTER_RATE_LATENCY << AR5212_USEC_TX_LAT_S;
+               usec = QUARTER_RATE_USEC;
+               eifs = IFS_EIFS_QUARTER_RATE;
+               init_usec = INIT_USEC >> 2;
+       }
+
+       OS_REG_WRITE(ah, AR_USEC, (usec | refClock | txLat | rxLat));
+       OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
+       OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
+       OS_REG_RMW_FIELD(ah, AR_D_GBL_IFS_MISC,
+                               AR_D_GBL_IFS_MISC_USEC_DURATION, init_usec);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_rfgain.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_rfgain.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#include "ah_eeprom_v3.h"
+
+static const GAIN_OPTIMIZATION_LADDER gainLadder = {
+       9,                                      /* numStepsInLadder */
+       4,                                      /* defaultStepNum */
+       { { {4, 1, 1, 1},  6, "FG8"},
+         { {4, 0, 1, 1},  4, "FG7"},
+         { {3, 1, 1, 1},  3, "FG6"},
+         { {4, 0, 0, 1},  1, "FG5"},
+         { {4, 1, 1, 0},  0, "FG4"},   /* noJack */
+         { {4, 0, 1, 0}, -2, "FG3"},   /* halfJack */
+         { {3, 1, 1, 0}, -3, "FG2"},   /* clip3 */
+         { {4, 0, 0, 0}, -4, "FG1"},   /* noJack */
+         { {2, 1, 1, 0}, -6, "FG0"}    /* clip2 */
+       }
+};
+
+static const GAIN_OPTIMIZATION_LADDER gainLadder5112 = {
+       8,                                      /* numStepsInLadder */
+       1,                                      /* defaultStepNum */
+       { { {3, 0,0,0, 0,0,0},   6, "FG7"},     /* most fixed gain */
+         { {2, 0,0,0, 0,0,0},   0, "FG6"},
+         { {1, 0,0,0, 0,0,0},  -3, "FG5"},
+         { {0, 0,0,0, 0,0,0},  -6, "FG4"},
+         { {0, 1,1,0, 0,0,0},  -8, "FG3"},
+         { {0, 1,1,0, 1,1,0}, -10, "FG2"},
+         { {0, 1,0,1, 1,1,0}, -13, "FG1"},
+         { {0, 1,0,1, 1,0,1}, -16, "FG0"},     /* least fixed gain */
+       }
+};
+
+/*
+ * Initialize the gain structure to good values
+ */
+void
+ar5212InitializeGainValues(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       GAIN_VALUES *gv = &ahp->ah_gainValues;
+
+       /* initialize gain optimization values */
+       if (IS_RAD5112_ANY(ah)) {
+               gv->currStepNum = gainLadder5112.defaultStepNum;
+               gv->currStep =
+                       &gainLadder5112.optStep[gainLadder5112.defaultStepNum];
+               gv->active = AH_TRUE;
+               gv->loTrig = 20;
+               gv->hiTrig = 85;
+       } else {
+               gv->currStepNum = gainLadder.defaultStepNum;
+               gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum];
+               gv->active = AH_TRUE;
+               gv->loTrig = 20;
+               gv->hiTrig = 35;
+       }
+}
+
+#define        MAX_ANALOG_START        319             /* XXX */
+
+/*
+ * Find analog bits of given parameter data and return a reversed value
+ */
+static uint32_t
+ar5212GetRfField(uint32_t *rfBuf, uint32_t numBits, uint32_t firstBit, uint32_t column)
+{
+       uint32_t reg32 = 0, mask, arrayEntry, lastBit;
+       uint32_t bitPosition, bitsShifted;
+       int32_t bitsLeft;
+
+       HALASSERT(column <= 3);
+       HALASSERT(numBits <= 32);
+       HALASSERT(firstBit + numBits <= MAX_ANALOG_START);
+
+       arrayEntry = (firstBit - 1) / 8;
+       bitPosition = (firstBit - 1) % 8;
+       bitsLeft = numBits;
+       bitsShifted = 0;
+       while (bitsLeft > 0) {
+               lastBit = (bitPosition + bitsLeft > 8) ?
+                       (8) : (bitPosition + bitsLeft);
+               mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
+                       (column * 8);
+               reg32 |= (((rfBuf[arrayEntry] & mask) >> (column * 8)) >>
+                       bitPosition) << bitsShifted;
+               bitsShifted += lastBit - bitPosition;
+               bitsLeft -= (8 - bitPosition);
+               bitPosition = 0;
+               arrayEntry++;
+       }
+       reg32 = ath_hal_reverseBits(reg32, numBits);
+       return reg32;
+}
+
+static HAL_BOOL
+ar5212InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv)
+{
+       uint32_t gStep, g, mixOvr;
+       uint32_t L1, L2, L3, L4;
+
+       if (IS_RAD5112_ANY(ah)) {
+               mixOvr = ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0);
+               L1 = 0;
+               L2 = 107;
+               L3 = 0;
+               L4 = 107;
+               if (mixOvr == 1) {
+                       L2 = 83;
+                       L4 = 83;
+                       gv->hiTrig = 55;
+               }
+       } else {
+               gStep = ar5212GetRfField(ar5212GetRfBank(ah, 7), 6, 37, 0);
+
+               L1 = 0;
+               L2 = (gStep == 0x3f) ? 50 : gStep + 4;
+               L3 = (gStep != 0x3f) ? 0x40 : L1;
+               L4 = L3 + 50;
+
+               gv->loTrig = L1 + (gStep == 0x3f ? DYN_ADJ_LO_MARGIN : 0);
+               /* never adjust if != 0x3f */
+               gv->hiTrig = L4 - (gStep == 0x3f ? DYN_ADJ_UP_MARGIN : -5);
+       }
+       g = gv->currGain;
+
+       return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4));
+}
+
+/*
+ * Enable the probe gain check on the next packet
+ */
+void
+ar5212RequestRfgain(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t probePowerIndex;
+
+       /* Enable the gain readback probe */
+       probePowerIndex = ahp->ah_ofdmTxPower + ahp->ah_txPowerIndexOffset;
+       OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE,
+                 SM(probePowerIndex, AR_PHY_PAPD_PROBE_POWERTX)
+               | AR_PHY_PAPD_PROBE_NEXT_TX);
+
+       ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED;
+}
+
+/*
+ * Check to see if our readback gain level sits within the linear
+ * region of our current variable attenuation window
+ */
+static HAL_BOOL
+ar5212IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv)
+{
+       return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig);
+}
+
+/*
+ * Move the rabbit ears in the correct direction.
+ */
+static int32_t
+ar5212AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv)
+{
+       const GAIN_OPTIMIZATION_LADDER *gl;
+
+       if (IS_RAD5112_ANY(ah))
+               gl = &gainLadder5112;
+       else
+               gl = &gainLadder;
+       gv->currStep = &gl->optStep[gv->currStepNum];
+       if (gv->currGain >= gv->hiTrig) {
+               if (gv->currStepNum == 0) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Max gain limit.\n",
+                           __func__);
+                       return -1;
+               }
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                   "%s: Adding gain: currG=%d [%s] --> ",
+                   __func__, gv->currGain, gv->currStep->stepName);
+               gv->targetGain = gv->currGain;
+               while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) {
+                       gv->targetGain -= 2 * (gl->optStep[--(gv->currStepNum)].stepGain -
+                               gv->currStep->stepGain);
+                       gv->currStep = &gl->optStep[gv->currStepNum];
+               }
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
+                   gv->targetGain, gv->currStep->stepName);
+               return 1;
+       }
+       if (gv->currGain <= gv->loTrig) {
+               if (gv->currStepNum == gl->numStepsInLadder-1) {
+                       HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                           "%s: Min gain limit.\n", __func__);
+                       return -2;
+               }
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+                   "%s: Deducting gain: currG=%d [%s] --> ",
+                   __func__, gv->currGain, gv->currStep->stepName);
+               gv->targetGain = gv->currGain;
+               while (gv->targetGain <= gv->loTrig &&
+                     gv->currStepNum < (gl->numStepsInLadder - 1)) {
+                       gv->targetGain -= 2 *
+                               (gl->optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain);
+                       gv->currStep = &gl->optStep[gv->currStepNum];
+               }
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
+                   gv->targetGain, gv->currStep->stepName);
+               return 2;
+       }
+       return 0;               /* caller didn't call needAdjGain first */
+}
+
+/*
+ * Read rf register to determine if gainF needs correction
+ */
+static void
+ar5212GetGainFCorrection(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       GAIN_VALUES *gv = &ahp->ah_gainValues;
+
+       HALASSERT(IS_RADX112_REV2(ah));
+
+       gv->gainFCorrection = 0;
+       if (ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0) == 1) {
+               uint32_t mixGain = gv->currStep->paramVal[0];
+               uint32_t gainStep =
+                       ar5212GetRfField(ar5212GetRfBank(ah, 7), 4, 32, 0);
+               switch (mixGain) {
+               case 0 :
+                       gv->gainFCorrection = 0;
+                       break;
+               case 1 :
+                       gv->gainFCorrection = gainStep;
+                       break;
+               case 2 :
+                       gv->gainFCorrection = 2 * gainStep - 5;
+                       break;
+               case 3 :
+                       gv->gainFCorrection = 2 * gainStep;
+                       break;
+               }
+       }
+}
+
+/*
+ * Exported call to check for a recent gain reading and return
+ * the current state of the thermal calibration gain engine.
+ */
+HAL_RFGAIN
+ar5212GetRfgain(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       GAIN_VALUES *gv = &ahp->ah_gainValues;
+       uint32_t rddata, probeType;
+
+       if (!gv->active)
+               return HAL_RFGAIN_INACTIVE;
+
+       if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) {
+               /* Caller had asked to setup a new reading. Check it. */
+               rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE);
+
+               if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) {
+                       /* bit got cleared, we have a new reading. */
+                       gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S;
+                       probeType = MS(rddata, AR_PHY_PAPD_PROBE_TYPE);
+                       if (probeType == AR_PHY_PAPD_PROBE_TYPE_CCK) {
+                               const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+                               HALASSERT(IS_RAD5112_ANY(ah));
+                               HALASSERT(ah->ah_magic == AR5212_MAGIC);
+                               if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2)
+                                       gv->currGain += ee->ee_cckOfdmGainDelta;
+                               else
+                                       gv->currGain += PHY_PROBE_CCK_CORRECTION;
+                       }
+                       if (IS_RADX112_REV2(ah)) {
+                               ar5212GetGainFCorrection(ah);
+                               if (gv->currGain >= gv->gainFCorrection)
+                                       gv->currGain -= gv->gainFCorrection;
+                               else
+                                       gv->currGain = 0;
+                       }
+                       /* inactive by default */
+                       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+
+                       if (!ar5212InvalidGainReadback(ah, gv) &&
+                           ar5212IsGainAdjustNeeded(ah, gv) &&
+                           ar5212AdjustGain(ah, gv) > 0) {
+                               /*
+                                * Change needed. Copy ladder info
+                                * into eeprom info.
+                                */
+                               ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE;
+                               /* for ap51 */
+                               ahp->ah_cwCalRequire = AH_TRUE;
+                               /* Request IQ recalibration for temperature chang */
+                               ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
+                       }
+               }
+       }
+       return ahp->ah_rfgainState;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212_xmit.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,918 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212_xmit.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212desc.h"
+#include "ar5212/ar5212phy.h"
+#ifdef AH_SUPPORT_5311
+#include "ar5212/ar5311reg.h"
+#endif
+
+#ifdef AH_NEED_DESC_SWAP
+static void ar5212SwapTxDesc(struct ath_desc *ds);
+#endif
+
+/*
+ * Update Tx FIFO trigger level.
+ *
+ * Set bIncTrigLevel to TRUE to increase the trigger level.
+ * Set bIncTrigLevel to FALSE to decrease the trigger level.
+ *
+ * Returns TRUE if the trigger level was updated
+ */
+HAL_BOOL
+ar5212UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t txcfg, curLevel, newLevel;
+       HAL_INT omask;
+
+       /*
+        * Disable interrupts while futzing with the fifo level.
+        */
+       omask = ar5212SetInterrupts(ah, ahp->ah_maskReg &~ HAL_INT_GLOBAL);
+
+       txcfg = OS_REG_READ(ah, AR_TXCFG);
+       curLevel = MS(txcfg, AR_FTRIG);
+       newLevel = curLevel;
+       if (bIncTrigLevel) {            /* increase the trigger level */
+               if (curLevel < MAX_TX_FIFO_THRESHOLD)
+                       newLevel++;
+       } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
+               newLevel--;
+       if (newLevel != curLevel)
+               /* Update the trigger level */
+               OS_REG_WRITE(ah, AR_TXCFG,
+                       (txcfg &~ AR_FTRIG) | SM(newLevel, AR_FTRIG));
+
+       /* re-enable chip interrupts */
+       ar5212SetInterrupts(ah, omask);
+
+       return (newLevel != curLevel);
+}
+
+/*
+ * Set the properties of the tx queue with the parameters
+ * from qInfo.
+ */
+HAL_BOOL
+ar5212SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+
+       if (q >= pCap->halTotalQueues) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo);
+}
+
+/*
+ * Return the properties for the specified tx queue.
+ */
+HAL_BOOL
+ar5212GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+
+
+       if (q >= pCap->halTotalQueues) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]);
+}
+
+/*
+ * Allocate and initialize a tx DCU/QCU combination.
+ */
+int
+ar5212SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
+       const HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_TX_QUEUE_INFO *qi;
+       HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+       int q, defqflags;
+
+       /* by default enable OK+ERR+DESC+URN interrupts */
+       defqflags = HAL_TXQ_TXOKINT_ENABLE
+                 | HAL_TXQ_TXERRINT_ENABLE
+                 | HAL_TXQ_TXDESCINT_ENABLE
+                 | HAL_TXQ_TXURNINT_ENABLE;
+       /* XXX move queue assignment to driver */
+       switch (type) {
+       case HAL_TX_QUEUE_BEACON:
+               q = pCap->halTotalQueues-1;     /* highest priority */
+               defqflags |= HAL_TXQ_DBA_GATED
+                      | HAL_TXQ_CBR_DIS_QEMPTY
+                      | HAL_TXQ_ARB_LOCKOUT_GLOBAL
+                      | HAL_TXQ_BACKOFF_DISABLE;
+               break;
+       case HAL_TX_QUEUE_CAB:
+               q = pCap->halTotalQueues-2;     /* next highest priority */
+               defqflags |= HAL_TXQ_DBA_GATED
+                      | HAL_TXQ_CBR_DIS_QEMPTY
+                      | HAL_TXQ_CBR_DIS_BEMPTY
+                      | HAL_TXQ_ARB_LOCKOUT_GLOBAL
+                      | HAL_TXQ_BACKOFF_DISABLE;
+               break;
+       case HAL_TX_QUEUE_UAPSD:
+               q = pCap->halTotalQueues-3;     /* nextest highest priority */
+               if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: no available UAPSD tx queue\n", __func__);
+                       return -1;
+               }
+               break;
+       case HAL_TX_QUEUE_DATA:
+               for (q = 0; q < pCap->halTotalQueues; q++)
+                       if (ahp->ah_txq[q].tqi_type == HAL_TX_QUEUE_INACTIVE)
+                               break;
+               if (q == pCap->halTotalQueues) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: no available tx queue\n", __func__);
+                       return -1;
+               }
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: bad tx queue type %u\n", __func__, type);
+               return -1;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
+
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n",
+                   __func__, q);
+               return -1;
+       }
+       OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO));
+       qi->tqi_type = type;
+       if (qInfo == AH_NULL) {
+               qi->tqi_qflags = defqflags;
+               qi->tqi_aifs = INIT_AIFS;
+               qi->tqi_cwmin = HAL_TXQ_USEDEFAULT;     /* NB: do at reset */
+               qi->tqi_cwmax = INIT_CWMAX;
+               qi->tqi_shretry = INIT_SH_RETRY;
+               qi->tqi_lgretry = INIT_LG_RETRY;
+               qi->tqi_physCompBuf = 0;
+       } else {
+               qi->tqi_physCompBuf = qInfo->tqi_compBuf;
+               (void) ar5212SetTxQueueProps(ah, q, qInfo);
+       }
+       /* NB: must be followed by ar5212ResetTxQueue */
+       return q;
+}
+
+/*
+ * Update the h/w interrupt registers to reflect a tx q's configuration.
+ */
+static void
+setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
+           "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__,
+           ahp->ah_txOkInterruptMask, ahp->ah_txErrInterruptMask,
+           ahp->ah_txDescInterruptMask, ahp->ah_txEolInterruptMask,
+           ahp->ah_txUrnInterruptMask);
+
+       OS_REG_WRITE(ah, AR_IMR_S0,
+                 SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
+               | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC)
+       );
+       OS_REG_WRITE(ah, AR_IMR_S1,
+                 SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
+               | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL)
+       );
+       OS_REG_RMW_FIELD(ah, AR_IMR_S2,
+               AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
+}
+
+/*
+ * Free a tx DCU/QCU combination.
+ */
+HAL_BOOL
+ar5212ReleaseTxQueue(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+       HAL_TX_QUEUE_INFO *qi;
+
+       if (q >= pCap->halTotalQueues) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q);
+
+       qi->tqi_type = HAL_TX_QUEUE_INACTIVE;
+       ahp->ah_txOkInterruptMask &= ~(1 << q);
+       ahp->ah_txErrInterruptMask &= ~(1 << q);
+       ahp->ah_txDescInterruptMask &= ~(1 << q);
+       ahp->ah_txEolInterruptMask &= ~(1 << q);
+       ahp->ah_txUrnInterruptMask &= ~(1 << q);
+       setTxQInterrupts(ah, qi);
+
+       return AH_TRUE;
+}
+
+/*
+ * Set the retry, aifs, cwmin/max, readyTime regs for specified queue
+ * Assumes:
+ *  phwChannel has been set to point to the current channel
+ */
+HAL_BOOL
+ar5212ResetTxQueue(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       HAL_TX_QUEUE_INFO *qi;
+       uint32_t cwMin, chanCwMin, value, qmisc, dmisc;
+
+       if (q >= pCap->halTotalQueues) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
+                   __func__, q);
+               return AH_TRUE;         /* XXX??? */
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: reset queue %u\n", __func__, q);
+
+       if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) {
+               /*
+                * Select cwmin according to channel type.
+                * NB: chan can be NULL during attach
+                */
+               if (chan && IS_CHAN_B(chan))
+                       chanCwMin = INIT_CWMIN_11B;
+               else
+                       chanCwMin = INIT_CWMIN;
+               /* make sure that the CWmin is of the form (2^n - 1) */
+               for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1)
+                       ;
+       } else
+               cwMin = qi->tqi_cwmin;
+
+       /* set cwMin/Max and AIFS values */
+       OS_REG_WRITE(ah, AR_DLCL_IFS(q),
+                 SM(cwMin, AR_D_LCL_IFS_CWMIN)
+               | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
+               | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+
+       /* Set retry limit values */
+       OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q),
+                  SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
+                | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
+                | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG)
+                | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)
+       );
+
+       /* NB: always enable early termination on the QCU */
+       qmisc = AR_Q_MISC_DCU_EARLY_TERM_REQ
+             | SM(AR_Q_MISC_FSP_ASAP, AR_Q_MISC_FSP);
+
+       /* NB: always enable DCU to wait for next fragment from QCU */
+       dmisc = AR_D_MISC_FRAG_WAIT_EN;
+
+#ifdef AH_SUPPORT_5311
+       if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
+               /* Configure DCU to use the global sequence count */
+               dmisc |= AR5311_D_MISC_SEQ_NUM_CONTROL;
+       }
+#endif
+       /* multiqueue support */
+       if (qi->tqi_cbrPeriod) {
+               OS_REG_WRITE(ah, AR_QCBRCFG(q),
+                         SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL)
+                       | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH));
+               qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_CBR;
+               if (qi->tqi_cbrOverflowLimit)
+                       qmisc |= AR_Q_MISC_CBR_EXP_CNTR_LIMIT;
+       }
+       if (qi->tqi_readyTime) {
+               OS_REG_WRITE(ah, AR_QRDYTIMECFG(q),
+                         SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT)
+                       | AR_Q_RDYTIMECFG_ENA);
+       }
+
+       OS_REG_WRITE(ah, AR_DCHNTIME(q),
+                 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR)
+               | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
+
+       if (qi->tqi_readyTime &&
+           (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE))
+               qmisc |= AR_Q_MISC_RDYTIME_EXP_POLICY;
+       if (qi->tqi_qflags & HAL_TXQ_DBA_GATED)
+               qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_DBA_GATED;
+       if (MS(qmisc, AR_Q_MISC_FSP) != AR_Q_MISC_FSP_ASAP) {
+               /*
+                * These are meangingful only when not scheduled asap.
+                */
+               if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_BEMPTY)
+                       qmisc |= AR_Q_MISC_CBR_INCR_DIS0;
+               else
+                       qmisc &= ~AR_Q_MISC_CBR_INCR_DIS0;
+               if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_QEMPTY)
+                       qmisc |= AR_Q_MISC_CBR_INCR_DIS1;
+               else
+                       qmisc &= ~AR_Q_MISC_CBR_INCR_DIS1;
+       }
+
+       if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE)
+               dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS;
+       if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE)
+               dmisc |= AR_D_MISC_FRAG_BKOFF_EN;
+       if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_GLOBAL)
+               dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+                           AR_D_MISC_ARB_LOCKOUT_CNTRL);
+       else if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_INTRA)
+               dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR,
+                           AR_D_MISC_ARB_LOCKOUT_CNTRL);
+       if (qi->tqi_qflags & HAL_TXQ_IGNORE_VIRTCOL)
+               dmisc |= SM(AR_D_MISC_VIR_COL_HANDLING_IGNORE,
+                           AR_D_MISC_VIR_COL_HANDLING);
+       if (qi->tqi_qflags & HAL_TXQ_SEQNUM_INC_DIS)
+               dmisc |= AR_D_MISC_SEQ_NUM_INCR_DIS;
+
+       /*
+        * Fillin type-dependent bits.  Most of this can be
+        * removed by specifying the queue parameters in the
+        * driver; it's here for backwards compatibility.
+        */
+       switch (qi->tqi_type) {
+       case HAL_TX_QUEUE_BEACON:               /* beacon frames */
+               qmisc |= AR_Q_MISC_FSP_DBA_GATED
+                     |  AR_Q_MISC_BEACON_USE
+                     |  AR_Q_MISC_CBR_INCR_DIS1;
+
+               dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+                           AR_D_MISC_ARB_LOCKOUT_CNTRL)
+                     |  AR_D_MISC_BEACON_USE
+                     |  AR_D_MISC_POST_FR_BKOFF_DIS;
+               break;
+       case HAL_TX_QUEUE_CAB:                  /* CAB  frames */
+               /*
+                * No longer Enable AR_Q_MISC_RDYTIME_EXP_POLICY,
+                * There is an issue with the CAB Queue
+                * not properly refreshing the Tx descriptor if
+                * the TXE clear setting is used.
+                */
+               qmisc |= AR_Q_MISC_FSP_DBA_GATED
+                     |  AR_Q_MISC_CBR_INCR_DIS1
+                     |  AR_Q_MISC_CBR_INCR_DIS0;
+
+               if (!qi->tqi_readyTime) {
+                       /*
+                        * NB: don't set default ready time if driver
+                        * has explicitly specified something.  This is
+                        * here solely for backwards compatibility.
+                        */
+                       value = (ahp->ah_beaconInterval
+                               - (ath_hal_sw_beacon_response_time -
+                                       ath_hal_dma_beacon_response_time)
+                               - ath_hal_additional_swba_backoff) * 1024;
+                       OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_ENA);
+               }
+               dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+                           AR_D_MISC_ARB_LOCKOUT_CNTRL);
+               break;
+       default:                        /* NB: silence compiler */
+               break;
+       }
+
+       OS_REG_WRITE(ah, AR_QMISC(q), qmisc);
+       OS_REG_WRITE(ah, AR_DMISC(q), dmisc);
+
+       /* Setup compression scratchpad buffer */
+       /*
+        * XXX: calling this asynchronously to queue operation can
+        *      cause unexpected behavior!!!
+        */
+       if (qi->tqi_physCompBuf) {
+               HALASSERT(qi->tqi_type == HAL_TX_QUEUE_DATA ||
+                         qi->tqi_type == HAL_TX_QUEUE_UAPSD);
+               OS_REG_WRITE(ah, AR_Q_CBBS, (80 + 2*q));
+               OS_REG_WRITE(ah, AR_Q_CBBA, qi->tqi_physCompBuf);
+               OS_REG_WRITE(ah, AR_Q_CBC,  HAL_COMP_BUF_MAX_SIZE/1024);
+               OS_REG_WRITE(ah, AR_Q0_MISC + 4*q,
+                            OS_REG_READ(ah, AR_Q0_MISC + 4*q)
+                            | AR_Q_MISC_QCU_COMP_EN);
+       }
+
+       /*
+        * Always update the secondary interrupt mask registers - this
+        * could be a new queue getting enabled in a running system or
+        * hw getting re-initialized during a reset!
+        *
+        * Since we don't differentiate between tx interrupts corresponding
+        * to individual queues - secondary tx mask regs are always unmasked;
+        * tx interrupts are enabled/disabled for all queues collectively
+        * using the primary mask reg
+        */
+       if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE)
+               ahp->ah_txOkInterruptMask |= 1 << q;
+       else
+               ahp->ah_txOkInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE)
+               ahp->ah_txErrInterruptMask |= 1 << q;
+       else
+               ahp->ah_txErrInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE)
+               ahp->ah_txDescInterruptMask |= 1 << q;
+       else
+               ahp->ah_txDescInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE)
+               ahp->ah_txEolInterruptMask |= 1 << q;
+       else
+               ahp->ah_txEolInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE)
+               ahp->ah_txUrnInterruptMask |= 1 << q;
+       else
+               ahp->ah_txUrnInterruptMask &= ~(1 << q);
+       setTxQInterrupts(ah, qi);
+
+       return AH_TRUE;
+}
+
+/*
+ * Get the TXDP for the specified queue
+ */
+uint32_t
+ar5212GetTxDP(struct ath_hal *ah, u_int q)
+{
+       HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
+       return OS_REG_READ(ah, AR_QTXDP(q));
+}
+
+/*
+ * Set the TxDP for the specified queue
+ */
+HAL_BOOL
+ar5212SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp)
+{
+       HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
+       HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       /*
+        * Make sure that TXE is deasserted before setting the TXDP.  If TXE
+        * is still asserted, setting TXDP will have no effect.
+        */
+       HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0);
+
+       OS_REG_WRITE(ah, AR_QTXDP(q), txdp);
+
+       return AH_TRUE;
+}
+
+/*
+ * Set Transmit Enable bits for the specified queue
+ */
+HAL_BOOL
+ar5212StartTxDma(struct ath_hal *ah, u_int q)
+{
+       HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
+
+       HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
+
+       /* Check to be sure we're not enabling a q that has its TXD bit set. */
+       HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1 << q)) == 0);
+
+       OS_REG_WRITE(ah, AR_Q_TXE, 1 << q);
+       return AH_TRUE;
+}
+
+/*
+ * Return the number of pending frames or 0 if the specified
+ * queue is stopped.
+ */
+uint32_t
+ar5212NumTxPending(struct ath_hal *ah, u_int q)
+{
+       uint32_t npend;
+
+       HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
+       HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       npend = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
+       if (npend == 0) {
+               /*
+                * Pending frame count (PFC) can momentarily go to zero
+                * while TXE remains asserted.  In other words a PFC of
+                * zero is not sufficient to say that the queue has stopped.
+                */
+               if (OS_REG_READ(ah, AR_Q_TXE) & (1 << q))
+                       npend = 1;              /* arbitrarily return 1 */
+       }
+       return npend;
+}
+
+/*
+ * Stop transmit on the specified queue
+ */
+HAL_BOOL
+ar5212StopTxDma(struct ath_hal *ah, u_int q)
+{
+       u_int i;
+       u_int wait;
+
+       HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
+
+       HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       OS_REG_WRITE(ah, AR_Q_TXD, 1 << q);
+       for (i = 1000; i != 0; i--) {
+               if (ar5212NumTxPending(ah, q) == 0)
+                       break;
+               OS_DELAY(100);        /* XXX get actual value */
+       }
+#ifdef AH_DEBUG
+       if (i == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: queue %u DMA did not stop in 100 msec\n", __func__, q);
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__,
+                   OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE),
+                   OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q)));
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n",
+                   __func__, OS_REG_READ(ah, AR_QMISC(q)),
+                   OS_REG_READ(ah, AR_QRDYTIMECFG(q)),
+                   OS_REG_READ(ah, AR_Q_RDYTIMESHDN));
+       }
+#endif /* AH_DEBUG */
+
+       /* 2413+ and up can kill packets at the PCU level */
+       if (ar5212NumTxPending(ah, q) &&
+           (IS_2413(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah))) {
+               uint32_t tsfLow, j;
+
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
+                   "%s: Num of pending TX Frames %d on Q %d\n",
+                   __func__, ar5212NumTxPending(ah, q), q);
+
+               /* Kill last PCU Tx Frame */
+               /* TODO - save off and restore current values of Q1/Q2? */
+               for (j = 0; j < 2; j++) {
+                       tsfLow = OS_REG_READ(ah, AR_TSF_L32);
+                       OS_REG_WRITE(ah, AR_QUIET2, SM(100, AR_QUIET2_QUIET_PER) |
+                                    SM(10, AR_QUIET2_QUIET_DUR));
+                       OS_REG_WRITE(ah, AR_QUIET1, AR_QUIET1_QUIET_ENABLE |
+                                    SM(tsfLow >> 10, AR_QUIET1_NEXT_QUIET));
+                       if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) {
+                               break;
+                       }
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: TSF moved while trying to set quiet time "
+                           "TSF: 0x%08x\n", __func__, tsfLow);
+                       HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */
+               }
+
+               OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);
+
+               /* Allow the quiet mechanism to do its work */
+               OS_DELAY(200);
+               OS_REG_CLR_BIT(ah, AR_QUIET1, AR_QUIET1_QUIET_ENABLE);
+
+               /* Give at least 1 millisec more to wait */
+               wait = 100;
+
+               /* Verify all transmit is dead */
+               while (ar5212NumTxPending(ah, q)) {
+                       if ((--wait) == 0) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "%s: Failed to stop Tx DMA in %d msec after killing last frame\n",
+                                   __func__, wait);
+                               break;
+                       }
+                       OS_DELAY(10);
+               }
+
+               OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);
+       }
+
+       OS_REG_WRITE(ah, AR_Q_TXD, 0);
+       return (i != 0);
+}
+
+/*
+ * Descriptor Access Functions
+ */
+
+#define        VALID_PKT_TYPES \
+       ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\
+        (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\
+        (1<<HAL_PKT_TYPE_BEACON))
+#define        isValidPktType(_t)      ((1<<(_t)) & VALID_PKT_TYPES)
+#define        VALID_TX_RATES \
+       ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\
+        (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\
+        (1<<0x1d)|(1<<0x18)|(1<<0x1c))
+#define        isValidTxRate(_r)       ((1<<(_r)) & VALID_TX_RATES)
+
+HAL_BOOL
+ar5212SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int pktLen,
+       u_int hdrLen,
+       HAL_PKT_TYPE type,
+       u_int txPower,
+       u_int txRate0, u_int txTries0,
+       u_int keyIx,
+       u_int antMode,
+       u_int flags,
+       u_int rtsctsRate,
+       u_int rtsctsDuration,
+       u_int compicvLen,
+       u_int compivLen,
+       u_int comp)
+{
+#define        RTSCTS  (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)
+       struct ar5212_desc *ads = AR5212DESC(ds);
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       (void) hdrLen;
+
+       HALASSERT(txTries0 != 0);
+       HALASSERT(isValidPktType(type));
+       HALASSERT(isValidTxRate(txRate0));
+       HALASSERT((flags & RTSCTS) != RTSCTS);
+       /* XXX validate antMode */
+
+        txPower = (txPower + ahp->ah_txPowerIndexOffset );
+        if(txPower > 63)  txPower=63;
+
+       ads->ds_ctl0 = (pktLen & AR_FrameLen)
+                    | (txPower << AR_XmitPower_S)
+                    | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
+                    | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0)
+                    | SM(antMode, AR_AntModeXmit)
+                    | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0)
+                    ;
+       ads->ds_ctl1 = (type << AR_FrmType_S)
+                    | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0)
+                     | (comp << AR_CompProc_S)
+                     | (compicvLen << AR_CompICVLen_S)
+                     | (compivLen << AR_CompIVLen_S)
+                     ;
+       ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0)
+                    | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEna : 0)
+                    ;
+       ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S)
+                    ;
+       if (keyIx != HAL_TXKEYIX_INVALID) {
+               /* XXX validate key index */
+               ads->ds_ctl1 |= SM(keyIx, AR_DestIdx);
+               ads->ds_ctl0 |= AR_DestIdxValid;
+       }
+       if (flags & RTSCTS) {
+               if (!isValidTxRate(rtsctsRate)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid rts/cts rate 0x%x\n",
+                           __func__, rtsctsRate);
+                       return AH_FALSE;
+               }
+               /* XXX validate rtsctsDuration */
+               ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0)
+                            | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0)
+                            ;
+               ads->ds_ctl2 |= SM(rtsctsDuration, AR_RTSCTSDuration);
+               ads->ds_ctl3 |= (rtsctsRate << AR_RTSCTSRate_S);
+       }
+       return AH_TRUE;
+#undef RTSCTS
+}
+
+HAL_BOOL
+ar5212SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int txRate1, u_int txTries1,
+       u_int txRate2, u_int txTries2,
+       u_int txRate3, u_int txTries3)
+{
+       struct ar5212_desc *ads = AR5212DESC(ds);
+
+       if (txTries1) {
+               HALASSERT(isValidTxRate(txRate1));
+               ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1)
+                            |  AR_DurUpdateEna
+                            ;
+               ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S);
+       }
+       if (txTries2) {
+               HALASSERT(isValidTxRate(txRate2));
+               ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2)
+                            |  AR_DurUpdateEna
+                            ;
+               ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S);
+       }
+       if (txTries3) {
+               HALASSERT(isValidTxRate(txRate3));
+               ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3)
+                            |  AR_DurUpdateEna
+                            ;
+               ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S);
+       }
+       return AH_TRUE;
+}
+
+void
+ar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+       struct ar5212_desc *ads = AR5212DESC(ds);
+
+#ifdef AH_NEED_DESC_SWAP
+       ads->ds_ctl0 |= __bswap32(AR_TxInterReq);
+#else
+       ads->ds_ctl0 |= AR_TxInterReq;
+#endif
+}
+
+HAL_BOOL
+ar5212FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+       const struct ath_desc *ds0)
+{
+       struct ar5212_desc *ads = AR5212DESC(ds);
+
+       HALASSERT((segLen &~ AR_BufLen) == 0);
+
+       if (firstSeg) {
+               /*
+                * First descriptor, don't clobber xmit control data
+                * setup by ar5212SetupTxDesc.
+                */
+               ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More);
+       } else if (lastSeg) {           /* !firstSeg && lastSeg */
+               /*
+                * Last descriptor in a multi-descriptor frame,
+                * copy the multi-rate transmit parameters from
+                * the first frame for processing on completion.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 = segLen;
+#ifdef AH_NEED_DESC_SWAP
+               ads->ds_ctl2 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl2);
+               ads->ds_ctl3 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl3);
+#else
+               ads->ds_ctl2 = AR5212DESC_CONST(ds0)->ds_ctl2;
+               ads->ds_ctl3 = AR5212DESC_CONST(ds0)->ds_ctl3;
+#endif
+       } else {                        /* !firstSeg && !lastSeg */
+               /*
+                * Intermediate descriptor in a multi-descriptor frame.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 = segLen | AR_More;
+               ads->ds_ctl2 = 0;
+               ads->ds_ctl3 = 0;
+       }
+       ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+       return AH_TRUE;
+}
+
+#ifdef AH_NEED_DESC_SWAP
+/* Swap transmit descriptor */
+static __inline void
+ar5212SwapTxDesc(struct ath_desc *ds)
+{
+       ds->ds_data = __bswap32(ds->ds_data);
+        ds->ds_ctl0 = __bswap32(ds->ds_ctl0);
+        ds->ds_ctl1 = __bswap32(ds->ds_ctl1);
+        ds->ds_hw[0] = __bswap32(ds->ds_hw[0]);
+        ds->ds_hw[1] = __bswap32(ds->ds_hw[1]);
+        ds->ds_hw[2] = __bswap32(ds->ds_hw[2]);
+        ds->ds_hw[3] = __bswap32(ds->ds_hw[3]);
+}
+#endif
+
+/*
+ * Processing of HW TX descriptor.
+ */
+HAL_STATUS
+ar5212ProcTxDesc(struct ath_hal *ah,
+       struct ath_desc *ds, struct ath_tx_status *ts)
+{
+       struct ar5212_desc *ads = AR5212DESC(ds);
+
+#ifdef AH_NEED_DESC_SWAP
+       if ((ads->ds_txstatus1 & __bswap32(AR_Done)) == 0)
+                return HAL_EINPROGRESS;
+
+       ar5212SwapTxDesc(ds);
+#else
+       if ((ads->ds_txstatus1 & AR_Done) == 0)
+               return HAL_EINPROGRESS;
+#endif
+
+       /* Update software copies of the HW status */
+       ts->ts_seqnum = MS(ads->ds_txstatus1, AR_SeqNum);
+       ts->ts_tstamp = MS(ads->ds_txstatus0, AR_SendTimestamp);
+       ts->ts_status = 0;
+       if ((ads->ds_txstatus0 & AR_FrmXmitOK) == 0) {
+               if (ads->ds_txstatus0 & AR_ExcessiveRetries)
+                       ts->ts_status |= HAL_TXERR_XRETRY;
+               if (ads->ds_txstatus0 & AR_Filtered)
+                       ts->ts_status |= HAL_TXERR_FILT;
+               if (ads->ds_txstatus0 & AR_FIFOUnderrun)
+                       ts->ts_status |= HAL_TXERR_FIFO;
+       }
+       /*
+        * Extract the transmit rate used and mark the rate as
+        * ``alternate'' if it wasn't the series 0 rate.
+        */
+       ts->ts_finaltsi = MS(ads->ds_txstatus1, AR_FinalTSIndex);
+       switch (ts->ts_finaltsi) {
+       case 0:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0);
+               break;
+       case 1:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       case 2:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       case 3:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       }
+       ts->ts_rssi = MS(ads->ds_txstatus1, AR_AckSigStrength);
+       ts->ts_shortretry = MS(ads->ds_txstatus0, AR_RTSFailCnt);
+       ts->ts_longretry = MS(ads->ds_txstatus0, AR_DataFailCnt);
+       /*
+        * The retry count has the number of un-acked tries for the
+        * final series used.  When doing multi-rate retry we must
+        * fixup the retry count by adding in the try counts for
+        * each series that was fully-processed.  Beware that this
+        * takes values from the try counts in the final descriptor.
+        * These are not required by the hardware.  We assume they
+        * are placed there by the driver as otherwise we have no
+        * access and the driver can't do the calculation because it
+        * doesn't know the descriptor format.
+        */
+       switch (ts->ts_finaltsi) {
+       case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2);
+       case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1);
+       case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0);
+       }
+       ts->ts_virtcol = MS(ads->ds_txstatus0, AR_VirtCollCnt);
+       ts->ts_antenna = (ads->ds_txstatus1 & AR_XmitAtenna ? 2 : 1);
+
+       return HAL_OK;
+}
+
+/*
+ * Determine which tx queues need interrupt servicing.
+ */
+void
+ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       *txqs &= ahp->ah_intrTxqs;
+       ahp->ah_intrTxqs &= ~(*txqs);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212desc.h       2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212desc.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _ATH_AR5212_DESC_H_
+#define _ATH_AR5212_DESC_H_
+
+/*
+ * Hardware-specific descriptor structures.
+ */
+#include "ah_desc.h"
+
+/*
+ * AR5212-specific tx/rx descriptor definition.
+ */
+struct ar5212_desc {
+       uint32_t        ds_link;        /* link pointer */
+       uint32_t        ds_data;        /* data buffer pointer */
+       uint32_t        ds_ctl0;        /* DMA control 0 */
+       uint32_t        ds_ctl1;        /* DMA control 1 */
+       union {
+               struct {                /* xmit format */
+                       uint32_t        ctl2;   /* DMA control 2 */
+                       uint32_t        ctl3;   /* DMA control 3 */
+                       uint32_t        status0;/* DMA status 0 */
+                       uint32_t        status1;/* DMA status 1 */
+               } tx;
+               struct {                /* recv format */
+                       uint32_t        status0;/* DMA status 0 */
+                       uint32_t        status1;/* DMA status 1 */
+               } rx;
+       } u;
+} __packed;
+#define        AR5212DESC(_ds) ((struct ar5212_desc *)(_ds))
+#define        AR5212DESC_CONST(_ds)   ((const struct ar5212_desc *)(_ds))
+
+#define        ds_ctl2         u.tx.ctl2
+#define        ds_ctl3         u.tx.ctl3
+#define        ds_txstatus0    u.tx.status0
+#define        ds_txstatus1    u.tx.status1
+#define        ds_rxstatus0    u.rx.status0
+#define        ds_rxstatus1    u.rx.status1
+
+/* TX ds_ctl0 */
+#define        AR_FrameLen             0x00000fff      /* frame length */
+/* bits 12-15 are reserved */
+#define        AR_XmitPower            0x003f0000      /* transmit power control */
+#define        AR_XmitPower_S          16
+#define        AR_RTSCTSEnable         0x00400000      /* RTS/CTS protocol enable */
+#define        AR_VEOL                 0x00800000      /* virtual end-of-list */
+#define        AR_ClearDestMask        0x01000000      /* Clear destination mask bit */
+#define        AR_AntModeXmit          0x1e000000      /* TX antenna seslection */
+#define        AR_AntModeXmit_S        25
+#define        AR_TxInterReq           0x20000000      /* TX interrupt request */
+#define        AR_DestIdxValid         0x40000000      /* destination index valid */
+#define        AR_CTSEnable            0x80000000      /* precede frame with CTS */
+
+/* TX ds_ctl1 */
+#define        AR_BufLen               0x00000fff      /* data buffer length */
+#define        AR_More                 0x00001000      /* more desc in this frame */
+#define        AR_DestIdx              0x000fe000      /* destination table index */
+#define        AR_DestIdx_S            13
+#define        AR_FrmType              0x00f00000      /* frame type indication */
+#define        AR_FrmType_S            20
+#define        AR_NoAck                0x01000000      /* No ACK flag */
+#define        AR_CompProc             0x06000000      /* compression processing */
+#define        AR_CompProc_S           25
+#define        AR_CompIVLen            0x18000000      /* length of frame IV */
+#define        AR_CompIVLen_S          27
+#define        AR_CompICVLen           0x60000000      /* length of frame ICV */
+#define        AR_CompICVLen_S         29
+/* bit 31 is reserved */
+
+/* TX ds_ctl2 */
+#define        AR_RTSCTSDuration       0x00007fff      /* RTS/CTS duration */
+#define        AR_RTSCTSDuration_S     0
+#define        AR_DurUpdateEna         0x00008000      /* frame duration update ctl */
+#define        AR_XmitDataTries0       0x000f0000      /* series 0 max attempts */
+#define        AR_XmitDataTries0_S     16
+#define        AR_XmitDataTries1       0x00f00000      /* series 1 max attempts */
+#define        AR_XmitDataTries1_S     20
+#define        AR_XmitDataTries2       0x0f000000      /* series 2 max attempts */
+#define        AR_XmitDataTries2_S     24
+#define        AR_XmitDataTries3       0xf0000000      /* series 3 max attempts */
+#define        AR_XmitDataTries3_S     28
+
+/* TX ds_ctl3 */
+#define        AR_XmitRate0            0x0000001f      /* series 0 tx rate */
+#define        AR_XmitRate0_S          0
+#define        AR_XmitRate1            0x000003e0      /* series 1 tx rate */
+#define        AR_XmitRate1_S          5
+#define        AR_XmitRate2            0x00007c00      /* series 2 tx rate */
+#define        AR_XmitRate2_S          10
+#define        AR_XmitRate3            0x000f8000      /* series 3 tx rate */
+#define        AR_XmitRate3_S          15
+#define        AR_RTSCTSRate           0x01f00000      /* RTS or CTS rate */
+#define        AR_RTSCTSRate_S         20
+/* bits 25-31 are reserved */
+
+/* RX ds_ctl1 */
+/*     AR_BufLen               0x00000fff         data buffer length */
+/* bit 12 is reserved */
+#define        AR_RxInterReq           0x00002000      /* RX interrupt request */
+/* bits 14-31 are reserved */
+
+/* TX ds_txstatus0 */
+#define        AR_FrmXmitOK            0x00000001      /* TX success */
+#define        AR_ExcessiveRetries     0x00000002      /* excessive retries */
+#define        AR_FIFOUnderrun         0x00000004      /* TX FIFO underrun */
+#define        AR_Filtered             0x00000008      /* TX filter indication */
+#define        AR_RTSFailCnt           0x000000f0      /* RTS failure count */
+#define        AR_RTSFailCnt_S         4
+#define        AR_DataFailCnt          0x00000f00      /* Data failure count */
+#define        AR_DataFailCnt_S        8
+#define        AR_VirtCollCnt          0x0000f000      /* virtual collision count */
+#define        AR_VirtCollCnt_S        12
+#define        AR_SendTimestamp        0xffff0000      /* TX timestamp */
+#define        AR_SendTimestamp_S      16
+
+/* RX ds_rxstatus0 */
+#define        AR_DataLen              0x00000fff      /* RX data length */
+/*     AR_More                 0x00001000         more desc in this frame */
+#define        AR_DecompCRCErr         0x00002000      /* decompression CRC error */
+/* bit 14 is reserved */
+#define        AR_RcvRate              0x000f8000      /* reception rate */
+#define        AR_RcvRate_S            15
+#define        AR_RcvSigStrength       0x0ff00000      /* receive signal strength */
+#define        AR_RcvSigStrength_S     20
+#define        AR_RcvAntenna           0xf0000000      /* receive antenaa */
+#define        AR_RcvAntenna_S         28
+
+/* TX ds_txstatus1 */
+#define        AR_Done                 0x00000001      /* descripter complete */
+#define        AR_SeqNum               0x00001ffe      /* TX sequence number */
+#define        AR_SeqNum_S             1
+#define        AR_AckSigStrength       0x001fe000      /* strength of ACK */
+#define        AR_AckSigStrength_S     13
+#define        AR_FinalTSIndex         0x00600000      /* final TX attempt series ix */
+#define        AR_FinalTSIndex_S       21
+#define        AR_CompSuccess          0x00800000      /* compression status */
+#define        AR_XmitAtenna           0x01000000      /* transmit antenna */
+/* bits 25-31 are reserved */
+
+/* RX ds_rxstatus1 */
+/*     AR_Done                 0x00000001         descripter complete */
+#define        AR_FrmRcvOK             0x00000002      /* frame reception success */
+#define        AR_CRCErr               0x00000004      /* CRC error */
+#define        AR_DecryptCRCErr        0x00000008      /* Decryption CRC fiailure */
+#define        AR_PHYErr               0x00000010      /* PHY error */
+#define        AR_MichaelErr           0x00000020      /* Michae MIC decrypt error */
+/* bits 6-7 are reserved */
+#define        AR_KeyIdxValid          0x00000100      /* decryption key index valid */
+#define        AR_KeyIdx               0x0000fe00      /* Decryption key index */
+#define        AR_KeyIdx_S             9
+#define        AR_RcvTimestamp         0x7fff0000      /* timestamp */
+#define        AR_RcvTimestamp_S       16
+#define        AR_KeyCacheMiss         0x80000000      /* key cache miss indication */
+
+/* NB: phy error code overlays key index and valid fields */
+#define        AR_PHYErrCode           0x0000ff00      /* PHY error code */
+#define        AR_PHYErrCode_S         8
+
+#endif /* _ATH_AR5212_DESC_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5212reg.h        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,995 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5212reg.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5212REG_H_
+#define _DEV_ATH_AR5212REG_H_
+
+/*
+ * Definitions for the Atheros 5212 chipset.
+ */
+
+/* DMA Control and Interrupt Registers */
+#define        AR_CR           0x0008  /* MAC control register */
+#define        AR_RXDP         0x000C  /* MAC receive queue descriptor pointer */
+#define        AR_CFG          0x0014  /* MAC configuration and status register */
+#define        AR_IER          0x0024  /* MAC Interrupt enable register */
+/* 0x28 is RTSD0 on the 5211 */
+/* 0x2c is RTSD1 on the 5211 */
+#define        AR_TXCFG        0x0030  /* MAC tx DMA size config register */
+#define        AR_RXCFG        0x0034  /* MAC rx DMA size config register */
+/* 0x38 is the jumbo descriptor address on the 5211 */
+#define        AR_MIBC         0x0040  /* MAC MIB control register */
+#define        AR_TOPS         0x0044  /* MAC timeout prescale count */
+#define        AR_RXNPTO       0x0048  /* MAC no frame received timeout */
+#define        AR_TXNPTO       0x004C  /* MAC no frame trasmitted timeout */
+#define        AR_RPGTO        0x0050  /* MAC receive frame gap timeout */
+#define        AR_RPCNT        0x0054  /* MAC receive frame count limit */
+#define        AR_MACMISC      0x0058  /* MAC miscellaneous control/status register */
+#define        AR_SPC_0        0x005c  /* MAC sleep performance (awake cycles) */
+#define        AR_SPC_1        0x0060  /* MAC sleep performance (asleep cycles) */
+/* 0x5c is for QCU/DCU clock gating control on 5311 */
+#define        AR_ISR          0x0080  /* MAC Primary interrupt status register */
+#define        AR_ISR_S0       0x0084  /* MAC Secondary interrupt status register 0 */
+#define        AR_ISR_S1       0x0088  /* MAC Secondary interrupt status register 1 */
+#define        AR_ISR_S2       0x008c  /* MAC Secondary interrupt status register 2 */
+#define        AR_ISR_S3       0x0090  /* MAC Secondary interrupt status register 3 */
+#define        AR_ISR_S4       0x0094  /* MAC Secondary interrupt status register 4 */
+#define        AR_IMR          0x00a0  /* MAC Primary interrupt mask register */
+#define        AR_IMR_S0       0x00a4  /* MAC Secondary interrupt mask register 0 */
+#define        AR_IMR_S1       0x00a8  /* MAC Secondary interrupt mask register 1 */
+#define        AR_IMR_S2       0x00ac  /* MAC Secondary interrupt mask register 2 */
+#define        AR_IMR_S3       0x00b0  /* MAC Secondary interrupt mask register 3 */
+#define        AR_IMR_S4       0x00b4  /* MAC Secondary interrupt mask register 4 */
+#define        AR_ISR_RAC      0x00c0  /* ISR read-and-clear access */
+/* Shadow copies with read-and-clear access */
+#define        AR_ISR_S0_S     0x00c4  /* ISR_S0 shadow copy */
+#define        AR_ISR_S1_S     0x00c8  /* ISR_S1 shadow copy */
+#define        AR_ISR_S2_S     0x00cc  /* ISR_S2 shadow copy */
+#define        AR_ISR_S3_S     0x00d0  /* ISR_S3 shadow copy */
+#define        AR_ISR_S4_S     0x00d4  /* ISR_S4 shadow copy */
+#define        AR_DMADBG_0     0x00e0  /* DMA debug 0 */
+#define        AR_DMADBG_1     0x00e4  /* DMA debug 1 */
+#define        AR_DMADBG_2     0x00e8  /* DMA debug 2 */
+#define        AR_DMADBG_3     0x00ec  /* DMA debug 3 */
+#define        AR_DMADBG_4     0x00f0  /* DMA debug 4 */
+#define        AR_DMADBG_5     0x00f4  /* DMA debug 5 */
+#define        AR_DMADBG_6     0x00f8  /* DMA debug 6 */
+#define        AR_DMADBG_7     0x00fc  /* DMA debug 7 */
+#define        AR_DCM_A        0x0400  /* Decompression mask address */
+#define        AR_DCM_D        0x0404  /* Decompression mask data */
+#define        AR_DCCFG        0x0420  /* Decompression configuration */
+#define        AR_CCFG         0x0600  /* Compression configuration */
+#define        AR_CCUCFG       0x0604  /* Compression catchup configuration */
+#define        AR_CPC_0        0x0610  /* Compression performance counter 0 */
+#define        AR_CPC_1        0x0614  /* Compression performance counter 1 */
+#define        AR_CPC_2        0x0618  /* Compression performance counter 2 */
+#define        AR_CPC_3        0x061c  /* Compression performance counter 3 */
+#define        AR_CPCOVF       0x0620  /* Compression performance overflow status */
+
+#define        AR_Q0_TXDP      0x0800  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q1_TXDP      0x0804  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q2_TXDP      0x0808  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q3_TXDP      0x080c  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q4_TXDP      0x0810  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q5_TXDP      0x0814  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q6_TXDP      0x0818  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q7_TXDP      0x081c  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q8_TXDP      0x0820  /* MAC Transmit Queue descriptor pointer */
+#define        AR_Q9_TXDP      0x0824  /* MAC Transmit Queue descriptor pointer */
+#define        AR_QTXDP(_i)    (AR_Q0_TXDP + ((_i)<<2))
+
+#define        AR_Q_TXE        0x0840  /* MAC Transmit Queue enable */
+#define        AR_Q_TXD        0x0880  /* MAC Transmit Queue disable */
+
+#define        AR_Q0_CBRCFG    0x08c0  /* MAC CBR configuration */
+#define        AR_Q1_CBRCFG    0x08c4  /* MAC CBR configuration */
+#define        AR_Q2_CBRCFG    0x08c8  /* MAC CBR configuration */
+#define        AR_Q3_CBRCFG    0x08cc  /* MAC CBR configuration */
+#define        AR_Q4_CBRCFG    0x08d0  /* MAC CBR configuration */
+#define        AR_Q5_CBRCFG    0x08d4  /* MAC CBR configuration */
+#define        AR_Q6_CBRCFG    0x08d8  /* MAC CBR configuration */
+#define        AR_Q7_CBRCFG    0x08dc  /* MAC CBR configuration */
+#define        AR_Q8_CBRCFG    0x08e0  /* MAC CBR configuration */
+#define        AR_Q9_CBRCFG    0x08e4  /* MAC CBR configuration */
+#define        AR_QCBRCFG(_i)  (AR_Q0_CBRCFG + ((_i)<<2))
+
+#define        AR_Q0_RDYTIMECFG        0x0900  /* MAC ReadyTime configuration */
+#define        AR_Q1_RDYTIMECFG        0x0904  /* MAC ReadyTime configuration */
+#define        AR_Q2_RDYTIMECFG        0x0908  /* MAC ReadyTime configuration */
+#define        AR_Q3_RDYTIMECFG        0x090c  /* MAC ReadyTime configuration */
+#define        AR_Q4_RDYTIMECFG        0x0910  /* MAC ReadyTime configuration */
+#define        AR_Q5_RDYTIMECFG        0x0914  /* MAC ReadyTime configuration */
+#define        AR_Q6_RDYTIMECFG        0x0918  /* MAC ReadyTime configuration */
+#define        AR_Q7_RDYTIMECFG        0x091c  /* MAC ReadyTime configuration */
+#define        AR_Q8_RDYTIMECFG        0x0920  /* MAC ReadyTime configuration */
+#define        AR_Q9_RDYTIMECFG        0x0924  /* MAC ReadyTime configuration */
+#define        AR_QRDYTIMECFG(_i)      (AR_Q0_RDYTIMECFG + ((_i)<<2))
+
+#define        AR_Q_ONESHOTARM_SC      0x0940  /* MAC OneShotArm set control */
+#define        AR_Q_ONESHOTARM_CC      0x0980  /* MAC OneShotArm clear control */
+
+#define        AR_Q0_MISC      0x09c0  /* MAC Miscellaneous QCU settings */
+#define        AR_Q1_MISC      0x09c4  /* MAC Miscellaneous QCU settings */
+#define        AR_Q2_MISC      0x09c8  /* MAC Miscellaneous QCU settings */
+#define        AR_Q3_MISC      0x09cc  /* MAC Miscellaneous QCU settings */
+#define        AR_Q4_MISC      0x09d0  /* MAC Miscellaneous QCU settings */
+#define        AR_Q5_MISC      0x09d4  /* MAC Miscellaneous QCU settings */
+#define        AR_Q6_MISC      0x09d8  /* MAC Miscellaneous QCU settings */
+#define        AR_Q7_MISC      0x09dc  /* MAC Miscellaneous QCU settings */
+#define        AR_Q8_MISC      0x09e0  /* MAC Miscellaneous QCU settings */
+#define        AR_Q9_MISC      0x09e4  /* MAC Miscellaneous QCU settings */
+#define        AR_QMISC(_i)    (AR_Q0_MISC + ((_i)<<2))
+
+#define        AR_Q0_STS       0x0a00  /* MAC Miscellaneous QCU status */
+#define        AR_Q1_STS       0x0a04  /* MAC Miscellaneous QCU status */
+#define        AR_Q2_STS       0x0a08  /* MAC Miscellaneous QCU status */
+#define        AR_Q3_STS       0x0a0c  /* MAC Miscellaneous QCU status */
+#define        AR_Q4_STS       0x0a10  /* MAC Miscellaneous QCU status */
+#define        AR_Q5_STS       0x0a14  /* MAC Miscellaneous QCU status */
+#define        AR_Q6_STS       0x0a18  /* MAC Miscellaneous QCU status */
+#define        AR_Q7_STS       0x0a1c  /* MAC Miscellaneous QCU status */
+#define        AR_Q8_STS       0x0a20  /* MAC Miscellaneous QCU status */
+#define        AR_Q9_STS       0x0a24  /* MAC Miscellaneous QCU status */
+#define        AR_QSTS(_i)     (AR_Q0_STS + ((_i)<<2))
+
+#define        AR_Q_RDYTIMESHDN        0x0a40  /* MAC ReadyTimeShutdown status */
+#define        AR_Q_CBBS       0xb00   /* Compression buffer base select */
+#define        AR_Q_CBBA       0xb04   /* Compression buffer base access */
+#define        AR_Q_CBC        0xb08   /* Compression buffer configuration */
+
+#define        AR_D0_QCUMASK   0x1000  /* MAC QCU Mask */
+#define        AR_D1_QCUMASK   0x1004  /* MAC QCU Mask */
+#define        AR_D2_QCUMASK   0x1008  /* MAC QCU Mask */
+#define        AR_D3_QCUMASK   0x100c  /* MAC QCU Mask */
+#define        AR_D4_QCUMASK   0x1010  /* MAC QCU Mask */
+#define        AR_D5_QCUMASK   0x1014  /* MAC QCU Mask */
+#define        AR_D6_QCUMASK   0x1018  /* MAC QCU Mask */
+#define        AR_D7_QCUMASK   0x101c  /* MAC QCU Mask */
+#define        AR_D8_QCUMASK   0x1020  /* MAC QCU Mask */
+#define        AR_D9_QCUMASK   0x1024  /* MAC QCU Mask */
+#define        AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2))
+
+#define        AR_D0_LCL_IFS   0x1040  /* MAC DCU-specific IFS settings */
+#define        AR_D1_LCL_IFS   0x1044  /* MAC DCU-specific IFS settings */
+#define        AR_D2_LCL_IFS   0x1048  /* MAC DCU-specific IFS settings */
+#define        AR_D3_LCL_IFS   0x104c  /* MAC DCU-specific IFS settings */
+#define        AR_D4_LCL_IFS   0x1050  /* MAC DCU-specific IFS settings */
+#define        AR_D5_LCL_IFS   0x1054  /* MAC DCU-specific IFS settings */
+#define        AR_D6_LCL_IFS   0x1058  /* MAC DCU-specific IFS settings */
+#define        AR_D7_LCL_IFS   0x105c  /* MAC DCU-specific IFS settings */
+#define        AR_D8_LCL_IFS   0x1060  /* MAC DCU-specific IFS settings */
+#define        AR_D9_LCL_IFS   0x1064  /* MAC DCU-specific IFS settings */
+#define        AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2))
+
+#define        AR_D0_RETRY_LIMIT       0x1080  /* MAC Retry limits */
+#define        AR_D1_RETRY_LIMIT       0x1084  /* MAC Retry limits */
+#define        AR_D2_RETRY_LIMIT       0x1088  /* MAC Retry limits */
+#define        AR_D3_RETRY_LIMIT       0x108c  /* MAC Retry limits */
+#define        AR_D4_RETRY_LIMIT       0x1090  /* MAC Retry limits */
+#define        AR_D5_RETRY_LIMIT       0x1094  /* MAC Retry limits */
+#define        AR_D6_RETRY_LIMIT       0x1098  /* MAC Retry limits */
+#define        AR_D7_RETRY_LIMIT       0x109c  /* MAC Retry limits */
+#define        AR_D8_RETRY_LIMIT       0x10a0  /* MAC Retry limits */
+#define        AR_D9_RETRY_LIMIT       0x10a4  /* MAC Retry limits */
+#define        AR_DRETRY_LIMIT(_i)     (AR_D0_RETRY_LIMIT + ((_i)<<2))
+
+#define        AR_D0_CHNTIME   0x10c0  /* MAC ChannelTime settings */
+#define        AR_D1_CHNTIME   0x10c4  /* MAC ChannelTime settings */
+#define        AR_D2_CHNTIME   0x10c8  /* MAC ChannelTime settings */
+#define        AR_D3_CHNTIME   0x10cc  /* MAC ChannelTime settings */
+#define        AR_D4_CHNTIME   0x10d0  /* MAC ChannelTime settings */
+#define        AR_D5_CHNTIME   0x10d4  /* MAC ChannelTime settings */
+#define        AR_D6_CHNTIME   0x10d8  /* MAC ChannelTime settings */
+#define        AR_D7_CHNTIME   0x10dc  /* MAC ChannelTime settings */
+#define        AR_D8_CHNTIME   0x10e0  /* MAC ChannelTime settings */
+#define        AR_D9_CHNTIME   0x10e4  /* MAC ChannelTime settings */
+#define        AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2))
+
+#define        AR_D0_MISC      0x1100  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D1_MISC      0x1104  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D2_MISC      0x1108  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D3_MISC      0x110c  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D4_MISC      0x1110  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D5_MISC      0x1114  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D6_MISC      0x1118  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D7_MISC      0x111c  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D8_MISC      0x1120  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_D9_MISC      0x1124  /* MAC Miscellaneous DCU-specific settings */
+#define        AR_DMISC(_i)    (AR_D0_MISC + ((_i)<<2))
+
+#define        AR_D_SEQNUM     0x1140  /* MAC Frame sequence number */
+
+/* MAC DCU-global IFS settings */
+#define        AR_D_GBL_IFS_SIFS       0x1030  /* DCU global SIFS settings */
+#define        AR_D_GBL_IFS_SLOT       0x1070  /* DC global slot interval */
+#define        AR_D_GBL_IFS_EIFS       0x10b0  /* DCU global EIFS setting */
+#define        AR_D_GBL_IFS_MISC       0x10f0  /* DCU global misc. IFS settings */
+#define        AR_D_FPCTL      0x1230          /* DCU frame prefetch settings */
+#define        AR_D_TXPSE      0x1270          /* DCU transmit pause control/status */
+#define        AR_D_TXBLK_CMD  0x1038          /* DCU transmit filter cmd (w/only) */
+#define        AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) /* DCU transmit filter data */
+#define        AR_D_TXBLK_CLR  0x143c          /* DCU clear tx filter (w/only) */
+#define        AR_D_TXBLK_SET  0x147c          /* DCU set tx filter (w/only) */
+
+#define        AR_RC           0x4000  /* Warm reset control register */
+#define        AR_SCR          0x4004  /* Sleep control register */
+#define        AR_INTPEND      0x4008  /* Interrupt Pending register */
+#define        AR_SFR          0x400C  /* Sleep force register */
+#define        AR_PCICFG       0x4010  /* PCI configuration register */
+#define        AR_GPIOCR       0x4014  /* GPIO control register */
+#define        AR_GPIODO       0x4018  /* GPIO data output access register */
+#define        AR_GPIODI       0x401C  /* GPIO data input access register */
+#define        AR_SREV         0x4020  /* Silicon Revision register */
+#define        AR_TXEPOST      0x4028  /* TXE write posting resgister */
+#define        AR_QSM          0x402C  /* QCU sleep mask */
+
+#define        AR_PCIE_PMC     0x4068  /* PCIe power mgt config and status register */
+#define AR_PCIE_SERDES 0x4080  /* PCIe Serdes register */
+#define AR_PCIE_SERDES2        0x4084  /* PCIe Serdes register */
+
+#define        AR_EEPROM_ADDR  0x6000  /* EEPROM address register (10 bit) */
+#define        AR_EEPROM_DATA  0x6004  /* EEPROM data register (16 bit) */
+#define        AR_EEPROM_CMD   0x6008  /* EEPROM command register */
+#define        AR_EEPROM_STS   0x600c  /* EEPROM status register */
+#define        AR_EEPROM_CFG   0x6010  /* EEPROM configuration register */
+
+#define        AR_STA_ID0      0x8000  /* MAC station ID0 register - low 32 bits */
+#define        AR_STA_ID1      0x8004  /* MAC station ID1 register - upper 16 bits */
+#define        AR_BSS_ID0      0x8008  /* MAC BSSID low 32 bits */
+#define        AR_BSS_ID1      0x800C  /* MAC BSSID upper 16 bits / AID */
+#define        AR_SLOT_TIME    0x8010  /* MAC Time-out after a collision */
+#define        AR_TIME_OUT     0x8014  /* MAC ACK & CTS time-out */
+#define        AR_RSSI_THR     0x8018  /* MAC RSSI warning & missed beacon threshold */
+#define        AR_USEC         0x801c  /* MAC transmit latency register */
+#define        AR_BEACON       0x8020  /* MAC beacon control value/mode bits */
+#define        AR_CFP_PERIOD   0x8024  /* MAC CFP Interval (TU/msec) */
+#define        AR_TIMER0       0x8028  /* MAC Next beacon time (TU/msec) */
+#define        AR_TIMER1       0x802c  /* MAC DMA beacon alert time (1/8 TU) */
+#define        AR_TIMER2       0x8030  /* MAC Software beacon alert (1/8 TU) */
+#define        AR_TIMER3       0x8034  /* MAC ATIM window time */
+#define        AR_CFP_DUR      0x8038  /* MAC maximum CFP duration in TU */
+#define        AR_RX_FILTER    0x803C  /* MAC receive filter register */
+#define        AR_MCAST_FIL0   0x8040  /* MAC multicast filter lower 32 bits */
+#define        AR_MCAST_FIL1   0x8044  /* MAC multicast filter upper 32 bits */
+#define        AR_DIAG_SW      0x8048  /* MAC PCU control register */
+#define        AR_TSF_L32      0x804c  /* MAC local clock lower 32 bits */
+#define        AR_TSF_U32      0x8050  /* MAC local clock upper 32 bits */
+#define        AR_TST_ADDAC    0x8054  /* ADDAC test register */
+#define        AR_DEF_ANTENNA  0x8058  /* default antenna register */
+#define        AR_QOS_MASK     0x805c  /* MAC AES mute mask: QoS field */
+#define        AR_SEQ_MASK     0x8060  /* MAC AES mute mask: seqnum field */
+#define        AR_OBSERV_2     0x8068  /* Observation bus 2 */
+#define        AR_OBSERV_1     0x806c  /* Observation bus 1 */
+
+#define        AR_LAST_TSTP    0x8080  /* MAC Time stamp of the last beacon received */
+#define        AR_NAV          0x8084  /* MAC current NAV value */
+#define        AR_RTS_OK       0x8088  /* MAC RTS exchange success counter */
+#define        AR_RTS_FAIL     0x808c  /* MAC RTS exchange failure counter */
+#define        AR_ACK_FAIL     0x8090  /* MAC ACK failure counter */
+#define        AR_FCS_FAIL     0x8094  /* FCS check failure counter */
+#define        AR_BEACON_CNT   0x8098  /* Valid beacon counter */
+
+#define        AR_SLEEP1       0x80d4  /* Enhanced sleep control 1 */
+#define        AR_SLEEP2       0x80d8  /* Enhanced sleep control 2 */
+#define        AR_SLEEP3       0x80dc  /* Enhanced sleep control 3 */
+#define        AR_BSSMSKL      0x80e0  /* BSSID mask lower 32 bits */
+#define        AR_BSSMSKU      0x80e4  /* BSSID mask upper 16 bits */
+#define        AR_TPC          0x80e8  /* Transmit power control for self gen frames */
+#define        AR_TFCNT        0x80ec  /* Profile count, transmit frames */
+#define        AR_RFCNT        0x80f0  /* Profile count, receive frames */
+#define        AR_RCCNT        0x80f4  /* Profile count, receive clear */
+#define        AR_CCCNT        0x80f8  /* Profile count, cycle counter */
+
+#define AR_QUIET1   0x80fc  /* Quiet time programming for TGh */
+#define AR_QUIET1_NEXT_QUIET_S  0   /* TSF of next quiet period (TU) */
+#define AR_QUIET1_NEXT_QUIET    0xffff
+#define AR_QUIET1_QUIET_ENABLE  0x10000 /* Enable Quiet time operation */
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE  0x20000 /* Do we ack/cts during quiet period */
+
+#define AR_QUIET2   0x8100  /* More Quiet time programming */
+#define AR_QUIET2_QUIET_PER_S   0   /* Periodicity of quiet period (TU) */
+#define AR_QUIET2_QUIET_PER 0xffff
+#define AR_QUIET2_QUIET_DUR_S   16  /* Duration of quiet period (TU) */
+#define AR_QUIET2_QUIET_DUR 0xffff0000
+
+#define        AR_TSF_PARM     0x8104  /* TSF parameters */
+#define AR_NOACK        0x8108  /* No ack policy in QoS Control Field */
+#define        AR_PHY_ERR      0x810c  /* Phy error filter */
+
+#define        AR_QOS_CONTROL  0x8118  /* Control TKIP MIC for QoS */
+#define        AR_QOS_SELECT   0x811c  /* MIC QoS select */
+#define        AR_MISC_MODE    0x8120  /* PCU Misc. mode control */
+
+/* Hainan MIB counter registers */
+#define        AR_FILTOFDM     0x8124  /* Count of filtered OFDM frames */
+#define        AR_FILTCCK      0x8128  /* Count of filtered CCK frames */
+#define        AR_PHYCNT1      0x812c  /* Phy Error 1 counter */
+#define        AR_PHYCNTMASK1  0x8130  /* Phy Error 1 counter mask */
+#define        AR_PHYCNT2      0x8134  /* Phy Error 2 counter */
+#define        AR_PHYCNTMASK2  0x8138  /* Phy Error 2 counter mask */
+#define        AR_PHY_COUNTMAX (3 << 22)       /* Max value in counter before intr */
+#define        AR_MIBCNT_INTRMASK (3<<22)      /* Mask for top two bits of counters */
+
+#define        AR_RATE_DURATION_0      0x8700          /* base of multi-rate retry */
+#define        AR_RATE_DURATION(_n)    (AR_RATE_DURATION_0 + ((_n)<<2))
+
+#define        AR_KEYTABLE_0   0x8800  /* MAC Key Cache */
+#define        AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
+
+#define        AR_CFP_MASK     0x0000ffff /* Mask for next beacon time */
+
+#define        AR_CR_RXE       0x00000004 /* Receive enable */
+#define        AR_CR_RXD       0x00000020 /* Receive disable */
+#define        AR_CR_SWI       0x00000040 /* One-shot software interrupt */
+
+#define        AR_CFG_SWTD     0x00000001 /* byteswap tx descriptor words */
+#define        AR_CFG_SWTB     0x00000002 /* byteswap tx data buffer words */
+#define        AR_CFG_SWRD     0x00000004 /* byteswap rx descriptor words */
+#define        AR_CFG_SWRB     0x00000008 /* byteswap rx data buffer words */
+#define        AR_CFG_SWRG     0x00000010 /* byteswap register access data words */
+#define        AR_CFG_AP_ADHOC_INDICATION      0x00000020 /* AP/adhoc indication (0-AP, 1-Adhoc) */
+#define        AR_CFG_PHOK     0x00000100 /* PHY OK status */
+#define        AR_CFG_EEBS     0x00000200 /* EEPROM busy */
+#define        AR_5211_CFG_CLK_GATE_DIS        0x00000400 /* Clock gating disable (Oahu only) */
+#define        AR_CFG_PCI_MASTER_REQ_Q_THRESH  0x00060000 /* Mask of PCI core master request queue full threshold */
+#define        AR_CFG_PCI_MASTER_REQ_Q_THRESH_S        17         /* Shift for PCI core master request queue full threshold */
+
+#define        AR_IER_ENABLE   0x00000001 /* Global interrupt enable */
+#define        AR_IER_DISABLE  0x00000000 /* Global interrupt disable */
+
+#define        AR_DMASIZE_4B   0x00000000 /* DMA size 4 bytes (TXCFG + RXCFG) */
+#define        AR_DMASIZE_8B   0x00000001 /* DMA size 8 bytes */
+#define        AR_DMASIZE_16B  0x00000002 /* DMA size 16 bytes */
+#define        AR_DMASIZE_32B  0x00000003 /* DMA size 32 bytes */
+#define        AR_DMASIZE_64B  0x00000004 /* DMA size 64 bytes */
+#define        AR_DMASIZE_128B 0x00000005 /* DMA size 128 bytes */
+#define        AR_DMASIZE_256B 0x00000006 /* DMA size 256 bytes */
+#define        AR_DMASIZE_512B 0x00000007 /* DMA size 512 bytes */
+
+#define        AR_FTRIG        0x000003F0 /* Mask for Frame trigger level */
+#define        AR_FTRIG_S      4          /* Shift for Frame trigger level */
+#define        AR_FTRIG_IMMED  0x00000000 /* bytes in PCU TX FIFO before air */
+#define        AR_FTRIG_64B    0x00000010 /* default */
+#define        AR_FTRIG_128B   0x00000020
+#define        AR_FTRIG_192B   0x00000030
+#define        AR_FTRIG_256B   0x00000040 /* 5 bits total */
+
+#define        AR_RXCFG_ZLFDMA 0x00000010 /* Enable DMA of zero-length frame */
+
+#define        AR_MIBC_COW     0x00000001 /* counter overflow warning */
+#define        AR_MIBC_FMC     0x00000002 /* freeze MIB counters */
+#define        AR_MIBC_CMC     0x00000004 /* clear MIB counters */
+#define        AR_MIBC_MCS     0x00000008 /* MIB counter strobe, increment all */
+
+#define        AR_TOPS_MASK    0x0000FFFF /* Mask for timeout prescale */
+
+#define        AR_RXNPTO_MASK  0x000003FF /* Mask for no frame received timeout */
+
+#define        AR_TXNPTO_MASK  0x000003FF /* Mask for no frame transmitted timeout */
+#define        AR_TXNPTO_QCU_MASK      0x000FFC00 /* Mask indicating the set of QCUs */
+                                /* for which frame completions will cause */
+                                /* a reset of the no frame xmit'd timeout */
+
+#define        AR_RPGTO_MASK   0x000003FF /* Mask for receive frame gap timeout */
+
+#define        AR_RPCNT_MASK   0x0000001F /* Mask for receive frame count limit */
+
+#define        AR_MACMISC_DMA_OBS      0x000001E0 /* Mask for DMA observation bus mux select */
+#define        AR_MACMISC_DMA_OBS_S    5          /* Shift for DMA observation bus mux select */
+#define        AR_MACMISC_MISC_OBS     0x00000E00 /* Mask for MISC observation bus mux select */
+#define        AR_MACMISC_MISC_OBS_S   9          /* Shift for MISC observation bus mux select */
+#define        AR_MACMISC_MAC_OBS_BUS_LSB      0x00007000 /* Mask for MAC observation bus mux select (lsb) */
+#define        AR_MACMISC_MAC_OBS_BUS_LSB_S    12         /* Shift for MAC observation bus mux select (lsb) */
+#define        AR_MACMISC_MAC_OBS_BUS_MSB      0x00038000 /* Mask for MAC observation bus mux select (msb) */
+#define        AR_MACMISC_MAC_OBS_BUS_MSB_S    15         /* Shift for MAC observation bus mux select (msb) */
+
+/*
+ * Interrupt Status Registers
+ *
+ * Only the bits in the ISR_P register and the IMR_P registers
+ * control whether the MAC's INTA# output is asserted.  The bits in
+ * the secondary interrupt status/mask registers control what bits
+ * are set in the primary interrupt status register; however the
+ * IMR_S* registers DO NOT determine whether INTA# is asserted.
+ * That is INTA# is asserted only when the logical AND of ISR_P
+ * and IMR_P is non-zero.  The secondary interrupt mask/status
+ * registers affect what bits are set in ISR_P but they do not
+ * directly affect whether INTA# is asserted.
+ */
+#define        AR_ISR_RXOK     0x00000001 /* At least one frame received sans errors */
+#define        AR_ISR_RXDESC   0x00000002 /* Receive interrupt request */
+#define        AR_ISR_RXERR    0x00000004 /* Receive error interrupt */
+#define        AR_ISR_RXNOPKT  0x00000008 /* No frame received within timeout clock */
+#define        AR_ISR_RXEOL    0x00000010 /* Received descriptor empty interrupt */
+#define        AR_ISR_RXORN    0x00000020 /* Receive FIFO overrun interrupt */
+#define        AR_ISR_TXOK     0x00000040 /* Transmit okay interrupt */
+#define        AR_ISR_TXDESC   0x00000080 /* Transmit interrupt request */
+#define        AR_ISR_TXERR    0x00000100 /* Transmit error interrupt */
+#define        AR_ISR_TXNOPKT  0x00000200 /* No frame transmitted interrupt */
+#define        AR_ISR_TXEOL    0x00000400 /* Transmit descriptor empty interrupt */
+#define        AR_ISR_TXURN    0x00000800 /* Transmit FIFO underrun interrupt */
+#define        AR_ISR_MIB      0x00001000 /* MIB interrupt - see MIBC */
+#define        AR_ISR_SWI      0x00002000 /* Software interrupt */
+#define        AR_ISR_RXPHY    0x00004000 /* PHY receive error interrupt */
+#define        AR_ISR_RXKCM    0x00008000 /* Key-cache miss interrupt */
+#define        AR_ISR_SWBA     0x00010000 /* Software beacon alert interrupt */
+#define        AR_ISR_BRSSI    0x00020000 /* Beacon threshold interrupt */
+#define        AR_ISR_BMISS    0x00040000 /* Beacon missed interrupt */
+#define        AR_ISR_HIUERR   0x00080000 /* An unexpected bus error has occurred */
+#define        AR_ISR_BNR      0x00100000 /* Beacon not ready interrupt */
+#define        AR_ISR_RXCHIRP  0x00200000 /* Phy received a 'chirp' */
+#define        AR_ISR_RXDOPPL  0x00400000 /* Phy received a 'doppler chirp' */
+#define        AR_ISR_BCNMISC  0x00800000 /* 'or' of TIM, CABEND, DTIMSYNC, BCNTO,
+                                     CABTO, DTIM bits from ISR_S2 */
+#define        AR_ISR_TIM      0x00800000 /* TIM interrupt */
+#define        AR_ISR_GPIO     0x01000000 /* GPIO Interrupt */
+#define        AR_ISR_QCBROVF  0x02000000 /* QCU CBR overflow interrupt */
+#define        AR_ISR_QCBRURN  0x04000000 /* QCU CBR underrun interrupt */
+#define        AR_ISR_QTRIG    0x08000000 /* QCU scheduling trigger interrupt */
+#define        AR_ISR_RESV0    0xF0000000 /* Reserved */
+
+#define        AR_ISR_S0_QCU_TXOK      0x000003FF /* Mask for TXOK (QCU 0-9) */
+#define AR_ISR_S0_QCU_TXOK_S   0
+#define        AR_ISR_S0_QCU_TXDESC    0x03FF0000 /* Mask for TXDESC (QCU 0-9) */
+#define AR_ISR_S0_QCU_TXDESC_S 16
+
+#define        AR_ISR_S1_QCU_TXERR     0x000003FF /* Mask for TXERR (QCU 0-9) */
+#define AR_ISR_S1_QCU_TXERR_S  0
+#define        AR_ISR_S1_QCU_TXEOL     0x03FF0000 /* Mask for TXEOL (QCU 0-9) */
+#define AR_ISR_S1_QCU_TXEOL_S  16
+
+#define        AR_ISR_S2_QCU_TXURN     0x000003FF /* Mask for TXURN (QCU 0-9) */
+#define        AR_ISR_S2_MCABT         0x00010000 /* Master cycle abort interrupt */
+#define        AR_ISR_S2_SSERR         0x00020000 /* SERR interrupt */
+#define        AR_ISR_S2_DPERR         0x00040000 /* PCI bus parity error */
+#define        AR_ISR_S2_TIM           0x01000000 /* TIM */
+#define        AR_ISR_S2_CABEND        0x02000000 /* CABEND */
+#define        AR_ISR_S2_DTIMSYNC      0x04000000 /* DTIMSYNC */
+#define        AR_ISR_S2_BCNTO         0x08000000 /* BCNTO */
+#define        AR_ISR_S2_CABTO         0x10000000 /* CABTO */
+#define        AR_ISR_S2_DTIM          0x20000000 /* DTIM */
+#define        AR_ISR_S2_RESV0         0xE0F8FC00 /* Reserved */
+
+#define        AR_ISR_S3_QCU_QCBROVF   0x000003FF /* Mask for QCBROVF (QCU 0-9) */
+#define        AR_ISR_S3_QCU_QCBRURN   0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */
+
+#define        AR_ISR_S4_QCU_QTRIG     0x000003FF /* Mask for QTRIG (QCU 0-9) */
+#define        AR_ISR_S4_RESV0         0xFFFFFC00 /* Reserved */
+
+/*
+ * Interrupt Mask Registers
+ *
+ * Only the bits in the IMR control whether the MAC's INTA#
+ * output will be asserted.  The bits in the secondary interrupt
+ * mask registers control what bits get set in the primary
+ * interrupt status register; however the IMR_S* registers
+ * DO NOT determine whether INTA# is asserted.
+ */
+#define        AR_IMR_RXOK     0x00000001 /* At least one frame received sans errors */
+#define        AR_IMR_RXDESC   0x00000002 /* Receive interrupt request */
+#define        AR_IMR_RXERR    0x00000004 /* Receive error interrupt */
+#define        AR_IMR_RXNOPKT  0x00000008 /* No frame received within timeout clock */
+#define        AR_IMR_RXEOL    0x00000010 /* Received descriptor empty interrupt */
+#define        AR_IMR_RXORN    0x00000020 /* Receive FIFO overrun interrupt */
+#define        AR_IMR_TXOK     0x00000040 /* Transmit okay interrupt */
+#define        AR_IMR_TXDESC   0x00000080 /* Transmit interrupt request */
+#define        AR_IMR_TXERR    0x00000100 /* Transmit error interrupt */
+#define        AR_IMR_TXNOPKT  0x00000200 /* No frame transmitted interrupt */
+#define        AR_IMR_TXEOL    0x00000400 /* Transmit descriptor empty interrupt */
+#define        AR_IMR_TXURN    0x00000800 /* Transmit FIFO underrun interrupt */
+#define        AR_IMR_MIB      0x00001000 /* MIB interrupt - see MIBC */
+#define        AR_IMR_SWI      0x00002000 /* Software interrupt */
+#define        AR_IMR_RXPHY    0x00004000 /* PHY receive error interrupt */
+#define        AR_IMR_RXKCM    0x00008000 /* Key-cache miss interrupt */
+#define        AR_IMR_SWBA     0x00010000 /* Software beacon alert interrupt */
+#define        AR_IMR_BRSSI    0x00020000 /* Beacon threshold interrupt */
+#define        AR_IMR_BMISS    0x00040000 /* Beacon missed interrupt */
+#define        AR_IMR_HIUERR   0x00080000 /* An unexpected bus error has occurred */
+#define        AR_IMR_BNR      0x00100000 /* BNR interrupt */
+#define        AR_IMR_RXCHIRP  0x00200000 /* RXCHIRP interrupt */
+#define        AR_IMR_BCNMISC  0x00800000 /* Venice: BCNMISC */
+#define        AR_IMR_TIM      0x00800000 /* TIM interrupt */
+#define        AR_IMR_GPIO     0x01000000 /* GPIO Interrupt */
+#define        AR_IMR_QCBROVF  0x02000000 /* QCU CBR overflow interrupt */
+#define        AR_IMR_QCBRURN  0x04000000 /* QCU CBR underrun interrupt */
+#define        AR_IMR_QTRIG    0x08000000 /* QCU scheduling trigger interrupt */
+#define        AR_IMR_RESV0    0xF0000000 /* Reserved */
+
+#define        AR_IMR_S0_QCU_TXOK      0x000003FF /* TXOK (QCU 0-9) */
+#define        AR_IMR_S0_QCU_TXOK_S    0
+#define        AR_IMR_S0_QCU_TXDESC    0x03FF0000 /* TXDESC (QCU 0-9) */
+#define        AR_IMR_S0_QCU_TXDESC_S  16
+
+#define        AR_IMR_S1_QCU_TXERR     0x000003FF /* TXERR (QCU 0-9) */
+#define        AR_IMR_S1_QCU_TXERR_S   0
+#define        AR_IMR_S1_QCU_TXEOL     0x03FF0000 /* TXEOL (QCU 0-9) */
+#define        AR_IMR_S1_QCU_TXEOL_S   16
+
+#define        AR_IMR_S2_QCU_TXURN     0x000003FF /* Mask for TXURN (QCU 0-9) */
+#define        AR_IMR_S2_QCU_TXURN_S   0
+#define        AR_IMR_S2_MCABT         0x00010000 /* Master cycle abort interrupt */
+#define        AR_IMR_S2_SSERR         0x00020000 /* SERR interrupt */
+#define        AR_IMR_S2_DPERR         0x00040000 /* PCI bus parity error */
+#define        AR_IMR_S2_TIM           0x01000000 /* TIM */
+#define        AR_IMR_S2_CABEND        0x02000000 /* CABEND */
+#define        AR_IMR_S2_DTIMSYNC      0x04000000 /* DTIMSYNC */
+#define        AR_IMR_S2_BCNTO         0x08000000 /* BCNTO */
+#define        AR_IMR_S2_CABTO         0x10000000 /* CABTO */
+#define        AR_IMR_S2_DTIM          0x20000000 /* DTIM */
+#define        AR_IMR_S2_TSFOOR        0x80000000 /* TSF OOR */
+#define        AR_IMR_S2_RESV0         0xE0F8FC00 /* Reserved */
+
+#define        AR_IMR_S3_QCU_QCBROVF   0x000003FF /* Mask for QCBROVF (QCU 0-9) */
+#define        AR_IMR_S3_QCU_QCBRURN   0x03FF0000 /* Mask for QCBRURN (QCU 0-9) */
+#define        AR_IMR_S3_QCU_QCBRURN_S 16         /* Shift for QCBRURN (QCU 0-9) */
+
+#define        AR_IMR_S4_QCU_QTRIG     0x000003FF /* Mask for QTRIG (QCU 0-9) */
+#define        AR_IMR_S4_RESV0         0xFFFFFC00 /* Reserved */
+
+/* QCU registers */
+#define        AR_NUM_QCU      10     /* Only use QCU 0-9 for forward QCU compatibility */
+#define        AR_QCU_0        0x0001
+#define        AR_QCU_1        0x0002
+#define        AR_QCU_2        0x0004
+#define        AR_QCU_3        0x0008
+#define        AR_QCU_4        0x0010
+#define        AR_QCU_5        0x0020
+#define        AR_QCU_6        0x0040
+#define        AR_QCU_7        0x0080
+#define        AR_QCU_8        0x0100
+#define        AR_QCU_9        0x0200
+
+#define        AR_Q_CBRCFG_CBR_INTERVAL        0x00FFFFFF /* Mask for CBR interval (us) */
+#define AR_Q_CBRCFG_CBR_INTERVAL_S      0   /* Shift for CBR interval */
+#define        AR_Q_CBRCFG_CBR_OVF_THRESH      0xFF000000 /* Mask for CBR overflow threshold */
+#define AR_Q_CBRCFG_CBR_OVF_THRESH_S    24  /* Shift for CBR overflow thresh */
+
+#define        AR_Q_RDYTIMECFG_INT     0x00FFFFFF /* CBR interval (us) */
+#define AR_Q_RDYTIMECFG_INT_S   0  // Shift for ReadyTime Interval (us) */
+#define        AR_Q_RDYTIMECFG_ENA     0x01000000 /* CBR enable */
+/* bits 25-31 are reserved */
+
+#define        AR_Q_MISC_FSP           0x0000000F /* Frame Scheduling Policy mask */
+#define        AR_Q_MISC_FSP_ASAP              0       /* ASAP */
+#define        AR_Q_MISC_FSP_CBR               1       /* CBR */
+#define        AR_Q_MISC_FSP_DBA_GATED         2       /* DMA Beacon Alert gated */
+#define        AR_Q_MISC_FSP_TIM_GATED         3       /* TIM gated */
+#define        AR_Q_MISC_FSP_BEACON_SENT_GATED 4       /* Beacon-sent-gated */
+#define        AR_Q_MISC_FSP_S         0
+#define        AR_Q_MISC_ONE_SHOT_EN   0x00000010 /* OneShot enable */
+#define        AR_Q_MISC_CBR_INCR_DIS1 0x00000020 /* Disable CBR expired counter incr
+                                             (empty q) */
+#define        AR_Q_MISC_CBR_INCR_DIS0 0x00000040 /* Disable CBR expired counter incr
+                                             (empty beacon q) */
+#define        AR_Q_MISC_BEACON_USE    0x00000080 /* Beacon use indication */
+#define        AR_Q_MISC_CBR_EXP_CNTR_LIMIT    0x00000100 /* CBR expired counter limit enable */
+#define        AR_Q_MISC_RDYTIME_EXP_POLICY    0x00000200 /* Enable TXE cleared on ReadyTime expired or VEOL */
+#define        AR_Q_MISC_RESET_CBR_EXP_CTR     0x00000400 /* Reset CBR expired counter */
+#define        AR_Q_MISC_DCU_EARLY_TERM_REQ    0x00000800 /* DCU frame early termination request control */
+#define        AR_Q_MISC_QCU_COMP_EN   0x00001000 /* QCU frame compression enable */
+#define        AR_Q_MISC_RESV0         0xFFFFF000 /* Reserved */
+
+#define        AR_Q_STS_PEND_FR_CNT    0x00000003 /* Mask for Pending Frame Count */
+#define        AR_Q_STS_RESV0          0x000000FC /* Reserved */
+#define        AR_Q_STS_CBR_EXP_CNT    0x0000FF00 /* Mask for CBR expired counter */
+#define        AR_Q_STS_RESV1          0xFFFF0000 /* Reserved */
+
+/* DCU registers */
+#define        AR_NUM_DCU      10     /* Only use 10 DCU's for forward QCU/DCU compatibility */
+#define        AR_DCU_0        0x0001
+#define        AR_DCU_1        0x0002
+#define        AR_DCU_2        0x0004
+#define        AR_DCU_3        0x0008
+#define        AR_DCU_4        0x0010
+#define        AR_DCU_5        0x0020
+#define        AR_DCU_6        0x0040
+#define        AR_DCU_7        0x0080
+#define        AR_DCU_8        0x0100
+#define        AR_DCU_9        0x0200
+
+#define        AR_D_QCUMASK            0x000003FF /* Mask for QCU Mask (QCU 0-9) */
+#define        AR_D_QCUMASK_RESV0      0xFFFFFC00 /* Reserved */
+
+#define        AR_D_LCL_IFS_CWMIN      0x000003FF /* Mask for CW_MIN */
+#define        AR_D_LCL_IFS_CWMIN_S    0
+#define        AR_D_LCL_IFS_CWMAX      0x000FFC00 /* Mask for CW_MAX */
+#define        AR_D_LCL_IFS_CWMAX_S    10
+#define        AR_D_LCL_IFS_AIFS       0x0FF00000 /* Mask for AIFS */
+#define        AR_D_LCL_IFS_AIFS_S     20
+/*
+ *  Note:  even though this field is 8 bits wide the
+ *  maximum supported AIFS value is 0xfc.  Setting the AIFS value
+ *  to 0xfd 0xfe, or 0xff will not work correctly and will cause
+ *  the DCU to hang.
+ */
+#define        AR_D_LCL_IFS_RESV0      0xF0000000 /* Reserved */
+
+#define        AR_D_RETRY_LIMIT_FR_SH  0x0000000F /* frame short retry limit */
+#define        AR_D_RETRY_LIMIT_FR_SH_S        0
+#define        AR_D_RETRY_LIMIT_FR_LG  0x000000F0 /* frame long retry limit */
+#define        AR_D_RETRY_LIMIT_FR_LG_S        4
+#define        AR_D_RETRY_LIMIT_STA_SH 0x00003F00 /* station short retry limit */
+#define        AR_D_RETRY_LIMIT_STA_SH_S       8
+#define        AR_D_RETRY_LIMIT_STA_LG 0x000FC000 /* station short retry limit */
+#define        AR_D_RETRY_LIMIT_STA_LG_S       14
+#define        AR_D_RETRY_LIMIT_RESV0          0xFFF00000 /* Reserved */
+
+#define        AR_D_CHNTIME_DUR                0x000FFFFF /* ChannelTime duration (us) */
+#define AR_D_CHNTIME_DUR_S              0 /* Shift for ChannelTime duration */
+#define        AR_D_CHNTIME_EN                 0x00100000 /* ChannelTime enable */
+#define        AR_D_CHNTIME_RESV0              0xFFE00000 /* Reserved */
+
+#define        AR_D_MISC_BKOFF_THRESH  0x0000003F /* Backoff threshold */
+#define        AR_D_MISC_ETS_RTS               0x00000040 /* End of transmission series
+                                                     station RTS/data failure
+                                                     count reset policy */
+#define        AR_D_MISC_ETS_CW                0x00000080 /* End of transmission series
+                                                     CW reset policy */
+#define AR_D_MISC_FRAG_WAIT_EN          0x00000100 /* Wait for next fragment */
+#define AR_D_MISC_FRAG_BKOFF_EN         0x00000200 /* Backoff during a frag burst */
+#define        AR_D_MISC_HCF_POLL_EN           0x00000800 /* HFC poll enable */
+#define        AR_D_MISC_BKOFF_PERSISTENCE     0x00001000 /* Backoff persistence factor
+                                                     setting */
+#define        AR_D_MISC_FR_PREFETCH_EN        0x00002000 /* Frame prefetch enable */
+#define        AR_D_MISC_VIR_COL_HANDLING      0x0000C000 /* Mask for Virtual collision
+                                                     handling policy */
+#define        AR_D_MISC_VIR_COL_HANDLING_S    14
+/* FOO redefined for venice CW increment policy */
+#define        AR_D_MISC_VIR_COL_HANDLING_DEFAULT      0       /* Normal */
+#define        AR_D_MISC_VIR_COL_HANDLING_IGNORE       1       /* Ignore */
+#define        AR_D_MISC_BEACON_USE            0x00010000 /* Beacon use indication */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL     0x00060000 /* DCU arbiter lockout ctl */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL_S   17         /* DCU arbiter lockout ctl */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE        0       /* No lockout */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR    1       /* Intra-frame */
+#define        AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL      2       /* Global */
+#define        AR_D_MISC_ARB_LOCKOUT_IGNORE    0x00080000 /* DCU arbiter lockout ignore control */
+#define        AR_D_MISC_SEQ_NUM_INCR_DIS      0x00100000 /* Sequence number increment disable */
+#define        AR_D_MISC_POST_FR_BKOFF_DIS     0x00200000 /* Post-frame backoff disable */
+#define        AR_D_MISC_VIRT_COLL_POLICY      0x00400000 /* Virtual coll. handling policy */
+#define        AR_D_MISC_BLOWN_IFS_POLICY      0x00800000 /* Blown IFS handling policy */
+#define        AR_D_MISC_RESV0                 0xFE000000 /* Reserved */
+
+#define        AR_D_SEQNUM_RESV0       0xFFFFF000 /* Reserved */
+
+#define        AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007 /* LFSR slice select */
+#define        AR_D_GBL_IFS_MISC_TURBO_MODE    0x00000008 /* Turbo mode indication */
+#define        AR_D_GBL_IFS_MISC_SIFS_DURATION_USEC    0x000003F0 /* SIFS duration (us) */
+#define        AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 /* microsecond duration */
+#define        AR_D_GBL_IFS_MISC_USEC_DURATION_S 10
+#define        AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY       0x00300000 /* DCU arbiter delay */
+#define        AR_D_GBL_IFS_MISC_RESV0 0xFFC00000 /* Reserved */
+
+/* DMA & PCI Registers in PCI space (usable during sleep) */
+#define        AR_RC_MAC               0x00000001 /* MAC reset */
+#define        AR_RC_BB                0x00000002 /* Baseband reset */
+#define        AR_RC_RESV0             0x00000004 /* Reserved */
+#define        AR_RC_RESV1             0x00000008 /* Reserved */
+#define        AR_RC_PCI               0x00000010 /* PCI-core reset */
+
+#define        AR_SCR_SLDUR            0x0000ffff /* sleep duration, units of 128us */
+#define        AR_SCR_SLDUR_S          0
+#define        AR_SCR_SLE              0x00030000 /* sleep enable */
+#define        AR_SCR_SLE_S            16
+#define        AR_SCR_SLE_WAKE         0       /* force wake */
+#define        AR_SCR_SLE_SLP          1       /* force sleep */
+#define        AR_SCR_SLE_NORM         2       /* sleep logic normal operation */
+#define        AR_SCR_SLDTP            0x00040000 /* sleep duration timing policy */
+#define        AR_SCR_SLDWP            0x00080000 /* sleep duration write policy */
+#define        AR_SCR_SLEPOL           0x00100000 /* sleep policy mode */
+#define        AR_SCR_MIBIE            0x00200000 /* sleep perf cntrs MIB intr ena */
+
+#define        AR_INTPEND_TRUE         0x00000001 /* interrupt pending */
+
+#define        AR_SFR_SLEEP            0x00000001 /* force sleep */
+
+#define        AR_PCICFG_SCLK_SEL      0x00000002 /* sleep clock select */
+#define        AR_PCICFG_SCLK_SEL_S    1
+#define        AR_PCICFG_CLKRUNEN      0x00000004 /* enable PCI CLKRUN function */
+#define        AR_PCICFG_EEPROM_SIZE   0x00000018 /* Mask for EEPROM size */
+#define        AR_PCICFG_EEPROM_SIZE_4         0       /* EEPROM size 4 Kbit */
+#define        AR_PCICFG_EEPROM_SIZE_8K        1       /* EEPROM size 8 Kbit */
+#define        AR_PCICFG_EEPROM_SIZE_16K       2       /* EEPROM size 16 Kbit */
+#define        AR_PCICFG_EEPROM_SIZE_FAILED    3       /* Failure */
+#define        AR_PCICFG_EEPROM_SIZE_S 3
+#define        AR_PCICFG_LEDCTL        0x00000060 /* LED control Status */
+#define        AR_PCICFG_LEDCTL_NONE   0          /* STA is not associated or trying */
+#define        AR_PCICFG_LEDCTL_PEND   1          /* STA is trying to associate */
+#define        AR_PCICFG_LEDCTL_ASSOC  2          /* STA is associated */
+#define        AR_PCICFG_LEDCTL_S      5
+#define        AR_PCICFG_PCI_BUS_SEL   0x00000380 /* PCI observation bus mux select */
+#define        AR_PCICFG_DIS_CBE_FIX   0x00000400 /* Disable fix for bad PCI CBE# generation */
+#define        AR_PCICFG_SL_INTEN      0x00000800 /* enable interrupt line assertion when asleep */
+#define        AR_PCICFG_RETRYFIXEN    0x00001000 /* Enable PCI core retry fix */
+#define        AR_PCICFG_SL_INPEN      0x00002000 /* Force asleep when an interrupt is pending */
+#define        AR_PCICFG_RESV1         0x0000C000 /* Reserved */
+#define        AR_PCICFG_SPWR_DN       0x00010000 /* mask for sleep/awake indication */
+#define        AR_PCICFG_LEDMODE       0x000E0000 /* LED mode */
+#define        AR_PCICFG_LEDMODE_PROP  0          /* Blink prop to filtered tx/rx */
+#define        AR_PCICFG_LEDMODE_RPROP 1          /* Blink prop to unfiltered tx/rx */
+#define        AR_PCICFG_LEDMODE_SPLIT 2          /* Blink power for tx/net for rx */
+#define        AR_PCICFG_LEDMODE_RAND  3          /* Blink randomly */
+/* NB: s/w led control present in Hainan 1.1 and above */
+#define        AR_PCICFG_LEDMODE_OFF   4          /* s/w control + both led's off */
+#define        AR_PCICFG_LEDMODE_POWON 5          /* s/w control + power led on */
+#define        AR_PCICFG_LEDMODE_NETON 6          /* s/w control + network led on */
+#define        AR_PCICFG_LEDMODE_S     17
+#define        AR_PCICFG_LEDBLINK      0x00700000 /* LED blink threshold select */
+#define        AR_PCICFG_LEDBLINK_S    20
+#define        AR_PCICFG_LEDSLOW       0x00800000 /* LED slowest blink rate mode */
+#define        AR_PCICFG_LEDSLOW_S     23
+#define        AR_PCICFG_SCLK_RATE_IND 0x03000000 /* Sleep clock rate */
+#define        AR_PCICFG_SCLK_RATE_IND_S 24
+#define        AR_PCICFG_RESV2         0xFC000000 /* Reserved */
+
+#define        AR_GPIOCR_CR_SHIFT      2          /* Each CR is 2 bits */
+#define        AR_GPIOCR_CR_N(_g)      (0 << (AR_GPIOCR_CR_SHIFT * (_g)))
+#define        AR_GPIOCR_CR_0(_g)      (1 << (AR_GPIOCR_CR_SHIFT * (_g)))
+#define        AR_GPIOCR_CR_1(_g)      (2 << (AR_GPIOCR_CR_SHIFT * (_g)))
+#define        AR_GPIOCR_CR_A(_g)      (3 << (AR_GPIOCR_CR_SHIFT * (_g)))
+#define        AR_GPIOCR_INT_SHIFT     12         /* Interrupt select field shifter */
+#define        AR_GPIOCR_INT(_g)       ((_g) << AR_GPIOCR_INT_SHIFT)
+#define        AR_GPIOCR_INT_MASK      0x00007000 /* Interrupt select field mask */
+#define        AR_GPIOCR_INT_ENA       0x00008000 /* Enable GPIO Interrupt */
+#define        AR_GPIOCR_INT_SELL      0x00000000 /* Generate int if pin is low */
+#define        AR_GPIOCR_INT_SELH      0x00010000 /* Generate int if pin is high */
+#define        AR_GPIOCR_INT_SEL       AR_GPIOCR_INT_SELH
+
+#define        AR_SREV_ID              0x000000FF /* Mask to read SREV info */
+#define        AR_SREV_ID_S            4          /* Mask to shift Major Rev Info */
+#define        AR_SREV_REVISION        0x0000000F /* Mask for Chip revision level */
+#define        AR_SREV_REVISION_MIN    0          /* lowest revision level */
+#define        AR_SREV_REVISION_MAX    0xF        /* highest revision level */
+#define        AR_SREV_FPGA            1
+#define        AR_SREV_D2PLUS          2
+#define        AR_SREV_D2PLUS_MS       3       /* metal spin */
+#define        AR_SREV_CRETE           4
+#define        AR_SREV_CRETE_MS        5       /* FCS metal spin */
+#define        AR_SREV_CRETE_MS23      7       /* 2.3 metal spin (6 skipped) */
+#define        AR_SREV_CRETE_23        8       /* 2.3 full tape out */
+#define        AR_SREV_GRIFFIN_LITE    8
+#define        AR_SREV_HAINAN          9
+#define        AR_SREV_CONDOR          11
+#define        AR_SREV_VERSION 0x000000F0 /* Mask for Chip version */
+#define        AR_SREV_VERSION_CRETE   0
+#define        AR_SREV_VERSION_MAUI_1  1
+#define        AR_SREV_VERSION_MAUI_2  2
+#define        AR_SREV_VERSION_SPIRIT  3
+#define        AR_SREV_VERSION_OAHU    4
+#define        AR_SREV_VERSION_VENICE  5
+#define        AR_SREV_VERSION_GRIFFIN 7
+#define        AR_SREV_VERSION_CONDOR  9
+#define        AR_SREV_VERSION_EAGLE   10
+#define        AR_SREV_VERSION_COBRA   11
+#define        AR_SREV_2413            AR_SREV_VERSION_GRIFFIN
+#define        AR_SREV_5413            AR_SREV_VERSION_EAGLE
+#define        AR_SREV_2415            AR_SREV_VERSION_COBRA
+#define        AR_SREV_5424            AR_SREV_VERSION_CONDOR
+#define        AR_SREV_2425            14      /* SWAN */
+#define        AR_SREV_2417            15      /* Nala */
+#define        AR_SREV_OAHU_ES         0       /* Engineering Sample */
+#define        AR_SREV_OAHU_PROD       2       /* Production */
+
+#define        AR_PHYREV_HAINAN        0x43
+#define        AR_ANALOG5REV_HAINAN    0x46
+
+#define        AR_RADIO_SREV_MAJOR     0xF0
+#define        AR_RADIO_SREV_MINOR     0x0F
+#define        AR_RAD5111_SREV_MAJOR   0x10    /* All current supported ar5211 5 GHz
+                                          radios are rev 0x10 */
+#define        AR_RAD5111_SREV_PROD    0x15    /* Current production level radios */
+#define        AR_RAD2111_SREV_MAJOR   0x20    /* All current supported ar5211 2 GHz
+                                          radios are rev 0x10 */
+#define        AR_RAD5112_SREV_MAJOR   0x30    /* 5112 Major Rev */
+#define AR_RAD5112_SREV_2_0     0x35    /* AR5112 Revision 2.0 */
+#define AR_RAD5112_SREV_2_1     0x36    /* AR5112 Revision 2.1 */
+#define        AR_RAD2112_SREV_MAJOR   0x40    /* 2112 Major Rev */
+#define AR_RAD2112_SREV_2_0     0x45    /* AR2112 Revision 2.0 */
+#define AR_RAD2112_SREV_2_1     0x46    /* AR2112 Revision 2.1 */
+#define AR_RAD2413_SREV_MAJOR  0x50    /* 2413 Major Rev */
+#define AR_RAD5413_SREV_MAJOR   0x60    /* 5413 Major Rev */
+#define AR_RAD2316_SREV_MAJOR  0x70    /* 2316 Major Rev */
+#define AR_RAD2317_SREV_MAJOR  0x80    /* 2317 Major Rev */
+#define AR_RAD5424_SREV_MAJOR   0xa0    /* Mostly same as 5413 Major Rev */
+
+#define        AR_PCIE_PMC_ENA_L1      0x01    /* enable PCIe core enter L1 when
+                                          d2_sleep_en is asserted */
+#define        AR_PCIE_PMC_ENA_RESET   0x08    /* enable reset on link going down */
+
+/* EEPROM Registers in the MAC */
+#define        AR_EEPROM_CMD_READ      0x00000001
+#define        AR_EEPROM_CMD_WRITE     0x00000002
+#define        AR_EEPROM_CMD_RESET     0x00000004
+
+#define        AR_EEPROM_STS_READ_ERROR        0x00000001
+#define        AR_EEPROM_STS_READ_COMPLETE     0x00000002
+#define        AR_EEPROM_STS_WRITE_ERROR       0x00000004
+#define        AR_EEPROM_STS_WRITE_COMPLETE    0x00000008
+
+#define        AR_EEPROM_CFG_SIZE      0x00000003      /* size determination override */
+#define        AR_EEPROM_CFG_SIZE_AUTO         0
+#define        AR_EEPROM_CFG_SIZE_4KBIT        1
+#define        AR_EEPROM_CFG_SIZE_8KBIT        2
+#define        AR_EEPROM_CFG_SIZE_16KBIT       3
+#define        AR_EEPROM_CFG_DIS_WWRCL 0x00000004      /* Disable wait for write completion */
+#define        AR_EEPROM_CFG_CLOCK     0x00000018      /* clock rate control */
+#define        AR_EEPROM_CFG_CLOCK_S           3       /* clock rate control */
+#define        AR_EEPROM_CFG_CLOCK_156KHZ      0
+#define        AR_EEPROM_CFG_CLOCK_312KHZ      1
+#define        AR_EEPROM_CFG_CLOCK_625KHZ      2
+#define        AR_EEPROM_CFG_RESV0     0x000000E0      /* Reserved */
+#define        AR_EEPROM_CFG_PKEY      0x00FFFF00      /* protection key */
+#define        AR_EEPROM_CFG_PKEY_S    8
+#define        AR_EEPROM_CFG_EN_L      0x01000000      /* EPRM_EN_L setting */
+
+/* MAC PCU Registers */
+
+#define        AR_STA_ID1_SADH_MASK    0x0000FFFF /* upper 16 bits of MAC addr */
+#define        AR_STA_ID1_STA_AP       0x00010000 /* Device is AP */
+#define        AR_STA_ID1_ADHOC        0x00020000 /* Device is ad-hoc */
+#define        AR_STA_ID1_PWR_SAV      0x00040000 /* Power save reporting in
+                                             self-generated frames */
+#define        AR_STA_ID1_KSRCHDIS     0x00080000 /* Key search disable */
+#define        AR_STA_ID1_PCF          0x00100000 /* Observe PCF */
+#define        AR_STA_ID1_USE_DEFANT   0x00200000 /* Use default antenna */
+#define        AR_STA_ID1_UPD_DEFANT   0x00400000 /* Update default antenna w/
+                                             TX antenna */
+#define        AR_STA_ID1_RTS_USE_DEF  0x00800000 /* Use default antenna to send RTS */
+#define        AR_STA_ID1_ACKCTS_6MB   0x01000000 /* Use 6Mb/s rate for ACK & CTS */
+#define        AR_STA_ID1_BASE_RATE_11B 0x02000000/* Use 11b base rate for ACK & CTS */
+#define        AR_STA_ID1_USE_DA_SG    0x04000000 /* Use default antenna for
+                                             self-generated frames */
+#define        AR_STA_ID1_CRPT_MIC_ENABLE      0x08000000 /* Enable Michael */
+#define        AR_STA_ID1_KSRCH_MODE   0x10000000 /* Look-up key when keyID != 0 */
+#define        AR_STA_ID1_PRE_SEQNUM   0x20000000 /* Preserve s/w sequence number */
+#define        AR_STA_ID1_CBCIV_ENDIAN 0x40000000
+#define        AR_STA_ID1_MCAST_KSRCH  0x80000000 /* Do keycache search for mcast */
+
+#define        AR_BSS_ID1_U16          0x0000FFFF /* Upper 16 bits of BSSID */
+#define        AR_BSS_ID1_AID          0xFFFF0000 /* Association ID */
+#define        AR_BSS_ID1_AID_S        16
+
+#define        AR_SLOT_TIME_MASK       0x000007FF /* Slot time mask */
+
+#define        AR_TIME_OUT_ACK         0x00003FFF /* ACK time-out */
+#define        AR_TIME_OUT_ACK_S       0
+#define        AR_TIME_OUT_CTS         0x3FFF0000 /* CTS time-out */
+#define        AR_TIME_OUT_CTS_S       16
+
+#define        AR_RSSI_THR_MASK        0x000000FF /* Beacon RSSI warning threshold */
+#define        AR_RSSI_THR_BM_THR      0x0000FF00 /* Missed beacon threshold */
+#define        AR_RSSI_THR_BM_THR_S    8
+
+#define        AR_USEC_USEC            0x0000007F /* clock cycles in 1 usec */
+#define        AR_USEC_USEC_S          0
+#define        AR_USEC_USEC32          0x00003F80 /* 32MHz clock cycles in 1 usec */
+#define        AR_USEC_USEC32_S        7
+
+#define AR5212_USEC_TX_LAT_M    0x007FC000      /* Tx latency */
+#define AR5212_USEC_TX_LAT_S    14
+#define AR5212_USEC_RX_LAT_M    0x1F800000      /* Rx latency */
+#define AR5212_USEC_RX_LAT_S    23
+
+#define        AR_BEACON_PERIOD        0x0000FFFF /* Beacon period mask in TU/msec */
+#define        AR_BEACON_PERIOD_S      0
+#define        AR_BEACON_TIM           0x007F0000 /* byte offset of TIM start */
+#define        AR_BEACON_TIM_S         16
+#define        AR_BEACON_EN            0x00800000 /* Beacon enable */
+#define        AR_BEACON_RESET_TSF     0x01000000 /* Clear TSF to 0 */
+
+#define        AR_RX_NONE              0x00000000 /* Disallow all frames */
+#define        AR_RX_UCAST             0x00000001 /* Allow unicast frames */
+#define        AR_RX_MCAST             0x00000002 /* Allow multicast frames */
+#define        AR_RX_BCAST             0x00000004 /* Allow broadcast frames */
+#define        AR_RX_CONTROL           0x00000008 /* Allow control frames */
+#define        AR_RX_BEACON            0x00000010 /* Allow beacon frames */
+#define        AR_RX_PROM              0x00000020 /* Promiscuous mode, all packets */
+#define        AR_RX_PROBE_REQ         0x00000080 /* Allow probe request frames */
+
+#define        AR_DIAG_CACHE_ACK       0x00000001 /* No ACK if no valid key found */
+#define        AR_DIAG_ACK_DIS         0x00000002 /* Disable ACK generation */
+#define        AR_DIAG_CTS_DIS         0x00000004 /* Disable CTS generation */
+#define        AR_DIAG_ENCRYPT_DIS     0x00000008 /* Disable encryption */
+#define        AR_DIAG_DECRYPT_DIS     0x00000010 /* Disable decryption */
+#define        AR_DIAG_RX_DIS          0x00000020 /* Disable receive */
+#define        AR_DIAG_CORR_FCS        0x00000080 /* Corrupt FCS */
+#define        AR_DIAG_CHAN_INFO       0x00000100 /* Dump channel info */
+#define        AR_DIAG_EN_SCRAMSD      0x00000200 /* Enable fixed scrambler seed */
+#define        AR_DIAG_SCRAM_SEED      0x0001FC00 /* Fixed scrambler seed */
+#define        AR_DIAG_SCRAM_SEED_S    10
+#define        AR_DIAG_FRAME_NV0       0x00020000 /* Accept frames of non-zero
+                                             protocol version */
+#define        AR_DIAG_OBS_PT_SEL      0x000C0000 /* Observation point select */
+#define        AR_DIAG_OBS_PT_SEL_S    18
+#define AR_DIAG_RX_CLR_HI      0x00100000 /* Force rx_clear high */
+#define AR_DIAG_IGNORE_CS      0x00200000 /* Force virtual carrier sense */
+#define AR_DIAG_CHAN_IDLE      0x00400000 /* Force channel idle high */
+#define AR_DIAG_PHEAR_ME       0x00800000 /* Uses framed and wait_wep in the pherr_enable_eifs if set to 0 */
+
+#define        AR_SLEEP1_NEXT_DTIM     0x0007ffff /* Abs. time(1/8TU) for next DTIM */
+#define        AR_SLEEP1_NEXT_DTIM_S   0
+#define        AR_SLEEP1_ASSUME_DTIM   0x00080000 /* Assume DTIM present on missent beacon */
+#define        AR_SLEEP1_ENH_SLEEP_ENA 0x00100000 /* Enable enhanced sleep logic */
+#define        AR_SLEEP1_CAB_TIMEOUT   0xff000000 /* CAB timeout(TU) */
+#define        AR_SLEEP1_CAB_TIMEOUT_S 24
+
+#define        AR_SLEEP2_NEXT_TIM      0x0007ffff /* Abs. time(1/8TU) for next DTIM */
+#define        AR_SLEEP2_NEXT_TIM_S    0
+#define        AR_SLEEP2_BEACON_TIMEOUT        0xff000000 /* Beacon timeout(TU) */
+#define        AR_SLEEP2_BEACON_TIMEOUT_S      24
+
+#define        AR_SLEEP3_TIM_PERIOD    0x0000ffff /* Tim/Beacon period (TU) */
+#define        AR_SLEEP3_TIM_PERIOD_S  0
+#define        AR_SLEEP3_DTIM_PERIOD   0xffff0000 /* DTIM period (TU) */
+#define        AR_SLEEP3_DTIM_PERIOD_S 16
+
+#define        AR_TPC_ACK              0x0000003f /* ack frames */
+#define        AR_TPC_ACK_S            0
+#define        AR_TPC_CTS              0x00003f00 /* cts frames */
+#define        AR_TPC_CTS_S            8
+#define        AR_TPC_CHIRP            0x003f0000 /* chirp frames */
+#define        AR_TPC_CHIRP_S          16
+#define AR_TPC_DOPPLER          0x0f000000 /* doppler chirp span */
+#define AR_TPC_DOPPLER_S        24
+
+#define        AR_PHY_ERR_RADAR        0x00000020      /* Radar signal */
+#define        AR_PHY_ERR_OFDM_TIMING  0x00020000      /* False detect for OFDM */
+#define        AR_PHY_ERR_CCK_TIMING   0x02000000      /* False detect for CCK */
+
+#define        AR_TSF_PARM_INCREMENT   0x000000ff
+#define        AR_TSF_PARM_INCREMENT_S 0
+
+#define AR_NOACK_2BIT_VALUE    0x0000000f
+#define AR_NOACK_2BIT_VALUE_S  0
+#define AR_NOACK_BIT_OFFSET     0x00000070
+#define AR_NOACK_BIT_OFFSET_S   4
+#define AR_NOACK_BYTE_OFFSET    0x00000180
+#define AR_NOACK_BYTE_OFFSET_S  7
+
+#define        AR_MISC_MODE_BSSID_MATCH_FORCE  0x1     /* Force BSSID match */
+#define        AR_MISC_MODE_ACKSIFS_MEMORY     0x2     /* ACKSIFS use contents of Rate */
+#define        AR_MISC_MODE_MIC_NEW_LOC_ENABLE 0x4     /* Xmit Michael Key same as Rcv */
+#define        AR_MISC_MODE_TX_ADD_TSF         0x8     /* Beacon/Probe-Rsp timestamp add (not replace) */
+
+#define        AR_KEYTABLE_KEY0(_n)    (AR_KEYTABLE(_n) + 0)   /* key bit 0-31 */
+#define        AR_KEYTABLE_KEY1(_n)    (AR_KEYTABLE(_n) + 4)   /* key bit 32-47 */
+#define        AR_KEYTABLE_KEY2(_n)    (AR_KEYTABLE(_n) + 8)   /* key bit 48-79 */
+#define        AR_KEYTABLE_KEY3(_n)    (AR_KEYTABLE(_n) + 12)  /* key bit 80-95 */
+#define        AR_KEYTABLE_KEY4(_n)    (AR_KEYTABLE(_n) + 16)  /* key bit 96-127 */
+#define        AR_KEYTABLE_TYPE(_n)    (AR_KEYTABLE(_n) + 20)  /* key type */
+#define        AR_KEYTABLE_TYPE_40     0x00000000      /* WEP 40 bit key */
+#define        AR_KEYTABLE_TYPE_104    0x00000001      /* WEP 104 bit key */
+#define        AR_KEYTABLE_TYPE_128    0x00000003      /* WEP 128 bit key */
+#define        AR_KEYTABLE_TYPE_TKIP   0x00000004      /* TKIP and Michael */
+#define        AR_KEYTABLE_TYPE_AES    0x00000005      /* AES/OCB 128 bit key */
+#define        AR_KEYTABLE_TYPE_CCM    0x00000006      /* AES/CCM 128 bit key */
+#define        AR_KEYTABLE_TYPE_CLR    0x00000007      /* no encryption */
+#define        AR_KEYTABLE_ANT         0x00000008      /* previous transmit antenna */
+#define        AR_KEYTABLE_MAC0(_n)    (AR_KEYTABLE(_n) + 24)  /* MAC address 1-32 */
+#define        AR_KEYTABLE_MAC1(_n)    (AR_KEYTABLE(_n) + 28)  /* MAC address 33-47 */
+#define        AR_KEYTABLE_VALID       0x00008000      /* key and MAC address valid */
+
+/* Compress settings */
+#define AR_CCFG_WIN_M           0x00000007 /* mask for AR_CCFG_WIN size */
+#define AR_CCFG_MIB_INT_EN      0x00000008 /* compression performance MIB counter int enable */
+#define AR_CCUCFG_RESET_VAL     0x00100200 /* the should be reset value */
+#define AR_CCUCFG_CATCHUP_EN    0x00000001 /* Compression catchup enable */
+#define AR_DCM_D_EN             0x00000001 /* all direct frames to be decompressed */
+#define AR_COMPRESSION_WINDOW_SIZE      4096 /* default comp. window size */
+
+#endif /* _DEV_AR5212REG_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5311reg.h        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5311reg.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5311REG_H_
+#define _DEV_ATH_AR5311REG_H_
+
+/*
+ * Definitions for the Atheros 5311 chipset.
+ */
+#define        AR5311_QDCLKGATE        0x005c  /* MAC QCU/DCU clock gating control */
+#define        AR5311_QDCLKGATE_QCU_M  0x0000FFFF /* QCU clock disable */
+#define        AR5311_QDCLKGATE_DCU_M  0x07FF0000 /* DCU clock disable */
+
+#define        AR5311_RXCFG_DEF_RX_ANTENNA     0x00000008 /* Default Receive Antenna */
+
+/*
+ * NOTE: MAC_5211/MAC_5311 difference
+ * On Oahu the TX latency field has increased from 6 bits to 9 bits.
+ * The RX latency field is unchanged but is shifted over 3 bits.
+ */
+#define        AR5311_USEC_TX_LAT_M    0x000FC000 /* tx latency (usec) */
+#define        AR5311_USEC_TX_LAT_S    14
+#define        AR5311_USEC_RX_LAT_M    0x03F00000 /* rx latency (usec) */
+#define        AR5311_USEC_RX_LAT_S    20
+
+/*
+ * NOTE: MAC_5211/MAC_5311 difference
+ * On Maui2/Spirit the frame sequence number is controlled per DCU.
+ * On Oahu the frame sequence number is global across all DCUs and
+ * is controlled
+ */
+#define        AR5311_D_MISC_SEQ_NUM_CONTROL   0x01000000 /* seq num local or global */
+#define        AR5311_DIAG_USE_ECO     0x00000400      /* "super secret" enable ECO */
+
+#endif /* _DEV_ATH_AR5311REG_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5212/ar5413.c   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,797 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5413.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ah_eeprom_v3.h"
+
+#include "ar5212/ar5212.h"
+#include "ar5212/ar5212reg.h"
+#include "ar5212/ar5212phy.h"
+
+#define AH_5212_5413
+#include "ar5212/ar5212.ini"
+
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+
+struct ar5413State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[PWR_TABLE_SIZE_2413];
+
+       uint32_t        Bank1Data[N(ar5212Bank1_5413)];
+       uint32_t        Bank2Data[N(ar5212Bank2_5413)];
+       uint32_t        Bank3Data[N(ar5212Bank3_5413)];
+       uint32_t        Bank6Data[N(ar5212Bank6_5413)];
+       uint32_t        Bank7Data[N(ar5212Bank7_5413)];
+
+       /*
+        * Private state for reduced stack usage.
+        */
+       /* filled out Vpd table for all pdGains (chanL) */
+       uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (chanR) */
+       uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+       /* filled out Vpd table for all pdGains (interpolated) */
+       uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL]
+                           [MAX_PWR_RANGE_IN_HALF_DB];
+};
+#define        AR5413(ah)      ((struct ar5413State *) AH5212(ah)->ah_rfHal)
+
+extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+               uint32_t numBits, uint32_t firstBit, uint32_t column);
+
+static void
+ar5413WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int writes)
+{
+       HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5413, modesIndex, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212Common_5413, 1, writes);
+       HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5413, freqIndex, writes);
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar5413SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t channelSel  = 0;
+       uint32_t bModeSynth  = 0;
+       uint32_t aModeRefSel = 0;
+       uint32_t reg32       = 0;
+       uint16_t freq;
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       if (chan->channel < 4800) {
+               uint32_t txctl;
+
+               if (((chan->channel - 2192) % 5) == 0) {
+                       channelSel = ((chan->channel - 672) * 2 - 3040)/10;
+                       bModeSynth = 0;
+               } else if (((chan->channel - 2224) % 5) == 0) {
+                       channelSel = ((chan->channel - 704) * 2 - 3040) / 10;
+                       bModeSynth = 1;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid channel %u MHz\n",
+                           __func__, chan->channel);
+                       return AH_FALSE;
+               }
+
+               channelSel = (channelSel << 2) & 0xff;
+               channelSel = ath_hal_reverseBits(channelSel, 8);
+
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (chan->channel == 2484) {
+                       /* Enable channel spreading for channel 14 */
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+       } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) {
+               freq = chan->channel - 2; /* Align to even 5MHz raster */
+               channelSel = ath_hal_reverseBits(
+                       (uint32_t)(((freq - 4800)*10)/25 + 1), 8);
+               aModeRefSel = ath_hal_reverseBits(0, 2);
+       } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 20 << 2), 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else if ((chan->channel % 10) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       ((chan->channel - 4800) / 10 << 1), 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else if ((chan->channel % 5) == 0) {
+               channelSel = ath_hal_reverseBits(
+                       (chan->channel - 4800) / 5, 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
+                   __func__, chan->channel);
+               return AH_FALSE;
+       }
+
+       reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) |
+                       (1 << 12) | 0x1;
+       OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff);
+
+       reg32 >>= 8;
+       OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f);
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar5413SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+#define        RF_BANK_SETUP(_priv, _ix, _col) do {                                \
+       int i;                                                              \
+       for (i = 0; i < N(ar5212Bank##_ix##_5413); i++)                     \
+               (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5413[i][_col];\
+} while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t ob5GHz = 0, db5GHz = 0;
+       uint16_t ob2GHz = 0, db2GHz = 0;
+       struct ar5413State *priv = AR5413(ah);
+       int regWrites = 0;
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM,
+           "%s: chan 0x%x flag 0x%x modesIndex 0x%x\n",
+           __func__, chan->channel, chan->channelFlags, modesIndex);
+
+       HALASSERT(priv != AH_NULL);
+
+       /* Setup rf parameters */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+       case CHANNEL_T:
+               if (chan->channel > 4000 && chan->channel < 5260) {
+                       ob5GHz = ee->ee_ob1;
+                       db5GHz = ee->ee_db1;
+               } else if (chan->channel >= 5260 && chan->channel < 5500) {
+                       ob5GHz = ee->ee_ob2;
+                       db5GHz = ee->ee_db2;
+               } else if (chan->channel >= 5500 && chan->channel < 5725) {
+                       ob5GHz = ee->ee_ob3;
+                       db5GHz = ee->ee_db3;
+               } else if (chan->channel >= 5725) {
+                       ob5GHz = ee->ee_ob4;
+                       db5GHz = ee->ee_db4;
+               } else {
+                       /* XXX else */
+               }
+               break;
+       case CHANNEL_B:
+               ob2GHz = ee->ee_obFor24;
+               db2GHz = ee->ee_dbFor24;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_108G:
+               ob2GHz = ee->ee_obFor24g;
+               db2GHz = ee->ee_dbFor24g;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /* Bank 1 Write */
+       RF_BANK_SETUP(priv, 1, 1);
+
+       /* Bank 2 Write */
+       RF_BANK_SETUP(priv, 2, modesIndex);
+
+       /* Bank 3 Write */
+       RF_BANK_SETUP(priv, 3, modesIndex);
+
+       /* Bank 6 Write */
+       RF_BANK_SETUP(priv, 6, modesIndex);
+
+       /* Only the 5 or 2 GHz OB/DB need to be set for a mode */
+       if (IS_CHAN_2GHZ(chan)) {
+               ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 241, 0);
+               ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 238, 0);
+
+                       /* TODO - only for Eagle 1.0 2GHz - remove for production */
+                       /* XXX: but without this bit G doesn't work. */
+                       ar5212ModifyRfBuffer(priv->Bank6Data, 1 , 1, 291, 2);
+
+                       /* Optimum value for rf_pwd_iclobuf2G for PCIe chips only */
+                       if (IS_PCIE(ah)) {
+                               ar5212ModifyRfBuffer(priv->Bank6Data, ath_hal_reverseBits(6, 3),
+                                                3, 131, 3);
+                       }
+       } else {
+               ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 247, 0);
+               ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 244, 0);
+
+       }
+
+       /* Bank 7 Setup */
+       RF_BANK_SETUP(priv, 7, modesIndex);
+
+       /* Write Analog registers */
+       HAL_INI_WRITE_BANK(ah, ar5212Bank1_5413, priv->Bank1Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank2_5413, priv->Bank2Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank3_5413, priv->Bank3Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank6_5413, priv->Bank6Data, regWrites);
+       HAL_INI_WRITE_BANK(ah, ar5212Bank7_5413, priv->Bank7Data, regWrites);
+
+       /* Now that we have reprogrammed rfgain value, clear the flag. */
+       ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
+
+       return AH_TRUE;
+#undef RF_BANK_SETUP
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar5413GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar5413State *priv = AR5413(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Return indices surrounding the value in sorted integer lists.
+ *
+ * NB: the input list is assumed to be sorted in ascending order
+ */
+static void
+GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize,
+                          uint32_t *vlo, uint32_t *vhi)
+{
+       int16_t target = v;
+       const uint16_t *ep = lp+listSize;
+       const uint16_t *tp;
+
+       /*
+        * Check first and last elements for out-of-bounds conditions.
+        */
+       if (target < lp[0]) {
+               *vlo = *vhi = 0;
+               return;
+       }
+       if (target >= ep[-1]) {
+               *vlo = *vhi = listSize - 1;
+               return;
+       }
+
+       /* look for value being near or between 2 values in list */
+       for (tp = lp; tp < ep; tp++) {
+               /*
+                * If value is close to the current value of the list
+                * then target is not between values, it is one of the values
+                */
+               if (*tp == target) {
+                       *vlo = *vhi = tp - (const uint16_t *) lp;
+                       return;
+               }
+               /*
+                * Look for value being between current value and next value
+                * if so return these 2 values
+                */
+               if (target < tp[1]) {
+                       *vlo = tp - (const uint16_t *) lp;
+                       *vhi = *vlo + 1;
+                       return;
+               }
+       }
+}
+
+/*
+ * Fill the Vpdlist for indices Pmax-Pmin
+ */
+static HAL_BOOL
+ar5413FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t  Pmax,
+                  const int16_t *pwrList, const uint16_t *VpdList,
+                  uint16_t numIntercepts,
+                  uint16_t retVpdList[][64])
+{
+       uint16_t ii, jj, kk;
+       int16_t currPwr = (int16_t)(2*Pmin);
+       /* since Pmin is pwr*2 and pwrList is 4*pwr */
+       uint32_t  idxL = 0, idxR = 0;
+
+       ii = 0;
+       jj = 0;
+
+       if (numIntercepts < 2)
+               return AH_FALSE;
+
+       while (ii <= (uint16_t)(Pmax - Pmin)) {
+               GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList,
+                                  numIntercepts, &(idxL), &(idxR));
+               if (idxR < 1)
+                       idxR = 1;                       /* extrapolate below */
+               if (idxL == (uint32_t)(numIntercepts - 1))
+                       idxL = numIntercepts - 2;       /* extrapolate above */
+               if (pwrList[idxL] == pwrList[idxR])
+                       kk = VpdList[idxL];
+               else
+                       kk = (uint16_t)
+                               (((currPwr - pwrList[idxL])*VpdList[idxR]+
+                                 (pwrList[idxR] - currPwr)*VpdList[idxL])/
+                                (pwrList[idxR] - pwrList[idxL]));
+               retVpdList[pdGainIdx][ii] = kk;
+               ii++;
+               currPwr += 2;                           /* half dB steps */
+       }
+
+       return AH_TRUE;
+}
+
+/*
+ * Returns interpolated or the scaled up interpolated value
+ */
+static int16_t
+interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+       int16_t targetLeft, int16_t targetRight)
+{
+       int16_t rv;
+
+       if (srcRight != srcLeft) {
+               rv = ((target - srcLeft)*targetRight +
+                     (srcRight - target)*targetLeft) / (srcRight - srcLeft);
+       } else {
+               rv = targetLeft;
+       }
+       return rv;
+}
+
+/*
+ * Uses the data points read from EEPROM to reconstruct the pdadc power table
+ * Called by ar5413SetPowerTable()
+ */
+static int
+ar5413getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel,
+               const RAW_DATA_STRUCT_2413 *pRawDataset,
+               uint16_t pdGainOverlap_t2,
+               int16_t  *pMinCalPower, uint16_t pPdGainBoundaries[],
+               uint16_t pPdGainValues[], uint16_t pPDADCValues[])
+{
+       struct ar5413State *priv = AR5413(ah);
+#define        VpdTable_L      priv->vpdTable_L
+#define        VpdTable_R      priv->vpdTable_R
+#define        VpdTable_I      priv->vpdTable_I
+       uint32_t ii, jj, kk;
+       int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */
+       uint32_t idxL = 0, idxR = 0;
+       uint32_t numPdGainsUsed = 0;
+       /*
+        * If desired to support -ve power levels in future, just
+        * change pwr_I_0 to signed 5-bits.
+        */
+       int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on. */
+       int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL];
+       /* to accomodate -ve power levels later on */
+       uint16_t numVpd = 0;
+       uint16_t Vpd_step;
+       int16_t tmpVal ;
+       uint32_t sizeCurrVpdTable, maxIndex, tgtIndex;
+
+       /* Get upper lower index */
+       GetLowerUpperIndex(channel, pRawDataset->pChannels,
+                                pRawDataset->numChannels, &(idxL), &(idxR));
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain;
+                       Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0];
+                       if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) {
+                               Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0];
+                       }
+                       Pmin_t2[numPdGainsUsed] = (int16_t)
+                               (Pmin_t2[numPdGainsUsed] / 2);
+                       Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1])
+                               Pmax_t2[numPdGainsUsed] =
+                                       pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1];
+                       Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2);
+                       ar5413FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L
+                                          );
+                       ar5413FillVpdTable(
+                                          numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed],
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]),
+                                          &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R
+                                          );
+                       for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) {
+                               VpdTable_I[numPdGainsUsed][kk] =
+                                       interpolate_signed(
+                                                          channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR],
+                                                          (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]);
+                       }
+                       /* fill VpdTable_I for this pdGain */
+                       numPdGainsUsed++;
+               }
+               /* if this pdGain is used */
+       }
+
+       *pMinCalPower = Pmin_t2[0];
+       kk = 0; /* index for the final table */
+       for (ii = 0; ii < numPdGainsUsed; ii++) {
+               if (ii == (numPdGainsUsed - 1))
+                       pPdGainBoundaries[ii] = Pmax_t2[ii] +
+                               PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB;
+               else
+                       pPdGainBoundaries[ii] = (uint16_t)
+                               ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 );
+               if (pPdGainBoundaries[ii] > 63) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: clamp pPdGainBoundaries[%d] %d\n",
+                           __func__, ii, pPdGainBoundaries[ii]);/*XXX*/
+                       pPdGainBoundaries[ii] = 63;
+               }
+
+               /* Find starting index for this pdGain */
+               if (ii == 0)
+                       ss = 0; /* for the first pdGain, start from index 0 */
+               else
+                       ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) -
+                               pdGainOverlap_t2;
+               Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                *-ve ss indicates need to extrapolate data below for this pdGain
+                */
+               while (ss < 0) {
+                       tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step);
+                       pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal);
+                       ss++;
+               }
+
+               sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii];
+               tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii];
+               maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
+
+               while (ss < (int16_t)maxIndex)
+                       pPDADCValues[kk++] = VpdTable_I[ii][ss++];
+
+               Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] -
+                                      VpdTable_I[ii][sizeCurrVpdTable-2]);
+               Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step);
+               /*
+                * for last gain, pdGainBoundary == Pmax_t2, so will
+                * have to extrapolate
+                */
+               if (tgtIndex > maxIndex) {      /* need to extrapolate above */
+                       while(ss < (int16_t)tgtIndex) {
+                               tmpVal = (uint16_t)
+                                       (VpdTable_I[ii][sizeCurrVpdTable-1] +
+                                        (ss-maxIndex)*Vpd_step);
+                               pPDADCValues[kk++] = (tmpVal > 127) ?
+                                       127 : tmpVal;
+                               ss++;
+                       }
+               }                               /* extrapolated above */
+       }                                       /* for all pdGainUsed */
+
+       while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) {
+               pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1];
+               ii++;
+       }
+       while (kk < 128) {
+               pPDADCValues[kk] = pPDADCValues[kk-1];
+               kk++;
+       }
+
+       return numPdGainsUsed;
+#undef VpdTable_L
+#undef VpdTable_R
+#undef VpdTable_I
+}
+
+static HAL_BOOL
+ar5413SetPowerTable(struct ath_hal *ah,
+       int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan,
+       uint16_t *rfXpdGain)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL;
+       uint16_t pdGainOverlap_t2;
+       int16_t minCalPower5413_t2;
+       uint16_t *pdadcValues = ahp->ah_pcdacTable;
+       uint16_t gainBoundaries[4];
+       uint32_t reg32, regoffset;
+       int i, numPdGainsUsed;
+#ifndef AH_USE_INIPDGAIN
+       uint32_t tpcrg1;
+#endif
+
+       HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n",
+           __func__, chan->channel,chan->channelFlags);
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else {
+               HALASSERT(IS_CHAN_5GHZ(chan));
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11A];
+       }
+
+       pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5),
+                                         AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
+
+       numPdGainsUsed = ar5413getGainBoundariesAndPdadcsForPowers(ah,
+               chan->channel, pRawDataset, pdGainOverlap_t2,
+               &minCalPower5413_t2,gainBoundaries, rfXpdGain, pdadcValues);
+       HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3);
+
+#ifdef AH_USE_INIPDGAIN
+       /*
+        * Use pd_gains curve from eeprom; Atheros always uses
+        * the default curve from the ini file but some vendors
+        * (e.g. Zcomax) want to override this curve and not
+        * honoring their settings results in tx power 5dBm low.
+        */
+       OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                        (pRawDataset->pDataPerChannel[0].numPdGains - 1));
+#else
+       tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1);
+       tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN)
+                 | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN);
+       switch (numPdGainsUsed) {
+       case 3:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3;
+               tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3);
+               /* fall thru... */
+       case 2:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2;
+               tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2);
+               /* fall thru... */
+       case 1:
+               tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1;
+               tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1);
+               break;
+       }
+#ifdef AH_DEBUG
+       if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1))
+               HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default "
+                   "pd_gains (default 0x%x, calculated 0x%x)\n",
+                   __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1);
+#endif
+       OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1);
+#endif
+
+       /*
+        * Note the pdadc table may not start at 0 dBm power, could be
+        * negative or greater than 0.  Need to offset the power
+        * values by the amount of minPower for griffin
+        */
+       if (minCalPower5413_t2 != 0)
+               ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower5413_t2);
+       else
+               ahp->ah_txPowerIndexOffset = 0;
+
+       /* Finally, write the power values into the baseband power table */
+       regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */
+       for (i = 0; i < 32; i++) {
+               reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0)  |
+                       ((pdadcValues[4*i + 1] & 0xFF) << 8)  |
+                       ((pdadcValues[4*i + 2] & 0xFF) << 16) |
+                       ((pdadcValues[4*i + 3] & 0xFF) << 24) ;
+               OS_REG_WRITE(ah, regoffset, reg32);
+               regoffset += 4;
+       }
+
+       OS_REG_WRITE(ah, AR_PHY_TPCRG5,
+                    SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                    SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
+                    SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
+                    SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
+                    SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+
+       return AH_TRUE;
+}
+
+static int16_t
+ar5413GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data)
+{
+       uint32_t ii,jj;
+       uint16_t Pmin=0,numVpd;
+
+       for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1;
+               /* work backwards 'cause highest pdGain for lowest power */
+               numVpd = data->pDataPerPDGain[jj].numVpd;
+               if (numVpd > 0) {
+                       Pmin = data->pDataPerPDGain[jj].pwr_t4[0];
+                       return(Pmin);
+               }
+       }
+       return(Pmin);
+}
+
+static int16_t
+ar5413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data)
+{
+       uint32_t ii;
+       uint16_t Pmax=0,numVpd;
+
+       for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) {
+               /* work forwards cuase lowest pdGain for highest power */
+               numVpd = data->pDataPerPDGain[ii].numVpd;
+               if (numVpd > 0) {
+                       Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1];
+                       return(Pmax);
+               }
+       }
+       return(Pmax);
+}
+
+static HAL_BOOL
+ar5413GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan,
+       int16_t *maxPow, int16_t *minPow)
+{
+       const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL;
+       const RAW_DATA_PER_CHANNEL_2413 *data=AH_NULL;
+       uint16_t numChannels;
+       int totalD,totalF, totalMin,last, i;
+
+       *maxPow = 0;
+
+       if (IS_CHAN_G(chan) || IS_CHAN_108G(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
+       else if (IS_CHAN_B(chan))
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11B];
+       else {
+               HALASSERT(IS_CHAN_5GHZ(chan));
+               pRawDataset = &ee->ee_rawDataset2413[headerInfo11A];
+       }
+
+       numChannels = pRawDataset->numChannels;
+       data = pRawDataset->pDataPerChannel;
+
+       /* Make sure the channel is in the range of the TP values
+        *  (freq piers)
+        */
+       if (numChannels < 1)
+               return(AH_FALSE);
+
+       if ((chan->channel < data[0].channelValue) ||
+           (chan->channel > data[numChannels-1].channelValue)) {
+               if (chan->channel < data[0].channelValue) {
+                       *maxPow = ar5413GetMaxPower(ah, &data[0]);
+                       *minPow = ar5413GetMinPower(ah, &data[0]);
+                       return(AH_TRUE);
+               } else {
+                       *maxPow = ar5413GetMaxPower(ah, &data[numChannels - 1]);
+                       *minPow = ar5413GetMinPower(ah, &data[numChannels - 1]);
+                       return(AH_TRUE);
+               }
+       }
+
+       /* Linearly interpolate the power value now */
+       for (last=0,i=0; (i<numChannels) && (chan->channel > data[i].channelValue);
+            last = i++);
+       totalD = data[i].channelValue - data[last].channelValue;
+       if (totalD > 0) {
+               totalF = ar5413GetMaxPower(ah, &data[i]) - ar5413GetMaxPower(ah, &data[last]);
+               *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) +
+                                    ar5413GetMaxPower(ah, &data[last])*totalD)/totalD);
+               totalMin = ar5413GetMinPower(ah, &data[i]) - ar5413GetMinPower(ah, &data[last]);
+               *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) +
+                                    ar5413GetMinPower(ah, &data[last])*totalD)/totalD);
+               return(AH_TRUE);
+       } else {
+               if (chan->channel == data[i].channelValue) {
+                       *maxPow = ar5413GetMaxPower(ah, &data[i]);
+                       *minPow = ar5413GetMinPower(ah, &data[i]);
+                       return(AH_TRUE);
+               } else
+                       return(AH_FALSE);
+       }
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar5413RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for analog bank scratch buffers
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+static HAL_BOOL
+ar5413RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5413State *priv;
+
+       HALASSERT(ah->ah_magic == AR5212_MAGIC);
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar5413State));
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar5413RfDetach;
+       priv->base.writeRegs            = ar5413WriteRegs;
+       priv->base.getRfBank            = ar5413GetRfBank;
+       priv->base.setChannel           = ar5413SetChannel;
+       priv->base.setRfRegs            = ar5413SetRfRegs;
+       priv->base.setPowerTable        = ar5413SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar5413GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar5212GetNfAdjust;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+ar5413Probe(struct ath_hal *ah)
+{
+       return IS_5413(ah);
+}
+AH_RF(RF5413, ar5413Probe, ar5413RfAttach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210.h   2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AR5210_H_
+#define _ATH_AR5210_H_
+
+#define        AR5210_MAGIC    0x19980124
+
+#if 0
+/*
+ * RTS_ENABLE includes LONG_PKT because they essentially
+ * imply the same thing, and are set or not set together
+ * for this chip
+ */
+#define AR5210_TXD_CTRL_A_HDR_LEN(_val)         (((_val)      ) & 0x0003f)
+#define AR5210_TXD_CTRL_A_TX_RATE(_val)         (((_val) <<  6) & 0x003c0)
+#define AR5210_TXD_CTRL_A_RTS_ENABLE            (                 0x00c00)
+#define AR5210_TXD_CTRL_A_CLEAR_DEST_MASK(_val) (((_val) << 12) & 0x01000)
+#define AR5210_TXD_CTRL_A_ANT_MODE(_val)        (((_val) << 13) & 0x02000)
+#define AR5210_TXD_CTRL_A_PKT_TYPE(_val)        (((_val) << 14) & 0x1c000)
+#define AR5210_TXD_CTRL_A_INT_REQ               (                 0x20000)
+#define AR5210_TXD_CTRL_A_KEY_VALID             (                 0x40000)
+#define AR5210_TXD_CTRL_B_KEY_ID(_val)          (((_val)      ) & 0x0003f)
+#define AR5210_TXD_CTRL_B_RTS_DURATION(_val)    (((_val) <<  6) & 0x7ffc0)
+#endif
+
+#define INIT_CONFIG_STATUS              0x00000000
+#define INIT_ACKTOPS                    0x00000008
+#define INIT_BCON_CNTRL_REG             0x00000000
+#define INIT_SLOT_TIME                  0x00000168
+#define INIT_SLOT_TIME_TURBO            0x000001e0 /* More aggressive turbo slot timing = 6 us */
+#define INIT_ACK_CTS_TIMEOUT            0x04000400
+#define INIT_ACK_CTS_TIMEOUT_TURBO      0x08000800
+
+#define INIT_USEC                       0x27
+#define INIT_USEC_TURBO                 0x4f
+#define INIT_USEC_32                    0x1f
+#define INIT_TX_LATENCY                 0x36
+#define INIT_RX_LATENCY                 0x1D
+#define INIT_TRANSMIT_LATENCY \
+       ((INIT_RX_LATENCY << AR_USEC_RX_LATENCY_S) | \
+        (INIT_TX_LATENCY << AR_USEC_TX_LATENCY_S) | \
+        (INIT_USEC_32 << 7) | INIT_USEC )
+#define INIT_TRANSMIT_LATENCY_TURBO  \
+       ((INIT_RX_LATENCY << AR_USEC_RX_LATENCY_S) | \
+        (INIT_TX_LATENCY << AR_USEC_TX_LATENCY_S) | \
+        (INIT_USEC_32 << 7) | INIT_USEC_TURBO)
+
+#define INIT_SIFS                       0x230 /* = 16 us - 2 us */
+#define INIT_SIFS_TURBO                 0x1E0 /* More aggressive turbo SIFS timing - 8 us - 2 us */
+
+/*
+ * Various fifo fill before Tx start, in 64-byte units
+ * i.e. put the frame in the air while still DMAing
+ */
+#define MIN_TX_FIFO_THRESHOLD           0x1
+#define MAX_TX_FIFO_THRESHOLD           ((IEEE80211_MAX_LEN / 64) + 1)
+
+#define INIT_NEXT_CFP_START             0xffffffff
+
+#define INIT_BEACON_PERIOD              0xffff
+#define INIT_BEACON_EN                  0 /* this should be set by AP only when it's ready */
+#define INIT_BEACON_CONTROL \
+       ((INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \
+        (INIT_TIM_OFFSET<<16)  | INIT_BEACON_PERIOD)
+
+#define INIT_RSSI_THR                   0x00000700 /* Missed beacon counter initialized to max value of 7 */
+#define INIT_ProgIFS                    0x398      /* PIFS - 2us */
+#define INIT_ProgIFS_TURBO              0x3C0
+#define INIT_EIFS                       0xd70
+#define INIT_EIFS_TURBO                 0x1ae0
+#define INIT_CARR_SENSE_EN              1
+#define INIT_PROTO_TIME_CNTRL           ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS << 12) | \
+                                          (INIT_ProgIFS) )
+#define INIT_PROTO_TIME_CNTRL_TURBO     ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS_TURBO << 12) | \
+                                          (INIT_ProgIFS_TURBO) )
+
+#define        AR5210_MAX_RATE_POWER   60
+
+#undef HAL_NUM_TX_QUEUES       /* from ah.h */
+#define        HAL_NUM_TX_QUEUES       3
+
+struct ath_hal_5210 {
+       struct ath_hal_private ah_priv; /* base definitions */
+
+       uint8_t         ah_macaddr[IEEE80211_ADDR_LEN];
+       /*
+        * Runtime state.
+        */
+       uint32_t        ah_maskReg;             /* shadow of IMR+IER regs */
+       uint32_t        ah_txOkInterruptMask;
+       uint32_t        ah_txErrInterruptMask;
+       uint32_t        ah_txDescInterruptMask;
+       uint32_t        ah_txEolInterruptMask;
+       uint32_t        ah_txUrnInterruptMask;
+       HAL_POWER_MODE  ah_powerMode;
+       uint8_t         ah_bssid[IEEE80211_ADDR_LEN];
+       HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; /* beacon+cab+data */
+       /*
+        * Station mode support.
+        */
+       uint32_t        ah_staId1Defaults;      /* STA_ID1 default settings */
+       uint32_t        ah_rssiThr;             /* RSSI_THR settings */
+
+       u_int           ah_sifstime;            /* user-specified sifs time */
+       u_int           ah_slottime;            /* user-specified slot time */
+       u_int           ah_acktimeout;          /* user-specified ack timeout */
+       u_int           ah_ctstimeout;          /* user-specified cts timeout */
+};
+#define        AH5210(ah)      ((struct ath_hal_5210 *)(ah))
+
+struct ath_hal;
+
+extern void ar5210Detach(struct ath_hal *ah);
+extern HAL_BOOL ar5210Reset(struct ath_hal *, HAL_OPMODE,
+               HAL_CHANNEL *, HAL_BOOL bChannelChange, HAL_STATUS *);
+extern void ar5210SetPCUConfig(struct ath_hal *);
+extern HAL_BOOL ar5210PhyDisable(struct ath_hal *);
+extern HAL_BOOL ar5210Disable(struct ath_hal *);
+extern HAL_BOOL ar5210ChipReset(struct ath_hal *, HAL_CHANNEL *);
+extern HAL_BOOL ar5210PerCalibration(struct ath_hal *, HAL_CHANNEL *, HAL_BOOL *);
+extern HAL_BOOL ar5210PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan,
+               u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone);
+extern HAL_BOOL ar5210ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan);
+extern int16_t ar5210GetNoiseFloor(struct ath_hal *);
+extern int16_t ar5210GetNfAdjust(struct ath_hal *,
+               const HAL_CHANNEL_INTERNAL *);
+extern HAL_BOOL ar5210SetTxPowerLimit(struct ath_hal *, uint32_t limit);
+extern HAL_BOOL ar5210SetTransmitPower(struct ath_hal *, HAL_CHANNEL *);
+extern HAL_BOOL ar5210CalNoiseFloor(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+extern HAL_BOOL ar5210ResetDma(struct ath_hal *, HAL_OPMODE);
+
+extern  HAL_BOOL ar5210SetTxQueueProps(struct ath_hal *ah, int q,
+               const HAL_TXQ_INFO *qInfo);
+extern HAL_BOOL ar5210GetTxQueueProps(struct ath_hal *ah, int q,
+               HAL_TXQ_INFO *qInfo);
+extern int ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
+               const HAL_TXQ_INFO *qInfo);
+extern HAL_BOOL ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q);
+extern HAL_BOOL ar5210ResetTxQueue(struct ath_hal *ah, u_int q);
+extern uint32_t ar5210GetTxDP(struct ath_hal *, u_int);
+extern HAL_BOOL ar5210SetTxDP(struct ath_hal *, u_int, uint32_t txdp);
+extern HAL_BOOL ar5210UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL);
+extern uint32_t ar5210NumTxPending(struct ath_hal *, u_int);
+extern HAL_BOOL ar5210StartTxDma(struct ath_hal *, u_int);
+extern HAL_BOOL ar5210StopTxDma(struct ath_hal *, u_int);
+extern HAL_BOOL ar5210SetupTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower,
+               u_int txRate0, u_int txRetries0,
+               u_int keyIx, u_int antMode, u_int flags,
+               u_int rtsctsRate, u_int rtsctsDuration,
+                u_int compicvLen, u_int compivLen, u_int comp);
+extern HAL_BOOL ar5210SetupXTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int txRate1, u_int txRetries1,
+               u_int txRate2, u_int txRetries2,
+               u_int txRate3, u_int txRetries3);
+extern HAL_BOOL ar5210FillTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+               const struct ath_desc *ds0);
+extern HAL_STATUS ar5210ProcTxDesc(struct ath_hal *,
+               struct ath_desc *, struct ath_tx_status *);
+extern  void ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *);
+extern  void ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *);
+
+extern uint32_t ar5210GetRxDP(struct ath_hal *);
+extern void ar5210SetRxDP(struct ath_hal *, uint32_t rxdp);
+extern void ar5210EnableReceive(struct ath_hal *);
+extern HAL_BOOL ar5210StopDmaReceive(struct ath_hal *);
+extern void ar5210StartPcuReceive(struct ath_hal *);
+extern void ar5210StopPcuReceive(struct ath_hal *);
+extern void ar5210SetMulticastFilter(struct ath_hal *,
+               uint32_t filter0, uint32_t filter1);
+extern HAL_BOOL ar5210ClrMulticastFilterIndex(struct ath_hal *, uint32_t);
+extern HAL_BOOL ar5210SetMulticastFilterIndex(struct ath_hal *, uint32_t);
+extern uint32_t ar5210GetRxFilter(struct ath_hal *);
+extern void ar5210SetRxFilter(struct ath_hal *, uint32_t);
+extern HAL_BOOL ar5210SetupRxDesc(struct ath_hal *, struct ath_desc *,
+               uint32_t, u_int flags);
+extern HAL_STATUS ar5210ProcRxDesc(struct ath_hal *, struct ath_desc *,
+               uint32_t, struct ath_desc *, uint64_t,
+               struct ath_rx_status *);
+
+extern void ar5210GetMacAddress(struct ath_hal *, uint8_t *);
+extern HAL_BOOL ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *);
+extern void ar5210GetBssIdMask(struct ath_hal *, uint8_t *);
+extern HAL_BOOL ar5210SetBssIdMask(struct ath_hal *, const uint8_t *);
+extern HAL_BOOL ar5210EepromRead(struct ath_hal *, u_int off, uint16_t *data);
+extern HAL_BOOL ar5210EepromWrite(struct ath_hal *, u_int off, uint16_t data);
+extern HAL_BOOL ar5210SetRegulatoryDomain(struct ath_hal *,
+               uint16_t, HAL_STATUS *);
+extern u_int ar5210GetWirelessModes(struct ath_hal *ah);
+extern void ar5210EnableRfKill(struct ath_hal *);
+extern HAL_BOOL ar5210GpioCfgInput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5210GpioCfgOutput(struct ath_hal *, uint32_t gpio);
+extern uint32_t ar5210GpioGet(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5210GpioSet(struct ath_hal *, uint32_t gpio, uint32_t);
+extern void ar5210Gpio0SetIntr(struct ath_hal *, u_int, uint32_t ilevel);
+extern void ar5210SetLedState(struct ath_hal *, HAL_LED_STATE);
+extern u_int ar5210GetDefAntenna(struct ath_hal *);
+extern void ar5210SetDefAntenna(struct ath_hal *, u_int);
+extern HAL_ANT_SETTING ar5210GetAntennaSwitch(struct ath_hal *);
+extern HAL_BOOL ar5210SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
+extern void ar5210WriteAssocid(struct ath_hal *,
+               const uint8_t *bssid, uint16_t assocId);
+extern uint32_t ar5210GetTsf32(struct ath_hal *);
+extern uint64_t ar5210GetTsf64(struct ath_hal *);
+extern void ar5210ResetTsf(struct ath_hal *);
+extern uint32_t ar5210GetRandomSeed(struct ath_hal *);
+extern HAL_BOOL ar5210DetectCardPresent(struct ath_hal *);
+extern void ar5210UpdateMibCounters(struct ath_hal *, HAL_MIB_STATS *);
+extern void ar5210EnableHwEncryption(struct ath_hal *);
+extern void ar5210DisableHwEncryption(struct ath_hal *);
+extern HAL_RFGAIN ar5210GetRfgain(struct ath_hal *);
+extern HAL_BOOL ar5210SetSifsTime(struct ath_hal *, u_int);
+extern u_int ar5210GetSifsTime(struct ath_hal *);
+extern HAL_BOOL ar5210SetSlotTime(struct ath_hal *, u_int);
+extern u_int ar5210GetSlotTime(struct ath_hal *);
+extern HAL_BOOL ar5210SetAckTimeout(struct ath_hal *, u_int);
+extern u_int ar5210GetAckTimeout(struct ath_hal *);
+extern HAL_BOOL ar5210SetAckCTSRate(struct ath_hal *, u_int);
+extern u_int ar5210GetAckCTSRate(struct ath_hal *);
+extern HAL_BOOL ar5210SetCTSTimeout(struct ath_hal *, u_int);
+extern u_int ar5210GetCTSTimeout(struct ath_hal *);
+extern  HAL_BOOL ar5210SetDecompMask(struct ath_hal *, uint16_t, int);
+void   ar5210SetCoverageClass(struct ath_hal *, uint8_t, int);
+extern HAL_STATUS ar5210GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE,
+               uint32_t, uint32_t *);
+extern HAL_BOOL ar5210SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE,
+               uint32_t, uint32_t, HAL_STATUS *);
+extern HAL_BOOL ar5210GetDiagState(struct ath_hal *ah, int request,
+               const void *args, uint32_t argsize,
+               void **result, uint32_t *resultsize);
+
+extern u_int ar5210GetKeyCacheSize(struct ath_hal *);
+extern HAL_BOOL ar5210IsKeyCacheEntryValid(struct ath_hal *, uint16_t);
+extern HAL_BOOL ar5210ResetKeyCacheEntry(struct ath_hal *, uint16_t entry);
+extern HAL_BOOL ar5210SetKeyCacheEntry(struct ath_hal *, uint16_t entry,
+                       const HAL_KEYVAL *, const uint8_t *mac, int xorKey);
+extern HAL_BOOL ar5210SetKeyCacheEntryMac(struct ath_hal *,
+                       uint16_t, const uint8_t *);
+
+extern HAL_BOOL ar5210SetPowerMode(struct ath_hal *, uint32_t powerRequest,
+               int setChip);
+extern HAL_POWER_MODE ar5210GetPowerMode(struct ath_hal *);
+
+extern void ar5210SetBeaconTimers(struct ath_hal *,
+               const HAL_BEACON_TIMERS *);
+extern void ar5210BeaconInit(struct ath_hal *, uint32_t, uint32_t);
+extern void ar5210SetStaBeaconTimers(struct ath_hal *,
+               const HAL_BEACON_STATE *);
+extern void ar5210ResetStaBeaconTimers(struct ath_hal *);
+
+extern HAL_BOOL ar5210IsInterruptPending(struct ath_hal *);
+extern HAL_BOOL ar5210GetPendingInterrupts(struct ath_hal *, HAL_INT *);
+extern HAL_INT ar5210GetInterrupts(struct ath_hal *);
+extern HAL_INT ar5210SetInterrupts(struct ath_hal *, HAL_INT ints);
+
+extern const HAL_RATE_TABLE *ar5210GetRateTable(struct ath_hal *, u_int mode);
+
+extern HAL_BOOL ar5210AniControl(struct ath_hal *, HAL_ANI_CMD, int );
+extern void ar5210AniPoll(struct ath_hal *, const HAL_NODE_STATS *, HAL_CHANNEL *);
+extern void ar5210MibEvent(struct ath_hal *, const HAL_NODE_STATS *);
+#endif /* _ATH_AR5210_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_attach.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_attach.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+#include "ar5210/ar5210phy.h"
+
+#include "ah_eeprom_v1.h"
+
+static HAL_BOOL ar5210GetChannelEdges(struct ath_hal *,
+               uint16_t flags, uint16_t *low, uint16_t *high);
+static HAL_BOOL ar5210GetChipPowerLimits(struct ath_hal *ah,
+               HAL_CHANNEL *chans, uint32_t nchans);
+
+static const struct ath_hal_private ar5210hal = {{
+       .ah_magic                       = AR5210_MAGIC,
+       .ah_abi                         = HAL_ABI_VERSION,
+       .ah_countryCode                 = CTRY_DEFAULT,
+
+       .ah_getRateTable                = ar5210GetRateTable,
+       .ah_detach                      = ar5210Detach,
+
+       /* Reset Functions */
+       .ah_reset                       = ar5210Reset,
+       .ah_phyDisable                  = ar5210PhyDisable,
+       .ah_disable                     = ar5210Disable,
+       .ah_setPCUConfig                = ar5210SetPCUConfig,
+       .ah_perCalibration              = ar5210PerCalibration,
+       .ah_perCalibrationN             = ar5210PerCalibrationN,
+       .ah_resetCalValid               = ar5210ResetCalValid,
+       .ah_setTxPowerLimit             = ar5210SetTxPowerLimit,
+       .ah_getChanNoise                = ath_hal_getChanNoise,
+
+       /* Transmit functions */
+       .ah_updateTxTrigLevel           = ar5210UpdateTxTrigLevel,
+       .ah_setupTxQueue                = ar5210SetupTxQueue,
+       .ah_setTxQueueProps             = ar5210SetTxQueueProps,
+       .ah_getTxQueueProps             = ar5210GetTxQueueProps,
+       .ah_releaseTxQueue              = ar5210ReleaseTxQueue,
+       .ah_resetTxQueue                = ar5210ResetTxQueue,
+       .ah_getTxDP                     = ar5210GetTxDP,
+       .ah_setTxDP                     = ar5210SetTxDP,
+       .ah_numTxPending                = ar5210NumTxPending,
+       .ah_startTxDma                  = ar5210StartTxDma,
+       .ah_stopTxDma                   = ar5210StopTxDma,
+       .ah_setupTxDesc                 = ar5210SetupTxDesc,
+       .ah_setupXTxDesc                = ar5210SetupXTxDesc,
+       .ah_fillTxDesc                  = ar5210FillTxDesc,
+       .ah_procTxDesc                  = ar5210ProcTxDesc,
+       .ah_getTxIntrQueue              = ar5210GetTxIntrQueue,
+       .ah_reqTxIntrDesc               = ar5210IntrReqTxDesc,
+
+       /* RX Functions */
+       .ah_getRxDP                     = ar5210GetRxDP,
+       .ah_setRxDP                     = ar5210SetRxDP,
+       .ah_enableReceive               = ar5210EnableReceive,
+       .ah_stopDmaReceive              = ar5210StopDmaReceive,
+       .ah_startPcuReceive             = ar5210StartPcuReceive,
+       .ah_stopPcuReceive              = ar5210StopPcuReceive,
+       .ah_setMulticastFilter          = ar5210SetMulticastFilter,
+       .ah_setMulticastFilterIndex     = ar5210SetMulticastFilterIndex,
+       .ah_clrMulticastFilterIndex     = ar5210ClrMulticastFilterIndex,
+       .ah_getRxFilter                 = ar5210GetRxFilter,
+       .ah_setRxFilter                 = ar5210SetRxFilter,
+       .ah_setupRxDesc                 = ar5210SetupRxDesc,
+       .ah_procRxDesc                  = ar5210ProcRxDesc,
+       .ah_rxMonitor                   = ar5210AniPoll,
+       .ah_procMibEvent                = ar5210MibEvent,
+
+       /* Misc Functions */
+       .ah_getCapability               = ar5210GetCapability,
+       .ah_setCapability               = ar5210SetCapability,
+       .ah_getDiagState                = ar5210GetDiagState,
+       .ah_getMacAddress               = ar5210GetMacAddress,
+       .ah_setMacAddress               = ar5210SetMacAddress,
+       .ah_getBssIdMask                = ar5210GetBssIdMask,
+       .ah_setBssIdMask                = ar5210SetBssIdMask,
+       .ah_setRegulatoryDomain         = ar5210SetRegulatoryDomain,
+       .ah_setLedState                 = ar5210SetLedState,
+       .ah_writeAssocid                = ar5210WriteAssocid,
+       .ah_gpioCfgInput                = ar5210GpioCfgInput,
+       .ah_gpioCfgOutput               = ar5210GpioCfgOutput,
+       .ah_gpioGet                     = ar5210GpioGet,
+       .ah_gpioSet                     = ar5210GpioSet,
+       .ah_gpioSetIntr                 = ar5210Gpio0SetIntr,
+       .ah_getTsf32                    = ar5210GetTsf32,
+       .ah_getTsf64                    = ar5210GetTsf64,
+       .ah_resetTsf                    = ar5210ResetTsf,
+       .ah_detectCardPresent           = ar5210DetectCardPresent,
+       .ah_updateMibCounters           = ar5210UpdateMibCounters,
+       .ah_getRfGain                   = ar5210GetRfgain,
+       .ah_getDefAntenna               = ar5210GetDefAntenna,
+       .ah_setDefAntenna               = ar5210SetDefAntenna,
+       .ah_getAntennaSwitch            = ar5210GetAntennaSwitch,
+       .ah_setAntennaSwitch            = ar5210SetAntennaSwitch,
+       .ah_setSifsTime                 = ar5210SetSifsTime,
+       .ah_getSifsTime                 = ar5210GetSifsTime,
+       .ah_setSlotTime                 = ar5210SetSlotTime,
+       .ah_getSlotTime                 = ar5210GetSlotTime,
+       .ah_setAckTimeout               = ar5210SetAckTimeout,
+       .ah_getAckTimeout               = ar5210GetAckTimeout,
+       .ah_setAckCTSRate               = ar5210SetAckCTSRate,
+       .ah_getAckCTSRate               = ar5210GetAckCTSRate,
+       .ah_setCTSTimeout               = ar5210SetCTSTimeout,
+       .ah_getCTSTimeout               = ar5210GetCTSTimeout,
+       .ah_setDecompMask               = ar5210SetDecompMask,
+       .ah_setCoverageClass            = ar5210SetCoverageClass,
+
+       /* Key Cache Functions */
+       .ah_getKeyCacheSize             = ar5210GetKeyCacheSize,
+       .ah_resetKeyCacheEntry          = ar5210ResetKeyCacheEntry,
+       .ah_isKeyCacheEntryValid        = ar5210IsKeyCacheEntryValid,
+       .ah_setKeyCacheEntry            = ar5210SetKeyCacheEntry,
+       .ah_setKeyCacheEntryMac         = ar5210SetKeyCacheEntryMac,
+
+       /* Power Management Functions */
+       .ah_setPowerMode                = ar5210SetPowerMode,
+       .ah_getPowerMode                = ar5210GetPowerMode,
+
+       /* Beacon Functions */
+       .ah_setBeaconTimers             = ar5210SetBeaconTimers,
+       .ah_beaconInit                  = ar5210BeaconInit,
+       .ah_setStationBeaconTimers      = ar5210SetStaBeaconTimers,
+       .ah_resetStationBeaconTimers    = ar5210ResetStaBeaconTimers,
+
+       /* Interrupt Functions */
+       .ah_isInterruptPending          = ar5210IsInterruptPending,
+       .ah_getPendingInterrupts        = ar5210GetPendingInterrupts,
+       .ah_getInterrupts               = ar5210GetInterrupts,
+       .ah_setInterrupts               = ar5210SetInterrupts },
+
+       .ah_getChannelEdges             = ar5210GetChannelEdges,
+       .ah_getWirelessModes            = ar5210GetWirelessModes,
+       .ah_eepromRead                  = ar5210EepromRead,
+#ifdef AH_SUPPORT_WRITE_EEPROM
+       .ah_eepromWrite                 = ar5210EepromWrite,
+#endif
+       .ah_gpioCfgInput                = ar5210GpioCfgInput,
+       .ah_gpioCfgOutput               = ar5210GpioCfgOutput,
+       .ah_gpioGet                     = ar5210GpioGet,
+       .ah_gpioSet                     = ar5210GpioSet,
+       .ah_gpioSetIntr                 = ar5210Gpio0SetIntr,
+       .ah_getChipPowerLimits          = ar5210GetChipPowerLimits,
+};
+
+static HAL_BOOL ar5210FillCapabilityInfo(struct ath_hal *ah);
+
+/*
+ * Attach for an AR5210 part.
+ */
+static struct ath_hal *
+ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh,
+       HAL_STATUS *status)
+{
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+       struct ath_hal_5210 *ahp;
+       struct ath_hal *ah;
+       uint32_t revid, pcicfg;
+       uint16_t eeval;
+       HAL_STATUS ecode;
+       int i;
+
+       HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH,
+           "%s: devid 0x%x sc %p st %p sh %p\n", __func__, devid,
+           sc, (void*) st, (void*) sh);
+
+       /* NB: memory is returned zero'd */
+       ahp = ath_hal_malloc(sizeof (struct ath_hal_5210));
+       if (ahp == AH_NULL) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                   "%s: no memory for state block\n", __func__);
+               ecode = HAL_ENOMEM;
+               goto bad;
+       }
+       ah = &ahp->ah_priv.h;
+       /* set initial values */
+       OS_MEMCPY(&ahp->ah_priv, &ar5210hal, sizeof(struct ath_hal_private));
+       ah->ah_sc = sc;
+       ah->ah_st = st;
+       ah->ah_sh = sh;
+
+       ah->ah_devid = devid;                   /* NB: for AH_DEBUG_ALQ */
+       AH_PRIVATE(ah)->ah_devid = devid;
+       AH_PRIVATE(ah)->ah_subvendorid = 0;     /* XXX */
+
+       AH_PRIVATE(ah)->ah_powerLimit = AR5210_MAX_RATE_POWER;
+       AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX;  /* no scaling */
+
+       ahp->ah_powerMode = HAL_PM_UNDEFINED;
+       ahp->ah_staId1Defaults = 0;
+       ahp->ah_rssiThr = INIT_RSSI_THR;
+       ahp->ah_sifstime = (u_int) -1;
+       ahp->ah_slottime = (u_int) -1;
+       ahp->ah_acktimeout = (u_int) -1;
+       ahp->ah_ctstimeout = (u_int) -1;
+
+       if (!ar5210ChipReset(ah, AH_NULL)) {    /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",
+                   __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       /* Read Revisions from Chips */
+       AH_PRIVATE(ah)->ah_macVersion = 1;
+       AH_PRIVATE(ah)->ah_macRev = OS_REG_READ(ah, AR_SREV) & 0xff;
+       AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIPID);
+       AH_PRIVATE(ah)->ah_analog2GhzRev = 0;
+
+       /* Read Radio Chip Rev Extract */
+       OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16);
+       for (i = 0; i < 4; i++)
+               OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000);
+       revid = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 28) & 0xf;
+
+       /* Chip labelling is 1 greater than revision register for AR5110 */
+       AH_PRIVATE(ah)->ah_analog5GhzRev = ath_hal_reverseBits(revid, 4) + 1;
+
+       /*
+        * Read all the settings from the EEPROM and stash
+        * ones we'll use later.
+        */
+       pcicfg = OS_REG_READ(ah, AR_PCICFG);
+       OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL);
+       ecode = ath_hal_v1EepromAttach(ah);
+       if (ecode != HAL_OK) {
+               goto eebad;
+       }
+       ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot read regulatory domain from EEPROM\n",
+                   __func__);
+               goto eebad;
+        }
+       AH_PRIVATE(ah)->ah_currentRD = eeval;
+       ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error getting mac address from EEPROM\n", __func__);
+               goto eebad;
+        }
+       OS_REG_WRITE(ah, AR_PCICFG, pcicfg);    /* disable EEPROM access */
+
+       AH_PRIVATE(ah)->ah_getNfAdjust = ar5210GetNfAdjust;
+
+       /*
+        * Got everything we need now to setup the capabilities.
+        */
+       (void) ar5210FillCapabilityInfo(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
+
+       return ah;
+eebad:
+       OS_REG_WRITE(ah, AR_PCICFG, pcicfg);    /* disable EEPROM access */
+bad:
+       if (ahp)
+               ath_hal_free(ahp);
+       if (status)
+               *status = ecode;
+       return AH_NULL;
+#undef N
+}
+
+void
+ar5210Detach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
+
+       HALASSERT(ah != AH_NULL);
+       HALASSERT(ah->ah_magic == AR5210_MAGIC);
+
+       ath_hal_eepromDetach(ah);
+       ath_hal_free(ah);
+}
+
+/*
+ * Store the channel edges for the requested operational mode
+ */
+static HAL_BOOL
+ar5210GetChannelEdges(struct ath_hal *ah,
+       uint16_t flags, uint16_t *low, uint16_t *high)
+{
+       if (flags & CHANNEL_5GHZ) {
+               *low = 5120;
+               *high = 5430;
+               return AH_TRUE;
+       } else {
+               return AH_FALSE;
+       }
+}
+
+static HAL_BOOL
+ar5210GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans)
+{
+       HAL_CHANNEL *chan;
+       int i;
+
+       /* XXX fill in, this is just a placeholder */
+       for (i = 0; i < nchans; i++) {
+               chan = &chans[i];
+               HALDEBUG(ah, HAL_DEBUG_ATTACH,
+                   "%s: no min/max power for %u/0x%x\n",
+                   __func__, chan->channel, chan->channelFlags);
+               chan->maxTxPower = AR5210_MAX_RATE_POWER;
+               chan->minTxPower = 0;
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Fill all software cached or static hardware state information.
+ */
+static HAL_BOOL
+ar5210FillCapabilityInfo(struct ath_hal *ah)
+{
+       struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
+       HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
+
+       pCap->halWirelessModes |= HAL_MODE_11A;
+
+       pCap->halLow5GhzChan = 5120;
+       pCap->halHigh5GhzChan = 5430;
+
+       pCap->halSleepAfterBeaconBroken = AH_TRUE;
+       pCap->halPSPollBroken = AH_FALSE;
+
+       pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
+       pCap->halKeyCacheSize = 64;
+
+       /* XXX not needed */
+       pCap->halChanHalfRate = AH_FALSE;
+       pCap->halChanQuarterRate = AH_FALSE;
+
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL)) {
+               /*
+                * Setup initial rfsilent settings based on the EEPROM
+                * contents.  Pin 0, polarity 0 is fixed; record this
+                * using the EEPROM format found in later parts.
+                */
+               ahpriv->ah_rfsilent = SM(0, AR_EEPROM_RFSILENT_GPIO_SEL)
+                                   | SM(0, AR_EEPROM_RFSILENT_POLARITY);
+               ahpriv->ah_rfkillEnabled = AH_TRUE;
+               pCap->halRfSilentSupport = AH_TRUE;
+       }
+
+       pCap->halTstampPrecision = 15;          /* NB: s/w extended from 13 */
+
+       ahpriv->ah_rxornIsFatal = AH_TRUE;
+       return AH_TRUE;
+}
+
+static const char*
+ar5210Probe(uint16_t vendorid, uint16_t devid)
+{
+       if (vendorid == ATHEROS_VENDOR_ID &&
+           (devid == AR5210_PROD || devid == AR5210_DEFAULT))
+               return "Atheros 5210";
+       return AH_NULL;
+}
+AH_CHIP(AR5210, ar5210Probe, ar5210Attach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_beacon.c    2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_beacon.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+#include "ar5210/ar5210desc.h"
+
+/*
+ * Initialize all of the hardware registers used to send beacons.
+ */
+void
+ar5210SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
+{
+
+       OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt);
+       OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba);
+       OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba);
+       OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim);
+       /*
+        * Set the Beacon register after setting all timers.
+        */
+       OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval);
+}
+
+/*
+ * Legacy api to Initialize all of the beacon registers.
+ */
+void
+ar5210BeaconInit(struct ath_hal *ah,
+       uint32_t next_beacon, uint32_t beacon_period)
+{
+       HAL_BEACON_TIMERS bt;
+
+       bt.bt_nexttbtt = next_beacon;
+
+       if (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA) {
+               bt.bt_nextdba = (next_beacon -
+                       ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */
+               bt.bt_nextswba = (next_beacon -
+                       ath_hal_sw_beacon_response_time) << 3;  /* 1/8 TU */
+               /*
+                * The SWBA interrupt is not used for beacons in ad hoc mode
+                * as we don't yet support ATIMs. So since the beacon never
+                * changes, the beacon descriptor is set up once and read
+                * into a special HW buffer, from which it will be
+                * automagically retrieved at each DMA Beacon Alert (DBA).
+                */
+
+               /* Set the ATIM window */
+               bt.bt_nextatim = next_beacon + 0;       /* NB: no ATIMs */
+       } else {
+               bt.bt_nextdba = ~0;
+               bt.bt_nextswba = ~0;
+               bt.bt_nextatim = 1;
+       }
+       bt.bt_intval = beacon_period &
+               (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
+       ar5210SetBeaconTimers(ah, &bt);
+}
+
+void
+ar5210ResetStaBeaconTimers(struct ath_hal *ah)
+{
+       uint32_t val;
+
+       OS_REG_WRITE(ah, AR_TIMER0, 0);         /* no beacons */
+       val = OS_REG_READ(ah, AR_STA_ID1);
+       val |= AR_STA_ID1_NO_PSPOLL;            /* XXX */
+       /* tell the h/w that the associated AP is not PCF capable */
+       OS_REG_WRITE(ah, AR_STA_ID1,
+               val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF));
+       OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD);
+}
+
+/*
+ * Set all the beacon related bits on the h/w for stations
+ * i.e. initializes the corresponding h/w timers;
+ * also tells the h/w whether to anticipate PCF beacons
+ *
+ * dtim_count and cfp_count from the current beacon - their current
+ * values aren't necessarily maintained in the device struct
+ */
+void
+ar5210SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__);
+
+       HALASSERT(bs->bs_intval != 0);
+       /* if the AP will do PCF */
+       if (bs->bs_cfpmaxduration != 0) {
+               /* tell the h/w that the associated AP is PCF capable */
+               OS_REG_WRITE(ah, AR_STA_ID1,
+                       (OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_DEFAULT_ANTENNA)
+                       | AR_STA_ID1_PCF);
+
+               /* set CFP_PERIOD(1.024ms) register */
+               OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod);
+
+               /* set CFP_DUR(1.024ms) register to max cfp duration */
+               OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration);
+
+               /* set TIMER2(128us) to anticipated time of next CFP */
+               OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3);
+       } else {
+               /* tell the h/w that the associated AP is not PCF capable */
+               OS_REG_WRITE(ah, AR_STA_ID1,
+                       OS_REG_READ(ah, AR_STA_ID1) &~ (AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF));
+       }
+
+       /*
+        * Set TIMER0(1.024ms) to the anticipated time of the next beacon.
+        */
+       OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt);
+
+       /*
+        * Start the beacon timers by setting the BEACON register
+        * to the beacon interval; also write the tim offset which
+        * we should know by now.  The code, in ar5211WriteAssocid,
+        * also sets the tim offset once the AID is known which can
+        * be left as such for now.
+        */
+       OS_REG_WRITE(ah, AR_BEACON,
+               (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM))
+               | SM(bs->bs_intval, AR_BEACON_PERIOD)
+               | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM)
+       );
+
+       /*
+        * Configure the BMISS interrupt.  Note that we
+        * assume the caller blocks interrupts while enabling
+        * the threshold.
+        */
+
+       /*
+        * Interrupt works only on Crete.
+        */
+       if (AH_PRIVATE(ah)->ah_macRev < AR_SREV_CRETE)
+               return;
+       /*
+        * Counter is only 3-bits.
+        * Count of 0 with BMISS interrupt enabled will hang the system
+        * with too many interrupts
+        */
+       if (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_CRETE &&
+           (bs->bs_bmissthreshold&7) == 0) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s: invalid beacon miss threshold %u\n",
+                       __func__, bs->bs_bmissthreshold);
+#endif
+               return;
+       }
+#define        BMISS_MAX       (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S)
+       /*
+        * Configure the BMISS interrupt.  Note that we
+        * assume the caller blocks interrupts while enabling
+        * the threshold.
+        *
+        * NB: the beacon miss count field is only 3 bits which
+        *     is much smaller than what's found on later parts;
+        *     clamp overflow values as a safeguard.
+        */
+       ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR)
+                       | SM(bs->bs_bmissthreshold > BMISS_MAX ?
+                               BMISS_MAX : bs->bs_bmissthreshold,
+                            AR_RSSI_THR_BM_THR);
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+#undef BMISS_MAX
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_interrupts.c        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_interrupts.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+
+/*
+ * Return non-zero if an interrupt is pending.
+ */
+HAL_BOOL
+ar5210IsInterruptPending(struct ath_hal *ah)
+{
+       return (OS_REG_READ(ah, AR_INTPEND) ? AH_TRUE : AH_FALSE);
+}
+
+/*
+ * Read the Interrupt Status Register value and return
+ * an abstracted bitmask of the data found in the ISR.
+ * Note that reading the ISR clear pending interrupts.
+ */
+HAL_BOOL
+ar5210GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)
+{
+#define        AR_FATAL_INT \
+    (AR_ISR_MCABT_INT | AR_ISR_SSERR_INT | AR_ISR_DPERR_INT | AR_ISR_RXORN_INT)
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       uint32_t isr;
+
+       isr = OS_REG_READ(ah, AR_ISR);
+       if (isr == 0xffffffff) {
+               *masked = 0;
+               return AH_FALSE;
+       }
+
+       /*
+        * Mask interrupts that have no device-independent
+        * representation; these are added back below.  We
+        * also masked with the abstracted IMR to insure no
+        * status bits leak through that weren't requested
+        * (e.g. RXNOFRM) and that might confuse the caller.
+        */
+       *masked = (isr & HAL_INT_COMMON) & ahp->ah_maskReg;
+
+       if (isr & AR_FATAL_INT)
+               *masked |= HAL_INT_FATAL;
+       if (isr & (AR_ISR_RXOK_INT | AR_ISR_RXERR_INT))
+               *masked |= HAL_INT_RX;
+       if (isr & (AR_ISR_TXOK_INT | AR_ISR_TXDESC_INT | AR_ISR_TXERR_INT | AR_ISR_TXEOL_INT))
+               *masked |= HAL_INT_TX;
+
+       /*
+        * On fatal errors collect ISR state for debugging.
+        */
+       if (*masked & HAL_INT_FATAL) {
+               AH_PRIVATE(ah)->ah_fatalState[0] = isr;
+       }
+
+       return AH_TRUE;
+#undef AR_FATAL_INT
+}
+
+HAL_INT
+ar5210GetInterrupts(struct ath_hal *ah)
+{
+       return AH5210(ah)->ah_maskReg;
+}
+
+HAL_INT
+ar5210SetInterrupts(struct ath_hal *ah, HAL_INT ints)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       uint32_t omask = ahp->ah_maskReg;
+       uint32_t mask;
+
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",
+           __func__, omask, ints);
+
+       /*
+        * Disable interrupts here before reading & modifying
+        * the mask so that the ISR does not modify the mask
+        * out from under us.
+        */
+       if (omask & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+       }
+
+       mask = ints & HAL_INT_COMMON;
+       if (ints & HAL_INT_RX)
+               mask |= AR_IMR_RXOK_INT | AR_IMR_RXERR_INT;
+       if (ints & HAL_INT_TX) {
+               if (ahp->ah_txOkInterruptMask)
+                       mask |= AR_IMR_TXOK_INT;
+               if (ahp->ah_txErrInterruptMask)
+                       mask |= AR_IMR_TXERR_INT;
+               if (ahp->ah_txDescInterruptMask)
+                       mask |= AR_IMR_TXDESC_INT;
+               if (ahp->ah_txEolInterruptMask)
+                       mask |= AR_IMR_TXEOL_INT;
+       }
+
+       /* Write the new IMR and store off our SW copy. */
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
+       OS_REG_WRITE(ah, AR_IMR, mask);
+       ahp->ah_maskReg = ints;
+
+       /* Re-enable interrupts as appropriate. */
+       if (ints & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+       }
+
+       return omask;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_keycache.c  2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_keycache.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+
+#define        AR_KEYTABLE_SIZE        64
+#define        KEY_XOR                 0xaa
+
+/*
+ * Return the size of the hardware key cache.
+ */
+u_int
+ar5210GetKeyCacheSize(struct ath_hal *ah)
+{
+       return AR_KEYTABLE_SIZE;
+}
+
+/*
+ * Return the size of the hardware key cache.
+ */
+HAL_BOOL
+ar5210IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry)
+{
+       if (entry < AR_KEYTABLE_SIZE) {
+               uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
+               if (val & AR_KEYTABLE_VALID)
+                       return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Clear the specified key cache entry.
+ */
+HAL_BOOL
+ar5210ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
+{
+       if (entry < AR_KEYTABLE_SIZE) {
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+               OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Sets the mac part of the specified key cache entry and mark it valid.
+ */
+HAL_BOOL
+ar5210SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac)
+{
+       uint32_t macHi, macLo;
+
+       if (entry < AR_KEYTABLE_SIZE) {
+               /*
+                * Set MAC address -- shifted right by 1.  MacLo is
+                * the 4 MSBs, and MacHi is the 2 LSBs.
+                */
+               if (mac != AH_NULL) {
+                       macHi = (mac[5] << 8) | mac[4];
+                       macLo = (mac[3] << 24)| (mac[2] << 16)
+                             | (mac[1] << 8) | mac[0];
+                       macLo >>= 1;
+                       macLo |= (macHi & 1) << 31;     /* carry */
+                       macHi >>= 1;
+               } else {
+                       macLo = macHi = 0;
+               }
+
+               OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+               OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry),
+                       macHi | AR_KEYTABLE_VALID);
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Sets the contents of the specified key cache entry.
+ */
+HAL_BOOL
+ar5210SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
+                       const HAL_KEYVAL *k, const uint8_t *mac, int xorKey)
+{
+       uint32_t key0, key1, key2, key3, key4;
+       uint32_t keyType;
+       uint32_t xorMask= xorKey ?
+               (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
+
+       if (entry >= AR_KEYTABLE_SIZE)
+               return AH_FALSE;
+       if (k->kv_type != HAL_CIPHER_WEP) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n",
+                   __func__, k->kv_type);
+               return AH_FALSE;
+       }
+
+       /* NB: only WEP supported */
+       if (k->kv_len < 40 / NBBY)
+               return AH_FALSE;
+       if (k->kv_len <= 40 / NBBY)
+               keyType = AR_KEYTABLE_TYPE_40;
+       else if (k->kv_len <= 104 / NBBY)
+               keyType = AR_KEYTABLE_TYPE_104;
+       else
+               keyType = AR_KEYTABLE_TYPE_128;
+
+       key0 = LE_READ_4(k->kv_val+0) ^ xorMask;
+       key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff;
+       key2 = LE_READ_4(k->kv_val+6) ^ xorMask;
+       key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff;
+       key4 = LE_READ_4(k->kv_val+12) ^ xorMask;
+       if (k->kv_len <= 104 / NBBY)
+               key4 &= 0xff;
+
+       /*
+        * Note: WEP key cache hardware requires that each double-word
+        * pair be written in even/odd order (since the destination is
+        * a 64-bit register).  Don't reorder these writes w/o
+        * understanding this!
+        */
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+       OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+       OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+       return ar5210SetKeyCacheEntryMac(ah, entry, mac);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_misc.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_misc.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+#include "ar5210/ar5210phy.h"
+
+#include "ah_eeprom_v1.h"
+
+#define        AR_NUM_GPIO     6               /* 6 GPIO bits */
+#define        AR_GPIOD_MASK   0x2f            /* 6-bit mask */
+
+void
+ar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
+}
+
+HAL_BOOL
+ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
+       return AH_TRUE;
+}
+
+void
+ar5210GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
+{
+       static const uint8_t ones[IEEE80211_ADDR_LEN] =
+               { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+       OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN);
+}
+
+HAL_BOOL
+ar5210SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
+{
+       return AH_FALSE;
+}
+
+/*
+ * Read 16 bits of data from the specified EEPROM offset.
+ */
+HAL_BOOL
+ar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
+{
+       (void) OS_REG_READ(ah, AR_EP_AIR(off)); /* activate read op */
+       if (!ath_hal_wait(ah, AR_EP_STA,
+           AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n",
+                   __func__, AR_EP_AIR(off));
+               return AH_FALSE;
+       }
+       *data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff;
+       return AH_TRUE;
+}
+
+#ifdef AH_SUPPORT_WRITE_EEPROM
+/*
+ * Write 16 bits of data to the specified EEPROM offset.
+ */
+HAL_BOOL
+ar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data)
+{
+       return AH_FALSE;
+}
+#endif /* AH_SUPPORT_WRITE_EEPROM */
+
+/*
+ * Attempt to change the cards operating regulatory domain to the given value
+ */
+HAL_BOOL
+ar5210SetRegulatoryDomain(struct ath_hal *ah,
+       uint16_t regDomain, HAL_STATUS *status)
+{
+       HAL_STATUS ecode;
+
+       if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
+               ecode = HAL_EINVAL;
+               goto bad;
+       }
+       /*
+        * Check if EEPROM is configured to allow this; must
+        * be a proper version and the protection bits must
+        * permit re-writing that segment of the EEPROM.
+        */
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
+               ecode = HAL_EEWRITE;
+               goto bad;
+       }
+       ecode = HAL_EIO;                /* disallow all writes */
+bad:
+       if (status)
+               *status = ecode;
+       return AH_FALSE;
+}
+
+/*
+ * Return the wireless modes (a,b,g,t) supported by hardware.
+ *
+ * This value is what is actually supported by the hardware
+ * and is unaffected by regulatory/country code settings.
+ *
+ */
+u_int
+ar5210GetWirelessModes(struct ath_hal *ah)
+{
+       /* XXX could enable turbo mode but can't do all rates */
+       return HAL_MODE_11A;
+}
+
+/*
+ * Called if RfKill is supported (according to EEPROM).  Set the interrupt and
+ * GPIO values so the ISR and can disable RF on a switch signal
+ */
+void
+ar5210EnableRfKill(struct ath_hal *ah)
+{
+       uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
+       int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
+       int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
+
+       /*
+        * If radio disable switch connection to GPIO bit 0 is enabled
+        * program GPIO interrupt.
+        * If rfkill bit on eeprom is 1, setupeeprommap routine has already
+        * verified that it is a later version of eeprom, it has a place for
+        * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware
+        * connection is present.
+        */
+       ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity));
+}
+
+/*
+ * Configure GPIO Output lines
+ */
+HAL_BOOL
+ar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio)
+{
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       OS_REG_WRITE(ah, AR_GPIOCR,
+                 (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
+               | AR_GPIOCR_OUT1(gpio));
+
+       return AH_TRUE;
+}
+
+/*
+ * Configure GPIO Input lines
+ */
+HAL_BOOL
+ar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
+{
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       OS_REG_WRITE(ah, AR_GPIOCR,
+                 (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio))
+               | AR_GPIOCR_IN(gpio));
+
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - set output lines
+ */
+HAL_BOOL
+ar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
+{
+       uint32_t reg;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+
+       reg =  OS_REG_READ(ah, AR_GPIODO);
+       reg &= ~(1 << gpio);
+       reg |= (val&1) << gpio;
+
+       OS_REG_WRITE(ah, AR_GPIODO, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - get input lines
+ */
+uint32_t
+ar5210GpioGet(struct ath_hal *ah, uint32_t gpio)
+{
+       if (gpio < AR_NUM_GPIO) {
+               uint32_t val = OS_REG_READ(ah, AR_GPIODI);
+               val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1;
+               return val;
+       } else  {
+               return 0xffffffff;
+       }
+}
+
+/*
+ * Set the GPIO 0 Interrupt
+ */
+void
+ar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
+{
+       uint32_t val = OS_REG_READ(ah, AR_GPIOCR);
+
+       /* Clear the bits that we will modify. */
+       val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA |
+                       AR_GPIOCR_ALL(gpio));
+
+       val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA;
+       if (ilevel)
+               val |= AR_GPIOCR_INT_SELH;
+
+       /* Don't need to change anything for low level interrupt. */
+       OS_REG_WRITE(ah, AR_GPIOCR, val);
+
+       /* Change the interrupt mask. */
+       ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO);
+}
+
+/*
+ * Change the LED blinking pattern to correspond to the connectivity
+ */
+void
+ar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
+{
+       uint32_t val;
+
+       val = OS_REG_READ(ah, AR_PCICFG);
+       switch (state) {
+       case HAL_LED_INIT:
+               val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT);
+               break;
+       case HAL_LED_RUN:
+               /* normal blink when connected */
+               val &= ~AR_PCICFG_LED_PEND;
+               val |= AR_PCICFG_LED_ACT;
+               break;
+       default:
+               val |= AR_PCICFG_LED_PEND;
+               val &= ~AR_PCICFG_LED_ACT;
+               break;
+       }
+       OS_REG_WRITE(ah, AR_PCICFG, val);
+}
+
+/*
+ * Return 1 or 2 for the corresponding antenna that is in use
+ */
+u_int
+ar5210GetDefAntenna(struct ath_hal *ah)
+{
+       uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
+       return (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1);
+}
+
+void
+ar5210SetDefAntenna(struct ath_hal *ah, u_int antenna)
+{
+       uint32_t val = OS_REG_READ(ah, AR_STA_ID1);
+
+       if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ?  2 : 1)) {
+               /*
+                * Antenna change requested, force a toggle of the default.
+                */
+               OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA);
+       }
+}
+
+HAL_ANT_SETTING
+ar5210GetAntennaSwitch(struct ath_hal *ah)
+{
+       return HAL_ANT_VARIABLE;
+}
+
+HAL_BOOL
+ar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
+{
+       /* XXX not sure how to fix antenna */
+       return (settings == HAL_ANT_VARIABLE);
+}
+
+/*
+ * Change association related fields programmed into the hardware.
+ * Writing a valid BSSID to the hardware effectively enables the hardware
+ * to synchronize its TSF to the correct beacons and receive frames coming
+ * from that BSSID. It is called by the SME JOIN operation.
+ */
+void
+ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       /* XXX save bssid for possible re-use on reset */
+       OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
+                                    ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
+       if (assocId == 0)
+               OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
+       else
+               OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL);
+}
+
+/*
+ * Get the current hardware tsf for stamlme.
+ */
+uint64_t
+ar5210GetTsf64(struct ath_hal *ah)
+{
+       uint32_t low1, low2, u32;
+
+       /* sync multi-word read */
+       low1 = OS_REG_READ(ah, AR_TSF_L32);
+       u32 = OS_REG_READ(ah, AR_TSF_U32);
+       low2 = OS_REG_READ(ah, AR_TSF_L32);
+       if (low2 < low1) {      /* roll over */
+               /*
+                * If we are not preempted this will work.  If we are
+                * then we re-reading AR_TSF_U32 does no good as the
+                * low bits will be meaningless.  Likewise reading
+                * L32, U32, U32, then comparing the last two reads
+                * to check for rollover doesn't help if preempted--so
+                * we take this approach as it costs one less PCI
+                * read which can be noticeable when doing things
+                * like timestamping packets in monitor mode.
+                */
+               u32++;
+       }
+       return (((uint64_t) u32) << 32) | ((uint64_t) low2);
+}
+
+/*
+ * Get the current hardware tsf for stamlme.
+ */
+uint32_t
+ar5210GetTsf32(struct ath_hal *ah)
+{
+       return OS_REG_READ(ah, AR_TSF_L32);
+}
+
+/*
+ * Reset the current hardware tsf for stamlme
+ */
+void
+ar5210ResetTsf(struct ath_hal *ah)
+{
+       uint32_t val = OS_REG_READ(ah, AR_BEACON);
+
+       OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
+}
+
+/*
+ * Grab a semi-random value from hardware registers - may not
+ * change often
+ */
+uint32_t
+ar5210GetRandomSeed(struct ath_hal *ah)
+{
+       uint32_t nf;
+
+       nf = (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) >> 19) & 0x1ff;
+       if (nf & 0x100)
+               nf = 0 - ((nf ^ 0x1ff) + 1);
+       return (OS_REG_READ(ah, AR_TSF_U32) ^
+               OS_REG_READ(ah, AR_TSF_L32) ^ nf);
+}
+
+/*
+ * Detect if our card is present
+ */
+HAL_BOOL
+ar5210DetectCardPresent(struct ath_hal *ah)
+{
+       /*
+        * Read the Silicon Revision register and compare that
+        * to what we read at attach time.  If the same, we say
+        * a card/device is present.
+        */
+       return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff));
+}
+
+/*
+ * Update MIB Counters
+ */
+void
+ar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats)
+{
+       stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
+       stats->rts_bad    += OS_REG_READ(ah, AR_RTS_FAIL);
+       stats->fcs_bad    += OS_REG_READ(ah, AR_FCS_FAIL);
+       stats->rts_good   += OS_REG_READ(ah, AR_RTS_OK);
+       stats->beacons    += OS_REG_READ(ah, AR_BEACON_CNT);
+}
+
+HAL_BOOL
+ar5210SetSifsTime(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       if (us > ath_hal_mac_usec(ah, 0x7ff)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
+                   __func__, us);
+               ahp->ah_sifstime = (u_int) -1;  /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS,
+                   ath_hal_mac_clks(ah, us));
+               ahp->ah_sifstime = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5210GetSifsTime(struct ath_hal *ah)
+{
+       u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff;
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+HAL_BOOL
+ar5210SetSlotTime(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
+                   __func__, us);
+               ahp->ah_slottime = (u_int) -1;  /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us));
+               ahp->ah_slottime = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5210GetSlotTime(struct ath_hal *ah)
+{
+       u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff;
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+HAL_BOOL
+ar5210SetAckTimeout(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
+                   __func__, us);
+               ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
+                       AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
+               ahp->ah_acktimeout = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5210GetAckTimeout(struct ath_hal *ah)
+{
+       u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+u_int
+ar5210GetAckCTSRate(struct ath_hal *ah)
+{
+       return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
+}
+
+HAL_BOOL
+ar5210SetAckCTSRate(struct ath_hal *ah, u_int high)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       if (high) {
+               OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
+               ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
+       } else {
+               OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
+               ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5210SetCTSTimeout(struct ath_hal *ah, u_int us)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
+                   __func__, us);
+               ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
+               return AH_FALSE;
+       } else {
+               /* convert to system clocks */
+               OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
+                       AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
+               ahp->ah_ctstimeout = us;
+               return AH_TRUE;
+       }
+}
+
+u_int
+ar5210GetCTSTimeout(struct ath_hal *ah)
+{
+       u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
+       return ath_hal_mac_usec(ah, clks);      /* convert from system clocks */
+}
+
+HAL_BOOL
+ar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
+{
+       /* nothing to do */
+        return AH_TRUE;
+}
+
+void
+ar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
+{
+}
+
+/*
+ * Control Adaptive Noise Immunity Parameters
+ */
+HAL_BOOL
+ar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
+{
+       return AH_FALSE;
+}
+
+void
+ar5210AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, HAL_CHANNEL *chan)
+{
+}
+
+void
+ar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats)
+{
+}
+
+#define        AR_DIAG_SW_DIS_CRYPTO   (AR_DIAG_SW_DIS_ENC | AR_DIAG_SW_DIS_DEC)
+
+HAL_STATUS
+ar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+       uint32_t capability, uint32_t *result)
+{
+
+       switch (type) {
+       case HAL_CAP_CIPHER:            /* cipher handled in hardware */
+               return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP);
+       default:
+               return ath_hal_getcapability(ah, type, capability, result);
+       }
+}
+
+HAL_BOOL
+ar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+       uint32_t capability, uint32_t setting, HAL_STATUS *status)
+{
+
+       switch (type) {
+       case HAL_CAP_DIAG:              /* hardware diagnostic support */
+               /*
+                * NB: could split this up into virtual capabilities,
+                *     (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
+                *     seems worth the additional complexity.
+                */
+#ifdef AH_DEBUG
+               AH_PRIVATE(ah)->ah_diagreg = setting;
+#else
+               AH_PRIVATE(ah)->ah_diagreg = setting & 0x6;     /* ACK+CTS */
+#endif
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+               return AH_TRUE;
+       case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
+               return AH_FALSE;        /* NB: disallow */
+       default:
+               return ath_hal_setcapability(ah, type, capability,
+                       setting, status);
+       }
+}
+
+HAL_BOOL
+ar5210GetDiagState(struct ath_hal *ah, int request,
+       const void *args, uint32_t argsize,
+       void **result, uint32_t *resultsize)
+{
+#ifdef AH_PRIVATE_DIAG
+       uint32_t pcicfg;
+       HAL_BOOL ok;
+
+       switch (request) {
+       case HAL_DIAG_EEPROM:
+               /* XXX */
+               break;
+       case HAL_DIAG_EEREAD:
+               if (argsize != sizeof(uint16_t))
+                       return AH_FALSE;
+               pcicfg = OS_REG_READ(ah, AR_PCICFG);
+               OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL);
+               ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result);
+               OS_REG_WRITE(ah, AR_PCICFG, pcicfg);
+               if (ok)
+                       *resultsize = sizeof(uint16_t);
+               return ok;
+       }
+#endif
+       return ath_hal_getdiagstate(ah, request,
+               args, argsize, result, resultsize);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_phy.c       2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_phy.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5210/ar5210.h"
+
+/* shorthands to compact tables for readability */
+#define        OFDM    IEEE80211_T_OFDM
+#define        TURBO   IEEE80211_T_TURBO
+
+HAL_RATE_TABLE ar5210_11a_table = {
+       8,  /* number of rates */
+       { 0 },
+       {
+/*                                                  short            ctrl  */
+/*                valid                 rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, OFDM,    6000,     0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, OFDM,    9000,     0x0f,    0x00,        18,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,   12000,     0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,   18000,     0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   24000,     0x09,    0x00, (0x80|48),   4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   36000,     0x0d,    0x00,        72,   4, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   48000,     0x08,    0x00,        96,   4, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   54000,     0x0c,    0x00,       108,   4, 0, 0 }
+       },
+};
+
+HAL_RATE_TABLE ar5210_turbo_table = {
+       8,  /* number of rates */
+       { 0 },
+       {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, TURBO,   6000,    0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, TURBO,   9000,    0x0f,    0x00,        18,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, TURBO,  12000,    0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, TURBO,  18000,    0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, TURBO,  24000,    0x09,    0x00, (0x80|48),   4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, TURBO,  36000,    0x0d,    0x00,        72,   4, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, TURBO,  48000,    0x08,    0x00,        96,   4, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, TURBO,  54000,    0x0c,    0x00,       108,   4, 0, 0 }
+       },
+};
+
+#undef OFDM
+#undef TURBO
+
+const HAL_RATE_TABLE *
+ar5210GetRateTable(struct ath_hal *ah, u_int mode)
+{
+       HAL_RATE_TABLE *rt;
+       switch (mode) {
+       case HAL_MODE_11A:
+               rt = &ar5210_11a_table;
+               break;
+       case HAL_MODE_TURBO:
+               rt =  &ar5210_turbo_table;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
+                   __func__, mode);
+               return AH_NULL;
+       }
+       ath_hal_setupratetable(ah, rt);
+       return rt;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_power.c     2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_power.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, set Power Mode of chip to auto/normal.
+ */
+static void
+ar5210SetPowerModeAuto(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV);
+       if (setChip)
+               OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_ALLOW);
+}
+
+/*
+ * Notify Power Mgt is enabled in self-generated frames.
+ * If requested, force chip awake.
+ *
+ * Returns A_OK if chip is awake or successfully forced awake.
+ *
+ * WARNING WARNING WARNING
+ * There is a problem with the chip where sometimes it will not wake up.
+ */
+static HAL_BOOL
+ar5210SetPowerModeAwake(struct ath_hal *ah, int setChip)
+{
+#define        POWER_UP_TIME   2000
+       uint32_t val;
+       int i;
+
+       if (setChip) {
+               OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_WAKE);
+               OS_DELAY(2000); /* Give chip the chance to awake */
+
+               for (i = POWER_UP_TIME / 200; i != 0; i--) {
+                       val = OS_REG_READ(ah, AR_PCICFG);
+                       if ((val & AR_PCICFG_SPWR_DN) == 0)
+                               break;
+                       OS_DELAY(200);
+                       OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE,
+                               AR_SCR_SLE_WAKE);
+               }
+               if (i == 0) {
+#ifdef AH_DEBUG
+                       ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n",
+                               __func__, POWER_UP_TIME/20);
+#endif
+                       return AH_FALSE;
+               }
+       }
+
+       OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV);
+       return AH_TRUE;
+#undef POWER_UP_TIME
+}
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
+static void
+ar5210SetPowerModeSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV);
+       if (setChip)
+               OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP);
+}
+
+HAL_BOOL
+ar5210SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+#ifdef AH_DEBUG
+       static const char* modes[] = {
+               "AWAKE",
+               "FULL-SLEEP",
+               "NETWORK SLEEP",
+               "UNDEFINED"
+       };
+#endif
+       int status = AH_TRUE;
+
+       HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
+               modes[ahp->ah_powerMode], modes[mode],
+               setChip ? "set chip " : "");
+       switch (mode) {
+       case HAL_PM_AWAKE:
+               status = ar5210SetPowerModeAwake(ah, setChip);
+               break;
+       case HAL_PM_FULL_SLEEP:
+               ar5210SetPowerModeSleep(ah, setChip);
+               break;
+       case HAL_PM_NETWORK_SLEEP:
+               ar5210SetPowerModeAuto(ah, setChip);
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n",
+                   __func__, mode);
+               return AH_FALSE;
+       }
+       ahp->ah_powerMode = mode;
+       return status;
+}
+
+HAL_POWER_MODE
+ar5210GetPowerMode(struct ath_hal *ah)
+{
+       /* Just so happens the h/w maps directly to the abstracted value */
+       return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_recv.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_recv.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+#include "ar5210/ar5210desc.h"
+
+/*
+ * Get the RXDP.
+ */
+uint32_t
+ar5210GetRxDP(struct ath_hal *ah)
+{
+       return OS_REG_READ(ah, AR_RXDP);
+}
+
+/*
+ * Set the RxDP.
+ */
+void
+ar5210SetRxDP(struct ath_hal *ah, uint32_t rxdp)
+{
+       OS_REG_WRITE(ah, AR_RXDP, rxdp);
+}
+
+
+/*
+ * Set Receive Enable bits.
+ */
+void
+ar5210EnableReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+/*
+ * Stop Receive at the DMA engine
+ */
+HAL_BOOL
+ar5210StopDmaReceive(struct ath_hal *ah)
+{
+       int i;
+
+       OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);     /* Set receive disable bit */
+       for (i = 0; i < 1000; i++) {
+               if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
+                       return AH_TRUE;
+               OS_DELAY(10);
+       }
+#ifdef AH_DEBUG
+       ath_hal_printf(ah, "ar5210: dma receive failed to stop in 10ms\n");
+       ath_hal_printf(ah, "AR_CR=0x%x\n", OS_REG_READ(ah, AR_CR));
+       ath_hal_printf(ah, "AR_DIAG_SW=0x%x\n", OS_REG_READ(ah, AR_DIAG_SW));
+#endif
+       return AH_FALSE;
+}
+
+/*
+ * Start Transmit at the PCU engine (unpause receive)
+ */
+void
+ar5210StartPcuReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_DIAG_SW,
+               OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX));
+}
+
+/*
+ * Stop Transmit at the PCU engine (pause receive)
+ */
+void
+ar5210StopPcuReceive(struct ath_hal *ah)
+{
+       OS_REG_WRITE(ah, AR_DIAG_SW,
+               OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX);
+}
+
+/*
+ * Set multicast filter 0 (lower 32-bits)
+ *                        filter 1 (upper 32-bits)
+ */
+void
+ar5210SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1)
+{
+       OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+       OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);
+}
+
+/*
+ * Clear multicast filter by index
+ */
+HAL_BOOL
+ar5210ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
+{
+       uint32_t val;
+
+       if (ix >= 64)
+               return AH_FALSE;
+       if (ix >= 32) {
+               val = OS_REG_READ(ah, AR_MCAST_FIL1);
+               OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32))));
+       } else {
+               val = OS_REG_READ(ah, AR_MCAST_FIL0);
+               OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<<ix)));
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Set multicast filter by index
+ */
+HAL_BOOL
+ar5210SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
+{
+       uint32_t val;
+
+       if (ix >= 64)
+               return AH_FALSE;
+       if (ix >= 32) {
+               val = OS_REG_READ(ah, AR_MCAST_FIL1);
+               OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32))));
+       } else {
+               val = OS_REG_READ(ah, AR_MCAST_FIL0);
+               OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<<ix)));
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Return the receive packet filter.
+ */
+uint32_t
+ar5210GetRxFilter(struct ath_hal *ah)
+{
+       /* XXX can't be sure if promiscuous mode is set because of PHYRADAR */
+       return OS_REG_READ(ah, AR_RX_FILTER);
+}
+
+/*
+ * Turn off/on bits in the receive packet filter.
+ */
+void
+ar5210SetRxFilter(struct ath_hal *ah, uint32_t bits)
+{
+       if (bits & HAL_RX_FILTER_PHYRADAR) {
+               /* must enable promiscuous mode to get radar */
+               bits = (bits &~ HAL_RX_FILTER_PHYRADAR) | AR_RX_FILTER_PROMISCUOUS;
+       }
+       OS_REG_WRITE(ah, AR_RX_FILTER, bits);
+}
+
+/*
+ * Initialize RX descriptor, by clearing the status and clearing
+ * the size.  This is not strictly HW dependent, but we want the
+ * control and status words to be opaque above the hal.
+ */
+HAL_BOOL
+ar5210SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       uint32_t size, u_int flags)
+{
+       struct ar5210_desc *ads = AR5210DESC(ds);
+
+       (void) flags;
+
+       ads->ds_ctl0 = 0;
+       ads->ds_ctl1 = size & AR_BufLen;
+       if (ads->ds_ctl1 != size) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n",
+                   __func__, size);
+               return AH_FALSE;
+       }
+       if (flags & HAL_RXDESC_INTREQ)
+               ads->ds_ctl1 |= AR_RxInterReq;
+       ads->ds_status0 = ads->ds_status1 = 0;
+
+       return AH_TRUE;
+}
+
+/*
+ * Process an RX descriptor, and return the status to the caller.
+ * Copy some hardware specific items into the software portion
+ * of the descriptor.
+ *
+ * NB: the caller is responsible for validating the memory contents
+ *     of the descriptor (e.g. flushing any cached copy).
+ */
+HAL_STATUS
+ar5210ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       uint32_t pa, struct ath_desc *nds, uint64_t tsf,
+       struct ath_rx_status *rs)
+{
+       struct ar5210_desc *ads = AR5210DESC(ds);
+       struct ar5210_desc *ands = AR5210DESC(nds);
+       uint32_t now, rstamp;
+
+       if ((ads->ds_status1 & AR_Done) == 0)
+               return HAL_EINPROGRESS;
+       /*
+        * Given the use of a self-linked tail be very sure that the hw is
+        * done with this descriptor; the hw may have done this descriptor
+        * once and picked it up again...make sure the hw has moved on.
+        */
+       if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa)
+               return HAL_EINPROGRESS;
+
+       rs->rs_datalen = ads->ds_status0 & AR_DataLen;
+       rstamp = MS(ads->ds_status1, AR_RcvTimestamp);
+       /*
+        * Convert timestamp.  The value in the
+        * descriptor is bits [10..22] of the TSF.
+        */
+       now = (OS_REG_READ(ah, AR_TSF_L32) >> 10) & 0xffff;
+       if ((now & 0x1fff) < rstamp)
+               rstamp |= (now - 0x2000) & 0xffff;
+       else
+               rstamp |= now;
+       /* NB: keep only 15 bits for consistency w/ other chips */
+       rs->rs_tstamp = rstamp & 0x7fff;
+       rs->rs_status = 0;
+       if ((ads->ds_status1 & AR_FrmRcvOK) == 0) {
+               if (ads->ds_status1 & AR_CRCErr)
+                       rs->rs_status |= HAL_RXERR_CRC;
+               else if (ads->ds_status1 & AR_DecryptCRCErr)
+                       rs->rs_status |= HAL_RXERR_DECRYPT;
+               else if (ads->ds_status1 & AR_FIFOOverrun)
+                       rs->rs_status |= HAL_RXERR_FIFO;
+               else {
+                       rs->rs_status |= HAL_RXERR_PHY;
+                       rs->rs_phyerr =
+                               (ads->ds_status1 & AR_PHYErr) >> AR_PHYErr_S;
+               }
+       }
+       /* XXX what about KeyCacheMiss? */
+       rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength);
+       if (ads->ds_status1 & AR_KeyIdxValid)
+               rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx);
+       else
+               rs->rs_keyix = HAL_RXKEYIX_INVALID;
+       /* NB: caller expected to do rate table mapping */
+       rs->rs_rate = MS(ads->ds_status0, AR_RcvRate);
+       rs->rs_antenna  = (ads->ds_status0 & AR_RcvAntenna) ? 1 : 0;
+       rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0;
+
+       return HAL_OK;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_reset.c     2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,1004 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_reset.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+#include "ar5210/ar5210phy.h"
+
+#include "ah_eeprom_v1.h"
+
+typedef struct {
+       uint32_t        Offset;
+       uint32_t        Value;
+} REGISTER_VAL;
+
+static const REGISTER_VAL ar5k0007_init[] = {
+#include "ar5210/ar5k_0007.ini"
+};
+
+/* Default Power Settings for channels outside of EEPROM range */
+static const uint8_t ar5k0007_pwrSettings[17] = {
+/*     gain delta                      pc dac */
+/* 54  48  36  24  18  12   9   54  48  36  24  18  12   9   6  ob  db   */
+    9,  9,  0,  0,  0,  0,  0,   2,  2,  6,  6,  6,  6,  6,  6,  2,  2
+};
+
+/*
+ * The delay, in usecs, between writing AR_RC with a reset
+ * request and waiting for the chip to settle.  If this is
+ * too short then the chip does not come out of sleep state.
+ * Note this value was empirically derived and may be dependent
+ * on the host machine (don't know--the problem was identified
+ * on an IBM 570e laptop; 10us delays worked on other systems).
+ */
+#define        AR_RC_SETTLE_TIME       20000
+
+static HAL_BOOL ar5210SetResetReg(struct ath_hal *,
+               uint32_t resetMask, u_int waitTime);
+static HAL_BOOL ar5210SetChannel(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+static void ar5210SetOperatingMode(struct ath_hal *, int opmode);
+
+/*
+ * Places the device in and out of reset and then places sane
+ * values in the registers based on EEPROM config, initialization
+ * vectors (as determined by the mode), and station configuration
+ *
+ * bChannelChange is used to preserve DMA/PCU registers across
+ * a HW Reset during channel change.
+ */
+HAL_BOOL
+ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+       HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
+{
+#define        N(a)    (sizeof (a) /sizeof (a[0]))
+#define        FAIL(_code)     do { ecode = _code; goto bad; } while (0)
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;
+       HAL_CHANNEL_INTERNAL *ichan;
+       HAL_STATUS ecode;
+       uint32_t ledstate;
+       int i, q;
+
+       HALDEBUG(ah, HAL_DEBUG_RESET,
+           "%s: opmode %u channel %u/0x%x %s channel\n", __func__,
+           opmode, chan->channel, chan->channelFlags,
+           bChannelChange ? "change" : "same");
+
+       if ((chan->channelFlags & CHANNEL_5GHZ) == 0) {
+               /* Only 11a mode */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: channel not 5Ghz\n", __func__);
+               FAIL(HAL_EINVAL);
+       }
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       switch (opmode) {
+       case HAL_M_STA:
+       case HAL_M_IBSS:
+       case HAL_M_HOSTAP:
+       case HAL_M_MONITOR:
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
+                   __func__, opmode);
+               FAIL(HAL_EINVAL);
+               break;
+       }
+
+       ledstate = OS_REG_READ(ah, AR_PCICFG) &
+               (AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT);
+
+       if (!ar5210ChipReset(ah, chan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",
+                   __func__);
+               FAIL(HAL_EIO);
+       }
+
+       OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
+       OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4));
+       ar5210SetOperatingMode(ah, opmode);
+
+       switch (opmode) {
+       case HAL_M_HOSTAP:
+               OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);
+               OS_REG_WRITE(ah, AR_PCICFG,
+                       AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL);
+               break;
+       case HAL_M_IBSS:
+               OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG | AR_BCR_BCMD);
+               OS_REG_WRITE(ah, AR_PCICFG,
+                       AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL);
+               break;
+       case HAL_M_STA:
+               OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);
+               OS_REG_WRITE(ah, AR_PCICFG,
+                       AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL);
+               break;
+       case HAL_M_MONITOR:
+               OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);
+               OS_REG_WRITE(ah, AR_PCICFG,
+                       AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL);
+               break;
+       }
+
+       /* Restore previous led state */
+       OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate);
+
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
+
+       OS_REG_WRITE(ah, AR_TXDP0, 0);
+       OS_REG_WRITE(ah, AR_TXDP1, 0);
+       OS_REG_WRITE(ah, AR_RXDP, 0);
+
+       /*
+        * Initialize interrupt state.
+        */
+       (void) OS_REG_READ(ah, AR_ISR);         /* cleared on read */
+       OS_REG_WRITE(ah, AR_IMR, 0);
+       OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+       ahp->ah_maskReg = 0;
+
+       (void) OS_REG_READ(ah, AR_BSR);         /* cleared on read */
+       OS_REG_WRITE(ah, AR_TXCFG, AR_DMASIZE_128B);
+       OS_REG_WRITE(ah, AR_RXCFG, AR_DMASIZE_128B);
+
+       OS_REG_WRITE(ah, AR_TOPS, 8);           /* timeout prescale */
+       OS_REG_WRITE(ah, AR_RXNOFRM, 8);        /* RX no frame timeout */
+       OS_REG_WRITE(ah, AR_RPGTO, 0);          /* RX frame gap timeout */
+       OS_REG_WRITE(ah, AR_TXNOFRM, 0);        /* TX no frame timeout */
+
+       OS_REG_WRITE(ah, AR_SFR, 0);
+       OS_REG_WRITE(ah, AR_MIBC, 0);           /* unfreeze ctrs + clr state */
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+       OS_REG_WRITE(ah, AR_CFP_DUR, 0);
+
+       ar5210SetRxFilter(ah, 0);               /* nothing for now */
+       OS_REG_WRITE(ah, AR_MCAST_FIL0, 0);     /* multicast filter */
+       OS_REG_WRITE(ah, AR_MCAST_FIL1, 0);     /* XXX was 2 */
+
+       OS_REG_WRITE(ah, AR_TX_MASK0, 0);
+       OS_REG_WRITE(ah, AR_TX_MASK1, 0);
+       OS_REG_WRITE(ah, AR_CLR_TMASK, 1);
+       OS_REG_WRITE(ah, AR_TRIG_LEV, 1);       /* minimum */
+
+       OS_REG_WRITE(ah, AR_DIAG_SW, 0);
+
+       OS_REG_WRITE(ah, AR_CFP_PERIOD, 0);
+       OS_REG_WRITE(ah, AR_TIMER0, 0);         /* next beacon time */
+       OS_REG_WRITE(ah, AR_TSF_L32, 0);        /* local clock */
+       OS_REG_WRITE(ah, AR_TIMER1, ~0);        /* next DMA beacon alert */
+       OS_REG_WRITE(ah, AR_TIMER2, ~0);        /* next SW beacon alert */
+       OS_REG_WRITE(ah, AR_TIMER3, 1);         /* next ATIM window */
+
+       /* Write the INI values for PHYreg initialization */
+       for (i = 0; i < N(ar5k0007_init); i++) {
+               uint32_t reg = ar5k0007_init[i].Offset;
+               /* On channel change, don't reset the PCU registers */
+               if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000)))
+                       OS_REG_WRITE(ah, reg, ar5k0007_init[i].Value);
+       }
+
+       /* Setup the transmit power values for cards since 0x0[0-2]05 */
+       if (!ar5210SetTransmitPower(ah, chan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       OS_REG_WRITE(ah, AR_PHY(10),
+               (OS_REG_READ(ah, AR_PHY(10)) & 0xFFFF00FF) |
+               (ee->ee_xlnaOn << 8));
+       OS_REG_WRITE(ah, AR_PHY(13),
+               (ee->ee_xpaOff << 24) | (ee->ee_xpaOff << 16) |
+               (ee->ee_xpaOn << 8) | ee->ee_xpaOn);
+       OS_REG_WRITE(ah, AR_PHY(17),
+               (OS_REG_READ(ah, AR_PHY(17)) & 0xFFFFC07F) |
+               ((ee->ee_antenna >> 1) & 0x3F80));
+       OS_REG_WRITE(ah, AR_PHY(18),
+               (OS_REG_READ(ah, AR_PHY(18)) & 0xFFFC0FFF) |
+               ((ee->ee_antenna << 10) & 0x3F000));
+       OS_REG_WRITE(ah, AR_PHY(25),
+               (OS_REG_READ(ah, AR_PHY(25)) & 0xFFF80FFF) |
+               ((ee->ee_thresh62 << 12) & 0x7F000));
+       OS_REG_WRITE(ah, AR_PHY(68),
+               (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) |
+               (ee->ee_antenna & 0x3));
+
+       if (!ar5210SetChannel(ah, ichan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n",
+                   __func__);
+               FAIL(HAL_EIO);
+       }
+       if (bChannelChange) {
+               if (!(ichan->privFlags & CHANNEL_DFS))
+                       ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+               chan->channelFlags = ichan->channelFlags;
+               chan->privFlags = ichan->privFlags;
+       }
+
+       /* Activate the PHY */
+       OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ENABLE);
+
+       OS_DELAY(1000);         /* Wait a bit (1 msec) */
+
+       /* calibrate the HW and poll the bit going to 0 for completion */
+       OS_REG_WRITE(ah, AR_PHY_AGCCTL,
+               OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL);
+       (void) ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0);
+
+       /* Perform noise floor calibration and set status */
+       if (!ar5210CalNoiseFloor(ah, ichan)) {
+               chan->channelFlags |= CHANNEL_CW_INT;
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: noise floor calibration failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       for (q = 0; q < HAL_NUM_TX_QUEUES; q++)
+               ar5210ResetTxQueue(ah, q);
+
+       if (AH_PRIVATE(ah)->ah_rfkillEnabled)
+               ar5210EnableRfKill(ah);
+
+       /*
+        * Writing to AR_BEACON will start timers. Hence it should be
+        * the last register to be written. Do not reset tsf, do not
+        * enable beacons at this point, but preserve other values
+        * like beaconInterval.
+        */
+       OS_REG_WRITE(ah, AR_BEACON,
+               (OS_REG_READ(ah, AR_BEACON) &
+                       ~(AR_BEACON_EN | AR_BEACON_RESET_TSF)));
+
+       /* Restore user-specified slot time and timeouts */
+       if (ahp->ah_sifstime != (u_int) -1)
+               ar5210SetSifsTime(ah, ahp->ah_sifstime);
+       if (ahp->ah_slottime != (u_int) -1)
+               ar5210SetSlotTime(ah, ahp->ah_slottime);
+       if (ahp->ah_acktimeout != (u_int) -1)
+               ar5210SetAckTimeout(ah, ahp->ah_acktimeout);
+       if (ahp->ah_ctstimeout != (u_int) -1)
+               ar5210SetCTSTimeout(ah, ahp->ah_ctstimeout);
+       if (AH_PRIVATE(ah)->ah_diagreg != 0)
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+
+       AH_PRIVATE(ah)->ah_opmode = opmode;     /* record operating mode */
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
+
+       return AH_TRUE;
+bad:
+       if (*status)
+               *status = ecode;
+       return AH_FALSE;
+#undef FAIL
+#undef N
+}
+
+static void
+ar5210SetOperatingMode(struct ath_hal *ah, int opmode)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       uint32_t val;
+
+       val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff;
+       switch (opmode) {
+       case HAL_M_HOSTAP:
+               OS_REG_WRITE(ah, AR_STA_ID1, val
+                       | AR_STA_ID1_AP
+                       | AR_STA_ID1_NO_PSPOLL
+                       | AR_STA_ID1_DESC_ANTENNA
+                       | ahp->ah_staId1Defaults);
+               break;
+       case HAL_M_IBSS:
+               OS_REG_WRITE(ah, AR_STA_ID1, val
+                       | AR_STA_ID1_ADHOC
+                       | AR_STA_ID1_NO_PSPOLL
+                       | AR_STA_ID1_DESC_ANTENNA
+                       | ahp->ah_staId1Defaults);
+               break;
+       case HAL_M_STA:
+               OS_REG_WRITE(ah, AR_STA_ID1, val
+                       | AR_STA_ID1_NO_PSPOLL
+                       | AR_STA_ID1_PWR_SV
+                       | ahp->ah_staId1Defaults);
+               break;
+       case HAL_M_MONITOR:
+               OS_REG_WRITE(ah, AR_STA_ID1, val
+                       | AR_STA_ID1_NO_PSPOLL
+                       | ahp->ah_staId1Defaults);
+               break;
+       }
+}
+
+void
+ar5210SetPCUConfig(struct ath_hal *ah)
+{
+       ar5210SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
+}
+
+/*
+ * Places the PHY and Radio chips into reset.  A full reset
+ * must be called to leave this state.  The PCI/MAC/PCU are
+ * not placed into reset as we must receive interrupt to
+ * re-enable the hardware.
+ */
+HAL_BOOL
+ar5210PhyDisable(struct ath_hal *ah)
+{
+       return ar5210SetResetReg(ah, AR_RC_RPHY, 10);
+}
+
+/*
+ * Places all of hardware into reset
+ */
+HAL_BOOL
+ar5210Disable(struct ath_hal *ah)
+{
+#define        AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC)
+       if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+
+       /*
+        * Reset the HW - PCI must be reset after the rest of the
+        * device has been reset
+        */
+       if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME))
+               return AH_FALSE;
+       OS_DELAY(1000);
+       (void) ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME);
+       OS_DELAY(2100);   /* 8245 @ 96Mhz hangs with 2000us. */
+
+       return AH_TRUE;
+#undef AR_RC_HW
+}
+
+/*
+ * Places the hardware into reset and then pulls it out of reset
+ */
+HAL_BOOL
+ar5210ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+#define        AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC)
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s turbo %s\n", __func__,
+               chan && IS_CHAN_TURBO(chan) ? "enabled" : "disabled");
+
+       if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+
+       /* Place chip in turbo before reset to cleanly reset clocks */
+       OS_REG_WRITE(ah, AR_PHY_FRCTL,
+               chan && IS_CHAN_TURBO(chan) ? AR_PHY_TURBO_MODE : 0);
+
+       /*
+        * Reset the HW.
+        * PCI must be reset after the rest of the device has been reset.
+        */
+       if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME))
+               return AH_FALSE;
+       OS_DELAY(1000);
+       if (!ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME))
+               return AH_FALSE;
+       OS_DELAY(2100);   /* 8245 @ 96Mhz hangs with 2000us. */
+
+       /*
+        * Bring out of sleep mode (AGAIN)
+        *
+        * WARNING WARNING WARNING
+        *
+        * There is a problem with the chip where it doesn't always indicate
+        * that it's awake, so initializePowerUp() will fail.
+        */
+       if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+
+       /* Clear warm reset reg */
+       return ar5210SetResetReg(ah, 0, 10);
+#undef AR_RC_HW
+}
+
+enum {
+       FIRPWR_M        = 0x03fc0000,
+       FIRPWR_S        = 18,
+       KCOARSEHIGH_M   = 0x003f8000,
+       KCOARSEHIGH_S   = 15,
+       KCOARSELOW_M    = 0x00007f80,
+       KCOARSELOW_S    = 7,
+       ADCSAT_ICOUNT_M = 0x0001f800,
+       ADCSAT_ICOUNT_S = 11,
+       ADCSAT_THRESH_M = 0x000007e0,
+       ADCSAT_THRESH_S = 5
+};
+
+/*
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+HAL_BOOL
+ar5210PerCalibrationN(struct ath_hal *ah,  HAL_CHANNEL *chan, u_int chainMask,
+       HAL_BOOL longCal, HAL_BOOL *isCalDone)
+{
+       uint32_t regBeacon;
+       uint32_t reg9858, reg985c, reg9868;
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               return AH_FALSE;
+       }
+       /* Disable tx and rx */
+       OS_REG_WRITE(ah, AR_DIAG_SW,
+               OS_REG_READ(ah, AR_DIAG_SW) | (AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX));
+
+       /* Disable Beacon Enable */
+       regBeacon = OS_REG_READ(ah, AR_BEACON);
+       OS_REG_WRITE(ah, AR_BEACON, regBeacon & ~AR_BEACON_EN);
+
+       /* Delay 4ms to ensure that all tx and rx activity has ceased */
+       OS_DELAY(4000);
+
+       /* Disable AGC to radio traffic */
+       OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000);
+       /* Wait for the AGC traffic to cease. */
+       OS_DELAY(10);
+
+       /* Change Channel to relock synth */
+       if (!ar5210SetChannel(ah, ichan))
+               return AH_FALSE;
+
+       /* wait for the synthesizer lock to stabilize */
+       OS_DELAY(1000);
+
+       /* Re-enable AGC to radio traffic */
+       OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000));
+
+       /*
+        * Configure the AGC so that it is highly unlikely (if not
+        * impossible) for it to send any gain changes to the analog
+        * chip.  We store off the current values so that they can
+        * be rewritten below. Setting the following values:
+        * firpwr        = -1
+        * Kcoursehigh   = -1
+        * Kcourselow    = -127
+        * ADCsat_icount = 2
+        * ADCsat_thresh = 12
+        */
+       reg9858 = OS_REG_READ(ah, 0x9858);
+       reg985c = OS_REG_READ(ah, 0x985c);
+       reg9868 = OS_REG_READ(ah, 0x9868);
+
+       OS_REG_WRITE(ah, 0x9858, (reg9858 & ~FIRPWR_M) |
+                                        ((-1 << FIRPWR_S) & FIRPWR_M));
+       OS_REG_WRITE(ah, 0x985c,
+                (reg985c & ~(KCOARSEHIGH_M | KCOARSELOW_M)) |
+                ((-1 << KCOARSEHIGH_S) & KCOARSEHIGH_M) |
+                ((-127 << KCOARSELOW_S) & KCOARSELOW_M));
+       OS_REG_WRITE(ah, 0x9868,
+                (reg9868 & ~(ADCSAT_ICOUNT_M | ADCSAT_THRESH_M)) |
+                ((2 << ADCSAT_ICOUNT_S) & ADCSAT_ICOUNT_M) |
+                ((12 << ADCSAT_THRESH_S) & ADCSAT_THRESH_M));
+
+       /* Wait for AGC changes to be enacted */
+       OS_DELAY(20);
+
+       /*
+        * We disable RF mix/gain stages for the PGA to avoid a
+        * race condition that will occur with receiving a frame
+        * and performing the AGC calibration.  This will be
+        * re-enabled at the end of offset cal.  We turn off AGC
+        * writes during this write as it will go over the analog bus.
+        */
+       OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000);
+       OS_DELAY(10);            /* wait for the AGC traffic to cease */
+       OS_REG_WRITE(ah, 0x98D4, 0x21);
+       OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000));
+
+       /* wait to make sure that additional AGC traffic has quiesced */
+       OS_DELAY(1000);
+
+       /* AGC calibration (this was added to make the NF threshold check work) */
+       OS_REG_WRITE(ah, AR_PHY_AGCCTL,
+                OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL);
+       if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: AGC calibration timeout\n",
+                   __func__);
+       }
+
+       /* Rewrite our AGC values we stored off earlier (return AGC to normal operation) */
+       OS_REG_WRITE(ah, 0x9858, reg9858);
+       OS_REG_WRITE(ah, 0x985c, reg985c);
+       OS_REG_WRITE(ah, 0x9868, reg9868);
+
+       /* Perform noise floor and set status */
+       if (!ar5210CalNoiseFloor(ah, ichan)) {
+               /*
+                * Delay 5ms before retrying the noise floor -
+                * just to make sure.  We're in an error
+                * condition here
+                */
+               HALDEBUG(ah, HAL_DEBUG_NFCAL | HAL_DEBUG_PERCAL,
+                   "%s: Performing 2nd Noise Cal\n", __func__);
+               OS_DELAY(5000);
+               if (!ar5210CalNoiseFloor(ah, ichan))
+                       chan->channelFlags |= CHANNEL_CW_INT;
+       }
+
+       /* Clear tx and rx disable bit */
+       OS_REG_WRITE(ah, AR_DIAG_SW,
+                OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX));
+
+       /* Re-enable Beacons */
+       OS_REG_WRITE(ah, AR_BEACON, regBeacon);
+
+       *isCalDone = AH_TRUE;
+
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5210PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone)
+{
+       return ar5210PerCalibrationN(ah,  chan, 0x1, AH_TRUE, isIQdone);
+}
+
+HAL_BOOL
+ar5210ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       return AH_TRUE;
+}
+
+/*
+ * Writes the given reset bit mask into the reset register
+ */
+static HAL_BOOL
+ar5210SetResetReg(struct ath_hal *ah, uint32_t resetMask, u_int waitTime)
+{
+       uint32_t mask = resetMask ? resetMask : ~0;
+       HAL_BOOL rt;
+
+       OS_REG_WRITE(ah, AR_RC, resetMask);
+       /* need to wait at least 128 clocks when reseting PCI before read */
+       OS_DELAY(waitTime);
+
+       resetMask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC;
+       mask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC;
+       rt = ath_hal_wait(ah, AR_RC, mask, resetMask);
+        if ((resetMask & AR_RC_RMAC) == 0) {
+               if (isBigEndian()) {
+                       /*
+                        * Set CFG, little-endian for register
+                        * and descriptor accesses.
+                        */
+                       mask = INIT_CONFIG_STATUS |
+                               AR_CFG_SWTD | AR_CFG_SWRD | AR_CFG_SWRG;
+                       OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));
+               } else
+                       OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
+       }
+       return rt;
+}
+
+
+/*
+ * Returns: the pcdac value
+ */
+static uint8_t
+getPcdac(struct ath_hal *ah, const struct tpcMap *pRD, uint8_t dBm)
+{
+       int32_t  i;
+       int useNextEntry = AH_FALSE;
+       uint32_t interp;
+
+       for (i = AR_TP_SCALING_ENTRIES - 1; i >= 0; i--) {
+               /* Check for exact entry */
+               if (dBm == AR_I2DBM(i)) {
+                       if (pRD->pcdac[i] != 63)
+                               return pRD->pcdac[i];
+                       useNextEntry = AH_TRUE;
+               } else if (dBm + 1 == AR_I2DBM(i) && i > 0) {
+                       /* Interpolate for between entry with a logish scale */
+                       if (pRD->pcdac[i] != 63 && pRD->pcdac[i-1] != 63) {
+                               interp = (350 * (pRD->pcdac[i] - pRD->pcdac[i-1])) + 999;
+                               interp = (interp / 1000) + pRD->pcdac[i-1];
+                               return interp;
+                       }
+                       useNextEntry = AH_TRUE;
+               } else if (useNextEntry == AH_TRUE) {
+                       /* Grab the next lowest */
+                       if (pRD->pcdac[i] != 63)
+                               return pRD->pcdac[i];
+               }
+       }
+
+       /* Return the lowest Entry if we haven't returned */
+       for (i = 0; i < AR_TP_SCALING_ENTRIES; i++)
+               if (pRD->pcdac[i] != 63)
+                       return pRD->pcdac[i];
+
+       /* No value to return from table */
+#ifdef AH_DEBUG
+       ath_hal_printf(ah, "%s: empty transmit power table?\n", __func__);
+#endif
+       return 1;
+}
+
+/*
+ * Find or interpolates the gainF value from the table ptr.
+ */
+static uint8_t
+getGainF(struct ath_hal *ah, const struct tpcMap *pRD,
+       uint8_t pcdac, uint8_t *dBm)
+{
+       uint32_t interp;
+       int low, high, i;
+
+       low = high = -1;
+
+       for (i = 0; i < AR_TP_SCALING_ENTRIES; i++) {
+               if(pRD->pcdac[i] == 63)
+                       continue;
+               if (pcdac == pRD->pcdac[i]) {
+                       *dBm = AR_I2DBM(i);
+                       return pRD->gainF[i];  /* Exact Match */
+               }
+               if (pcdac > pRD->pcdac[i])
+                       low = i;
+               if (pcdac < pRD->pcdac[i]) {
+                       high = i;
+                       if (low == -1) {
+                               *dBm = AR_I2DBM(i);
+                               /* PCDAC is lower than lowest setting */
+                               return pRD->gainF[i];
+                       }
+                       break;
+               }
+       }
+       if (i >= AR_TP_SCALING_ENTRIES && low == -1) {
+               /* No settings were found */
+#ifdef AH_DEBUG
+               ath_hal_printf(ah,
+                       "%s: no valid entries in the pcdac table: %d\n",
+                       __func__, pcdac);
+#endif
+               return 63;
+       }
+       if (i >= AR_TP_SCALING_ENTRIES) {
+               /* PCDAC setting was above the max setting in the table */
+               *dBm = AR_I2DBM(low);
+               return pRD->gainF[low];
+       }
+       /* Only exact if table has no missing entries */
+       *dBm = (low + high) + 3;
+
+       /*
+        * Perform interpolation between low and high values to find gainF
+        * linearly scale the pcdac between low and high
+        */
+       interp = ((pcdac - pRD->pcdac[low]) * 1000) /
+                 (pRD->pcdac[high] - pRD->pcdac[low]);
+       /*
+        * Multiply the scale ratio by the gainF difference
+        * (plus a rnd up factor)
+        */
+       interp = ((interp * (pRD->gainF[high] - pRD->gainF[low])) + 999) / 1000;
+
+       /* Add ratioed gain_f to low gain_f value */
+       return interp + pRD->gainF[low];
+}
+
+HAL_BOOL
+ar5210SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
+{
+       AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, AR5210_MAX_RATE_POWER);
+       /* XXX flush to h/w */
+       return AH_TRUE;
+}
+
+/*
+ * Get TXPower values and set them in the radio
+ */
+static HAL_BOOL
+setupPowerSettings(struct ath_hal *ah, HAL_CHANNEL *chan, uint8_t cp[17])
+{
+       const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint8_t gainFRD, gainF36, gainF48, gainF54;
+       uint8_t dBmRD = 0, dBm36 = 0, dBm48 = 0, dBm54 = 0, dontcare;
+       uint32_t rd, group;
+       const struct tpcMap  *pRD;
+
+       /* Set OB/DB Values regardless of channel */
+       cp[15] = (ee->ee_biasCurrents >> 4) & 0x7;
+       cp[16] = ee->ee_biasCurrents & 0x7;
+
+       if (chan->channel < 5170 || chan->channel > 5320) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u\n",
+                   __func__, chan->channel);
+               return AH_FALSE;
+       }
+
+       HALASSERT(ee->ee_version >= AR_EEPROM_VER1 &&
+           ee->ee_version < AR_EEPROM_VER3);
+
+       /* Match regulatory domain */
+       for (rd = 0; rd < AR_REG_DOMAINS_MAX; rd++)
+               if (AH_PRIVATE(ah)->ah_currentRD == ee->ee_regDomain[rd])
+                       break;
+       if (rd == AR_REG_DOMAINS_MAX) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah,
+                       "%s: no calibrated regulatory domain matches the "
+                       "current regularly domain (0x%0x)\n", __func__,
+                       AH_PRIVATE(ah)->ah_currentRD);
+#endif
+               return AH_FALSE;
+       }
+       group = ((chan->channel - 5170) / 10);
+
+       if (group > 11) {
+               /* Pull 5.29 into the 5.27 group */
+               group--;
+       }
+
+       /* Integer divide will set group from 0 to 4 */
+       group = group / 3;
+       pRD   = &ee->ee_tpc[group];
+
+       /* Set PC DAC Values */
+       cp[14] = pRD->regdmn[rd];
+       cp[9]  = AH_MIN(pRD->regdmn[rd], pRD->rate36);
+       cp[8]  = AH_MIN(pRD->regdmn[rd], pRD->rate48);
+       cp[7]  = AH_MIN(pRD->regdmn[rd], pRD->rate54);
+
+       /* Find Corresponding gainF values for RD, 36, 48, 54 */
+       gainFRD = getGainF(ah, pRD, pRD->regdmn[rd], &dBmRD);
+       gainF36 = getGainF(ah, pRD, cp[9], &dBm36);
+       gainF48 = getGainF(ah, pRD, cp[8], &dBm48);
+       gainF54 = getGainF(ah, pRD, cp[7], &dBm54);
+
+       /* Power Scale if requested */
+       if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) {
+               static const uint16_t tpcScaleReductionTable[5] =
+                       { 0, 3, 6, 9, AR5210_MAX_RATE_POWER };
+               uint16_t tpScale;
+
+               tpScale = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale];
+               if (dBmRD < tpScale+3)
+                       dBmRD = 3;              /* min */
+               else
+                       dBmRD -= tpScale;
+               cp[14]  = getPcdac(ah, pRD, dBmRD);
+               gainFRD = getGainF(ah, pRD, cp[14], &dontcare);
+               dBm36   = AH_MIN(dBm36, dBmRD);
+               cp[9]   = getPcdac(ah, pRD, dBm36);
+               gainF36 = getGainF(ah, pRD, cp[9], &dontcare);
+               dBm48   = AH_MIN(dBm48, dBmRD);
+               cp[8]   = getPcdac(ah, pRD, dBm48);
+               gainF48 = getGainF(ah, pRD, cp[8], &dontcare);
+               dBm54   = AH_MIN(dBm54, dBmRD);
+               cp[7]   = getPcdac(ah, pRD, dBm54);
+               gainF54 = getGainF(ah, pRD, cp[7], &dontcare);
+       }
+       /* Record current dBm at rate 6 */
+       AH_PRIVATE(ah)->ah_maxPowerLevel = 2*dBmRD;
+
+       cp[13] = cp[12] = cp[11] = cp[10] = cp[14];
+
+       /* Set GainF Values */
+       cp[0] = gainFRD - gainF54;
+       cp[1] = gainFRD - gainF48;
+       cp[2] = gainFRD - gainF36;
+       /* 9, 12, 18, 24 have no gain_delta from 6 */
+       cp[3] = cp[4] = cp[5] = cp[6] = 0;
+       return AH_TRUE;
+}
+
+/*
+ * Places the device in and out of reset and then places sane
+ * values in the registers based on EEPROM config, initialization
+ * vectors (as determined by the mode), and station configuration
+ */
+HAL_BOOL
+ar5210SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+       static const uint32_t pwr_regs_start[17] = {
+               0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xf0000000,
+               0xcc000000, 0x00000000, 0x00000000,
+               0x00000000, 0x0a000000, 0x000000e2,
+               0x0a000020, 0x01000002, 0x01000018,
+               0x40000000, 0x00000418
+       };
+       uint16_t i;
+       uint8_t cp[sizeof(ar5k0007_pwrSettings)];
+       uint32_t pwr_regs[17];
+
+       OS_MEMCPY(pwr_regs, pwr_regs_start, sizeof(pwr_regs));
+       OS_MEMCPY(cp, ar5k0007_pwrSettings, sizeof(cp));
+
+       /* Check the EEPROM tx power calibration settings */
+       if (!setupPowerSettings(ah, chan, cp)) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s: unable to setup power settings\n",
+                       __func__);
+#endif
+               return AH_FALSE;
+       }
+       if (cp[15] < 1 || cp[15] > 5) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s: OB out of range (%u)\n",
+                       __func__, cp[15]);
+#endif
+               return AH_FALSE;
+       }
+       if (cp[16] < 1 || cp[16] > 5) {
+#ifdef AH_DEBUG
+               ath_hal_printf(ah, "%s: DB out of range (%u)\n",
+                       __func__, cp[16]);
+#endif
+               return AH_FALSE;
+       }
+
+       /* reverse bits of the transmit power array */
+       for (i = 0; i < 7; i++)
+               cp[i] = ath_hal_reverseBits(cp[i], 5);
+       for (i = 7; i < 15; i++)
+               cp[i] = ath_hal_reverseBits(cp[i], 6);
+
+       /* merge transmit power values into the register - quite gross */
+       pwr_regs[0] |= ((cp[1] << 5) & 0xE0) | (cp[0] & 0x1F);
+       pwr_regs[1] |= ((cp[3] << 7) & 0x80) | ((cp[2] << 2) & 0x7C) |
+                       ((cp[1] >> 3) & 0x03);
+       pwr_regs[2] |= ((cp[4] << 4) & 0xF0) | ((cp[3] >> 1) & 0x0F);
+       pwr_regs[3] |= ((cp[6] << 6) & 0xC0) | ((cp[5] << 1) & 0x3E) |
+                      ((cp[4] >> 4) & 0x01);
+       pwr_regs[4] |= ((cp[7] << 3) & 0xF8) | ((cp[6] >> 2) & 0x07);
+       pwr_regs[5] |= ((cp[9] << 7) & 0x80) | ((cp[8] << 1) & 0x7E) |
+                       ((cp[7] >> 5) & 0x01);
+       pwr_regs[6] |= ((cp[10] << 5) & 0xE0) | ((cp[9] >> 1) & 0x1F);
+       pwr_regs[7] |= ((cp[11] << 3) & 0xF8) | ((cp[10] >> 3) & 0x07);
+       pwr_regs[8] |= ((cp[12] << 1) & 0x7E) | ((cp[11] >> 5) & 0x01);
+       pwr_regs[9] |= ((cp[13] << 5) & 0xE0);
+       pwr_regs[10] |= ((cp[14] << 3) & 0xF8) | ((cp[13] >> 3) & 0x07);
+       pwr_regs[11] |= ((cp[14] >> 5) & 0x01);
+
+       /* Set OB */
+       pwr_regs[8] |=  (ath_hal_reverseBits(cp[15], 3) << 7) & 0x80;
+       pwr_regs[9] |=  (ath_hal_reverseBits(cp[15], 3) >> 1) & 0x03;
+
+       /* Set DB */
+       pwr_regs[9] |=  (ath_hal_reverseBits(cp[16], 3) << 2) & 0x1C;
+
+       /* Write the registers */
+       for (i = 0; i < N(pwr_regs)-1; i++)
+               OS_REG_WRITE(ah, 0x0000989c, pwr_regs[i]);
+       /* last write is a flush */
+       OS_REG_WRITE(ah, 0x000098d4, pwr_regs[i]);
+
+       return AH_TRUE;
+#undef N
+}
+
+/*
+ * Takes the MHz channel value and sets the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus before AGC is active
+ *   or by disabling the AGC.
+ */
+static HAL_BOOL
+ar5210SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t data;
+
+       /* Set the Channel */
+       data = ath_hal_reverseBits((chan->channel - 5120)/10, 5);
+       data = (data << 1) | 0x41;
+       OS_REG_WRITE(ah, AR_PHY(0x27), data);
+       OS_REG_WRITE(ah, AR_PHY(0x30), 0);
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+}
+
+int16_t
+ar5210GetNoiseFloor(struct ath_hal *ah)
+{
+       int16_t nf;
+
+       nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
+       if (nf & 0x100)
+               nf = 0 - ((nf ^ 0x1ff) + 1);
+       return nf;
+}
+
+#define NORMAL_NF_THRESH (-72)
+/*
+ * Peform the noisefloor calibration and check for
+ * any constant channel interference
+ *
+ * Returns: TRUE for a successful noise floor calibration; else FALSE
+ */
+HAL_BOOL
+ar5210CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       int32_t nf, nfLoops;
+
+       /* Calibrate the noise floor */
+       OS_REG_WRITE(ah, AR_PHY_AGCCTL,
+               OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_NF);
+
+       /* Do not read noise floor until it has done the first update */
+       if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_NF, 0)) {
+#ifdef ATH_HAL_DEBUG
+               ath_hal_printf(ah, " -PHY NF Reg state: 0x%x\n",
+                       OS_REG_READ(ah, AR_PHY_AGCCTL));
+               ath_hal_printf(ah, " -MAC Reset Reg state: 0x%x\n",
+                       OS_REG_READ(ah, AR_RC));
+               ath_hal_printf(ah, " -PHY Active Reg state: 0x%x\n",
+                       OS_REG_READ(ah, AR_PHY_ACTIVE));
+#endif /* ATH_HAL_DEBUG */
+               return AH_FALSE;
+       }
+
+       nf = 0;
+       /* Keep checking until the floor is below the threshold or the nf is done */
+       for (nfLoops = 0; ((nfLoops < 21) && (nf > NORMAL_NF_THRESH)); nfLoops++) {
+               OS_DELAY(1000); /* Sleep for 1 ms */
+               nf = ar5210GetNoiseFloor(ah);
+       }
+
+       if (nf > NORMAL_NF_THRESH) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Bad noise cal %d\n",
+                   __func__, nf);
+               chan->rawNoiseFloor = 0;
+               return AH_FALSE;
+       }
+       chan->rawNoiseFloor = nf;
+       return AH_TRUE;
+}
+
+/*
+ * Adjust NF based on statistical values for 5GHz frequencies.
+ */
+int16_t
+ar5210GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
+{
+       return 0;
+}
+
+HAL_RFGAIN
+ar5210GetRfgain(struct ath_hal *ah)
+{
+       return HAL_RFGAIN_INACTIVE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210_xmit.c      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210_xmit.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+
+#include "ar5210/ar5210.h"
+#include "ar5210/ar5210reg.h"
+#include "ar5210/ar5210phy.h"
+#include "ar5210/ar5210desc.h"
+
+/*
+ * Set the properties of the tx queue with the parameters
+ * from qInfo.  The queue must previously have been setup
+ * with a call to ar5210SetupTxQueue.
+ */
+HAL_BOOL
+ar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       if (q >= HAL_NUM_TX_QUEUES) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo);
+}
+
+/*
+ * Return the properties for the specified tx queue.
+ */
+HAL_BOOL
+ar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+
+       if (q >= HAL_NUM_TX_QUEUES) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]);
+}
+
+/*
+ * Allocate and initialize a tx DCU/QCU combination.
+ */
+int
+ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
+       const HAL_TXQ_INFO *qInfo)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       HAL_TX_QUEUE_INFO *qi;
+       int q;
+
+       switch (type) {
+       case HAL_TX_QUEUE_BEACON:
+               q = 2;
+               break;
+       case HAL_TX_QUEUE_CAB:
+               q = 1;
+               break;
+       case HAL_TX_QUEUE_DATA:
+               q = 0;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n",
+                   __func__, type);
+               return -1;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
+
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n",
+                   __func__, q);
+               return -1;
+       }
+       OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO));
+       qi->tqi_type = type;
+       if (qInfo == AH_NULL) {
+               /* by default enable OK+ERR+DESC+URN interrupts */
+               qi->tqi_qflags =
+                         HAL_TXQ_TXOKINT_ENABLE
+                       | HAL_TXQ_TXERRINT_ENABLE
+                       | HAL_TXQ_TXDESCINT_ENABLE
+                       | HAL_TXQ_TXURNINT_ENABLE
+                       ;
+               qi->tqi_aifs = INIT_AIFS;
+               qi->tqi_cwmin = HAL_TXQ_USEDEFAULT;     /* NB: do at reset */
+               qi->tqi_shretry = INIT_SH_RETRY;
+               qi->tqi_lgretry = INIT_LG_RETRY;
+       } else
+               (void) ar5210SetTxQueueProps(ah, q, qInfo);
+       /* NB: must be followed by ar5210ResetTxQueue */
+       return q;
+}
+
+/*
+ * Free a tx DCU/QCU combination.
+ */
+HAL_BOOL
+ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       HAL_TX_QUEUE_INFO *qi;
+
+       if (q >= HAL_NUM_TX_QUEUES) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q);
+
+       qi->tqi_type = HAL_TX_QUEUE_INACTIVE;
+       ahp->ah_txOkInterruptMask &= ~(1 << q);
+       ahp->ah_txErrInterruptMask &= ~(1 << q);
+       ahp->ah_txDescInterruptMask &= ~(1 << q);
+       ahp->ah_txEolInterruptMask &= ~(1 << q);
+       ahp->ah_txUrnInterruptMask &= ~(1 << q);
+
+       return AH_TRUE;
+#undef N
+}
+
+HAL_BOOL
+ar5210ResetTxQueue(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       HAL_TX_QUEUE_INFO *qi;
+       uint32_t cwMin;
+
+       if (q >= HAL_NUM_TX_QUEUES) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
+                   __func__, q);
+               return AH_FALSE;
+       }
+
+       /*
+        * Ignore any non-data queue(s).
+        */
+       if (qi->tqi_type != HAL_TX_QUEUE_DATA)
+               return AH_TRUE;
+
+       /* Set turbo mode / base mode parameters on or off */
+       if (IS_CHAN_TURBO(chan)) {
+               OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME_TURBO);
+               OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT_TURBO);
+               OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY_TURBO);
+               OS_REG_WRITE(ah, AR_IFS0,
+                       ((INIT_SIFS_TURBO + qi->tqi_aifs * INIT_SLOT_TIME_TURBO)
+                               << AR_IFS0_DIFS_S)
+                       | INIT_SIFS_TURBO);
+               OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL_TURBO);
+               OS_REG_WRITE(ah, AR_PHY(17),
+                       (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x38);
+               OS_REG_WRITE(ah, AR_PHY_FRCTL,
+                       AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR |
+                       AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR |
+                       AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR |
+                       0x2020 |
+                       AR_PHY_TURBO_MODE | AR_PHY_TURBO_SHORT);
+       } else {
+               OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME);
+               OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT);
+               OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY);
+               OS_REG_WRITE(ah, AR_IFS0,
+                       ((INIT_SIFS + qi->tqi_aifs * INIT_SLOT_TIME)
+                               << AR_IFS0_DIFS_S)
+                       | INIT_SIFS);
+               OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL);
+               OS_REG_WRITE(ah, AR_PHY(17),
+                       (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x1C);
+               OS_REG_WRITE(ah, AR_PHY_FRCTL,
+                       AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR |
+                       AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR |
+                       AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x1020);
+       }
+
+       if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT)
+               cwMin = INIT_CWMIN;
+       else
+               cwMin = qi->tqi_cwmin;
+
+       /* Set cwmin and retry limit values */
+       OS_REG_WRITE(ah, AR_RETRY_LMT,
+                 (cwMin << AR_RETRY_LMT_CW_MIN_S)
+                | SM(INIT_SLG_RETRY, AR_RETRY_LMT_SLG_RETRY)
+                | SM(INIT_SSH_RETRY, AR_RETRY_LMT_SSH_RETRY)
+                | SM(qi->tqi_lgretry, AR_RETRY_LMT_LG_RETRY)
+                | SM(qi->tqi_shretry, AR_RETRY_LMT_SH_RETRY)
+       );
+
+       if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE)
+               ahp->ah_txOkInterruptMask |= 1 << q;
+       else
+               ahp->ah_txOkInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE)
+               ahp->ah_txErrInterruptMask |= 1 << q;
+       else
+               ahp->ah_txErrInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE)
+               ahp->ah_txDescInterruptMask |= 1 << q;
+       else
+               ahp->ah_txDescInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE)
+               ahp->ah_txEolInterruptMask |= 1 << q;
+       else
+               ahp->ah_txEolInterruptMask &= ~(1 << q);
+       if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE)
+               ahp->ah_txUrnInterruptMask |= 1 << q;
+       else
+               ahp->ah_txUrnInterruptMask &= ~(1 << q);
+
+       return AH_TRUE;
+}
+
+/*
+ * Get the TXDP for the "main" data queue.  Needs to be extended
+ * for multiple Q functionality
+ */
+uint32_t
+ar5210GetTxDP(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       HAL_TX_QUEUE_INFO *qi;
+
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+
+       qi = &ahp->ah_txq[q];
+       switch (qi->tqi_type) {
+       case HAL_TX_QUEUE_DATA:
+               return OS_REG_READ(ah, AR_TXDP0);
+       case HAL_TX_QUEUE_INACTIVE:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n",
+                   __func__, q);
+               /* fall thru... */
+       default:
+               break;
+       }
+       return 0xffffffff;
+}
+
+/*
+ * Set the TxDP for the "main" data queue.
+ */
+HAL_BOOL
+ar5210SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       HAL_TX_QUEUE_INFO *qi;
+
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u 0x%x\n",
+           __func__, q, txdp);
+       qi = &ahp->ah_txq[q];
+       switch (qi->tqi_type) {
+       case HAL_TX_QUEUE_DATA:
+#ifdef AH_DEBUG
+               /*
+                * Make sure that TXE is deasserted before setting the
+                * TXDP.  If TXE is still asserted, setting TXDP will
+                * have no effect.
+                */
+               if (OS_REG_READ(ah, AR_CR) & AR_CR_TXE0)
+                       ath_hal_printf(ah, "%s: TXE asserted; AR_CR=0x%x\n",
+                               __func__, OS_REG_READ(ah, AR_CR));
+#endif
+               OS_REG_WRITE(ah, AR_TXDP0, txdp);
+               break;
+       case HAL_TX_QUEUE_BEACON:
+       case HAL_TX_QUEUE_CAB:
+               OS_REG_WRITE(ah, AR_TXDP1, txdp);
+               break;
+       case HAL_TX_QUEUE_INACTIVE:
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
+                   __func__, q);
+               /* fall thru... */
+       default:
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Update Tx FIFO trigger level.
+ *
+ * Set bIncTrigLevel to TRUE to increase the trigger level.
+ * Set bIncTrigLevel to FALSE to decrease the trigger level.
+ *
+ * Returns TRUE if the trigger level was updated
+ */
+HAL_BOOL
+ar5210UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel)
+{
+       uint32_t curTrigLevel;
+       HAL_INT ints = ar5210GetInterrupts(ah);
+
+       /*
+        * Disable chip interrupts. This is because halUpdateTxTrigLevel
+        * is called from both ISR and non-ISR contexts.
+        */
+       (void) ar5210SetInterrupts(ah, ints &~ HAL_INT_GLOBAL);
+       curTrigLevel = OS_REG_READ(ah, AR_TRIG_LEV);
+       if (bIncTrigLevel){
+               /* increase the trigger level */
+               curTrigLevel = curTrigLevel +
+                       ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2);
+       } else {
+               /* decrease the trigger level if not already at the minimum */
+               if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) {
+                       /* decrease the trigger level */
+                       curTrigLevel--;
+               } else {
+                       /* no update to the trigger level */
+                       /* re-enable chip interrupts */
+                       ar5210SetInterrupts(ah, ints);
+                       return AH_FALSE;
+               }
+       }
+       /* Update the trigger level */
+       OS_REG_WRITE(ah, AR_TRIG_LEV, curTrigLevel);
+       /* re-enable chip interrupts */
+       ar5210SetInterrupts(ah, ints);
+       return AH_TRUE;
+}
+
+/*
+ * Set Transmit Enable bits for the specified queues.
+ */
+HAL_BOOL
+ar5210StartTxDma(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       HAL_TX_QUEUE_INFO *qi;
+
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
+       qi = &ahp->ah_txq[q];
+       switch (qi->tqi_type) {
+       case HAL_TX_QUEUE_DATA:
+               OS_REG_WRITE(ah, AR_CR, AR_CR_TXE0);
+               break;
+       case HAL_TX_QUEUE_CAB:
+               OS_REG_WRITE(ah, AR_CR, AR_CR_TXE1);    /* enable altq xmit */
+               OS_REG_WRITE(ah, AR_BCR,
+                       AR_BCR_TQ1V | AR_BCR_BDMAE | AR_BCR_TQ1FV);
+               break;
+       case HAL_TX_QUEUE_BEACON:
+               /* XXX add CR_BCR_BCMD if IBSS mode */
+               OS_REG_WRITE(ah, AR_BCR, AR_BCR_TQ1V | AR_BCR_BDMAE);
+               break;
+       case HAL_TX_QUEUE_INACTIVE:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n",
+                   __func__, q);
+               /* fal thru... */
+       default:
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+uint32_t
+ar5210NumTxPending(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       HAL_TX_QUEUE_INFO *qi;
+       uint32_t v;
+
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
+       qi = &ahp->ah_txq[q];
+       switch (qi->tqi_type) {
+       case HAL_TX_QUEUE_DATA:
+               v = OS_REG_READ(ah, AR_CFG);
+               return MS(v, AR_CFG_TXCNT);
+       case HAL_TX_QUEUE_INACTIVE:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n",
+                   __func__, q);
+               /* fall thru... */
+       default:
+               break;
+       }
+       return 0;
+}
+
+/*
+ * Stop transmit on the specified queue
+ */
+HAL_BOOL
+ar5210StopTxDma(struct ath_hal *ah, u_int q)
+{
+       struct ath_hal_5210 *ahp = AH5210(ah);
+       HAL_TX_QUEUE_INFO *qi;
+
+       HALASSERT(q < HAL_NUM_TX_QUEUES);
+
+       HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
+       qi = &ahp->ah_txq[q];
+       switch (qi->tqi_type) {
+       case HAL_TX_QUEUE_DATA: {
+               int i;
+               OS_REG_WRITE(ah, AR_CR, AR_CR_TXD0);
+               for (i = 0; i < 1000; i++) {
+                       if ((OS_REG_READ(ah, AR_CFG) & AR_CFG_TXCNT) == 0)
+                               break;
+                       OS_DELAY(10);
+               }
+               OS_REG_WRITE(ah, AR_CR, 0);
+               return (i < 1000);
+       }
+       case HAL_TX_QUEUE_BEACON:
+               return ath_hal_wait(ah, AR_BSR, AR_BSR_TXQ1F, 0);
+       case HAL_TX_QUEUE_INACTIVE:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n",
+                   __func__, q);
+               /* fall thru... */
+       default:
+               break;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Descriptor Access Functions
+ */
+
+#define        VALID_PKT_TYPES \
+       ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\
+        (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\
+        (1<<HAL_PKT_TYPE_BEACON))
+#define        isValidPktType(_t)      ((1<<(_t)) & VALID_PKT_TYPES)
+#define        VALID_TX_RATES \
+       ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\
+        (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\
+        (1<<0x1d)|(1<<0x18)|(1<<0x1c))
+#define        isValidTxRate(_r)       ((1<<(_r)) & VALID_TX_RATES)
+
+HAL_BOOL
+ar5210SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int pktLen,
+       u_int hdrLen,
+       HAL_PKT_TYPE type,
+       u_int txPower,
+       u_int txRate0, u_int txTries0,
+       u_int keyIx,
+       u_int antMode,
+       u_int flags,
+       u_int rtsctsRate,
+       u_int rtsctsDuration,
+        u_int compicvLen,
+       u_int compivLen,
+       u_int comp)
+{
+       struct ar5210_desc *ads = AR5210DESC(ds);
+       uint32_t frtype;
+
+       (void) txPower;
+       (void) rtsctsDuration;
+
+       HALASSERT(txTries0 != 0);
+       HALASSERT(isValidPktType(type));
+       HALASSERT(isValidTxRate(txRate0));
+
+       if (type == HAL_PKT_TYPE_BEACON || type == HAL_PKT_TYPE_PROBE_RESP)
+               frtype = AR_Frm_NoDelay;
+       else
+               frtype = type << 26;
+       ads->ds_ctl0 = (pktLen & AR_FrameLen)
+                    | (txRate0 << AR_XmitRate_S)
+                    | ((hdrLen << AR_HdrLen_S) & AR_HdrLen)
+                    | frtype
+                    | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0)
+                    | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0)
+                    | (antMode ? AR_AntModeXmit : 0)
+                    ;
+       if (keyIx != HAL_TXKEYIX_INVALID) {
+               ads->ds_ctl1 = (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx;
+               ads->ds_ctl0 |= AR_EncryptKeyValid;
+       } else
+               ads->ds_ctl1 = 0;
+       if (flags & HAL_TXDESC_RTSENA) {
+               ads->ds_ctl0 |= AR_RTSCTSEnable;
+               ads->ds_ctl1 |= rtsctsDuration & AR_RTSDuration;
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5210SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int txRate1, u_int txTries1,
+       u_int txRate2, u_int txTries2,
+       u_int txRate3, u_int txTries3)
+{
+       (void) ah; (void) ds;
+       (void) txRate1; (void) txTries1;
+       (void) txRate2; (void) txTries2;
+       (void) txRate3; (void) txTries3;
+       return AH_FALSE;
+}
+
+void
+ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+       struct ar5210_desc *ads = AR5210DESC(ds);
+
+       ads->ds_ctl0 |= AR_TxInterReq;
+}
+
+HAL_BOOL
+ar5210FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+       const struct ath_desc *ds0)
+{
+       struct ar5210_desc *ads = AR5210DESC(ds);
+
+       HALASSERT((segLen &~ AR_BufLen) == 0);
+
+       if (firstSeg) {
+               /*
+                * First descriptor, don't clobber xmit control data
+                * setup by ar5210SetupTxDesc.
+                */
+               ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More);
+       } else if (lastSeg) {           /* !firstSeg && lastSeg */
+               /*
+                * Last descriptor in a multi-descriptor frame,
+                * copy the transmit parameters from the first
+                * frame for processing on completion.
+                */
+               ads->ds_ctl0 = AR5210DESC_CONST(ds0)->ds_ctl0;
+               ads->ds_ctl1 = segLen;
+       } else {                        /* !firstSeg && !lastSeg */
+               /*
+                * Intermediate descriptor in a multi-descriptor frame.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 = segLen | AR_More;
+       }
+       ads->ds_status0 = ads->ds_status1 = 0;
+       return AH_TRUE;
+}
+
+/*
+ * Processing of HW TX descriptor.
+ */
+HAL_STATUS
+ar5210ProcTxDesc(struct ath_hal *ah,
+       struct ath_desc *ds, struct ath_tx_status *ts)
+{
+       struct ar5210_desc *ads = AR5210DESC(ds);
+
+       if ((ads->ds_status1 & AR_Done) == 0)
+               return HAL_EINPROGRESS;
+
+       /* Update software copies of the HW status */
+       ts->ts_seqnum = ads->ds_status1 & AR_SeqNum;
+       ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp);
+       ts->ts_status = 0;
+       if ((ads->ds_status0 & AR_FrmXmitOK) == 0) {
+               if (ads->ds_status0 & AR_ExcessiveRetries)
+                       ts->ts_status |= HAL_TXERR_XRETRY;
+               if (ads->ds_status0 & AR_Filtered)
+                       ts->ts_status |= HAL_TXERR_FILT;
+               if (ads->ds_status0  & AR_FIFOUnderrun)
+                       ts->ts_status |= HAL_TXERR_FIFO;
+       }
+       ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate);
+       ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength);
+       ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt);
+       ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt);
+       ts->ts_antenna = 0;             /* NB: don't know */
+       ts->ts_finaltsi = 0;
+
+       return HAL_OK;
+}
+
+/*
+ * Determine which tx queues need interrupt servicing.
+ * STUB.
+ */
+void
+ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs)
+{
+       return;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210desc.h       2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210desc.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5210DESC_H
+#define _DEV_ATH_AR5210DESC_H
+
+#include "ah_desc.h"
+
+/*
+ * Defintions for the DMA descriptors used by the Atheros
+ * AR5210/AR5211 and AR5110 Wireless Lan controller parts.
+ */
+
+/* DMA descriptors */
+struct ar5210_desc {
+       uint32_t        ds_link;        /* link pointer */
+       uint32_t        ds_data;        /* data buffer pointer */
+       uint32_t        ds_ctl0;        /* DMA control 0 */
+       uint32_t        ds_ctl1;        /* DMA control 1 */
+       uint32_t        ds_status0;     /* DMA status 0 */
+       uint32_t        ds_status1;     /* DMA status 1 */
+} __packed;
+#define        AR5210DESC(_ds) ((struct ar5210_desc *)(_ds))
+#define        AR5210DESC_CONST(_ds)   ((const struct ar5210_desc *)(_ds))
+
+/* TX ds_ctl0 */
+#define        AR_FrameLen             0x00000fff      /* frame length */
+#define        AR_HdrLen               0x0003f000      /* header length */
+#define        AR_HdrLen_S             12
+#define        AR_XmitRate             0x003c0000      /* txrate */
+#define        AR_XmitRate_S           18
+#define        AR_Rate_6M              0xb
+#define        AR_Rate_9M              0xf
+#define        AR_Rate_12M             0xa
+#define        AR_Rate_18M             0xe
+#define        AR_Rate_24M             0x9
+#define        AR_Rate_36M             0xd
+#define        AR_Rate_48M             0x8
+#define        AR_Rate_54M             0xc
+#define        AR_RTSCTSEnable         0x00400000      /* RTS/CTS enable */
+#define        AR_LongPkt              0x00800000      /* long packet indication */
+#define        AR_ClearDestMask        0x01000000      /* Clear destination mask bit */
+#define        AR_AntModeXmit          0x02000000      /* TX antenna seslection */
+#define        AR_FrmType              0x1c000000      /* frame type indication */
+#define        AR_Frm_Normal           0x00000000      /* normal frame */
+#define        AR_Frm_ATIM             0x04000000      /* ATIM frame */
+#define        AR_Frm_PSPOLL           0x08000000      /* PS poll frame */
+#define        AR_Frm_NoDelay          0x0c000000      /* no delay data */
+#define        AR_Frm_PIFS             0x10000000      /* PIFS data */
+#define        AR_TxInterReq           0x20000000      /* TX interrupt request */
+#define        AR_EncryptKeyValid      0x40000000      /* EncryptKeyIdx is valid */
+
+/* TX ds_ctl1 */
+#define        AR_BufLen               0x00000fff      /* data buffer length */
+#define        AR_More                 0x00001000      /* more desc in this frame */
+#define        AR_EncryptKeyIdx        0x0007e000      /* ecnrypt key table index */
+#define        AR_EncryptKeyIdx_S      13
+#define        AR_RTSDuration          0xfff80000      /* lower 13bit of duration */
+
+/* RX ds_ctl1 */
+/*     AR_BufLen               0x00000fff         data buffer length */
+#define        AR_RxInterReq           0x00002000      /* RX interrupt request */
+
+/* TX ds_status0 */
+#define        AR_FrmXmitOK            0x00000001      /* TX success */
+#define        AR_ExcessiveRetries     0x00000002      /* excessive retries */
+#define        AR_FIFOUnderrun         0x00000004      /* TX FIFO underrun */
+#define        AR_Filtered             0x00000008      /* TX filter indication */
+/* NB: the spec has the Short+Long retry counts reversed */
+#define        AR_LongRetryCnt         0x000000f0      /* long retry count */
+#define        AR_LongRetryCnt_S       4
+#define        AR_ShortRetryCnt        0x00000f00      /* short retry count */
+#define        AR_ShortRetryCnt_S      8
+#define        AR_SendTimestamp        0xffff0000      /* TX timestamp */
+#define        AR_SendTimestamp_S      16
+
+/* RX ds_status0 */
+#define        AR_DataLen              0x00000fff      /* RX data length */
+/*     AR_More                 0x00001000         more desc in this frame */
+#define        AR_RcvAntenna           0x00004000      /* received on ant 1 */
+#define        AR_RcvRate              0x00078000      /* reception rate */
+#define        AR_RcvRate_S            15
+#define        AR_RcvSigStrength       0x07f80000      /* receive signal strength */
+#define        AR_RcvSigStrength_S     19
+
+/* TX ds_status1 */
+#define        AR_Done                 0x00000001      /* descripter complete */
+#define        AR_SeqNum               0x00001ffe      /* TX sequence number */
+#define        AR_AckSigStrength       0x001fe000      /* strength of ACK */
+#define        AR_AckSigStrength_S     13
+
+/* RX ds_status1 */
+/*     AR_Done                 0x00000001         descripter complete */
+#define        AR_FrmRcvOK             0x00000002      /* frame reception success */
+#define        AR_CRCErr               0x00000004      /* CRC error */
+#define        AR_FIFOOverrun          0x00000008      /* RX FIFO overrun */
+#define        AR_DecryptCRCErr        0x00000010      /* Decryption CRC fiailure */
+#define        AR_PHYErr               0x000000e0      /* PHY error */
+#define        AR_PHYErr_S             5
+#define        AR_PHYErr_NoErr         0x00000000      /* No error */
+#define        AR_PHYErr_Tim           0x00000020      /* Timing error */
+#define        AR_PHYErr_Par           0x00000040      /* Parity error */
+#define        AR_PHYErr_Rate          0x00000060      /* Illegal rate */
+#define        AR_PHYErr_Len           0x00000080      /* Illegal length */
+#define        AR_PHYErr_QAM           0x000000a0      /* 64 QAM rate */
+#define        AR_PHYErr_Srv           0x000000c0      /* Service bit error */
+#define        AR_PHYErr_TOR           0x000000e0      /* Transmit override receive */
+#define        AR_KeyIdxValid          0x00000100      /* decryption key index valid */
+#define        AR_KeyIdx               0x00007e00      /* Decryption key index */
+#define        AR_KeyIdx_S             9
+#define        AR_RcvTimestamp         0x0fff8000      /* timestamp */
+#define        AR_RcvTimestamp_S       15
+#define        AR_KeyCacheMiss         0x10000000      /* key cache miss indication */
+
+#endif /* _DEV_ATH_AR5210DESC_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210phy.h        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210phy.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5210PHY_H
+#define _DEV_ATH_AR5210PHY_H
+
+/*
+ * Definitions for the PHY on the Atheros AR5210 parts.
+ */
+
+/* PHY Registers */
+#define        AR_PHY_BASE             0x9800          /* PHY register base */
+#define        AR_PHY(_n)              (AR_PHY_BASE + ((_n)<<2))
+
+#define        AR_PHY_FRCTL            0x9804          /* PHY frame control */
+#define        AR_PHY_TURBO_MODE       0x00000001      /* PHY turbo mode */
+#define        AR_PHY_TURBO_SHORT      0x00000002      /* PHY turbo short symbol */
+#define        AR_PHY_TIMING_ERR       0x01000000      /* Detect PHY timing error */
+#define        AR_PHY_PARITY_ERR       0x02000000      /* Detect signal parity err */
+#define        AR_PHY_ILLRATE_ERR      0x04000000      /* Detect PHY illegal rate */
+#define        AR_PHY_ILLLEN_ERR       0x08000000      /* Detect PHY illegal length */
+#define        AR_PHY_SERVICE_ERR      0x20000000      /* Detect PHY nonzero service */
+#define        AR_PHY_TXURN_ERR        0x40000000      /* DetectPHY TX underrun */
+#define        AR_PHY_FRCTL_BITS \
+       "\20\1TURBO_MODE\2TURBO_SHORT\30TIMING_ERR\31PARITY_ERR\32ILLRATE_ERR"\
+       "\33ILLEN_ERR\35SERVICE_ERR\36TXURN_ERR"
+
+#define        AR_PHY_AGC              0x9808          /* PHY AGC command */
+#define        AR_PHY_AGC_DISABLE      0x08000000      /* Disable PHY AGC */
+#define        AR_PHY_AGC_BITS "\20\33DISABLE"
+
+#define        AR_PHY_CHIPID           0x9818          /* PHY chip revision */
+
+#define        AR_PHY_ACTIVE           0x981c          /* PHY activation */
+#define        AR_PHY_ENABLE           0x00000001      /* activate PHY */
+#define        AR_PHY_DISABLE          0x00000002      /* deactivate PHY */
+#define        AR_PHY_ACTIVE_BITS      "\20\1ENABLE\2DISABLE"
+
+#define        AR_PHY_AGCCTL           0x9860          /* PHY calibration and noise floor */
+#define        AR_PHY_AGC_CAL          0x00000001      /* PHY internal calibration */
+#define        AR_PHY_AGC_NF           0x00000002      /* calc PHY noise-floor */
+#define        AR_PHY_AGCCTL_BITS      "\20\1CAL\2NF"
+
+#endif /* _DEV_ATH_AR5210PHY_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5210reg.h        2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5210reg.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5210REG_H
+#define _DEV_ATH_AR5210REG_H
+
+/*
+ * Register defintions for the Atheros AR5210/5110 MAC/Basedband
+ * Processor for IEEE 802.11a 5-GHz Wireless LANs.
+ */
+
+#ifndef PCI_VENDOR_ATHEROS
+#define        PCI_VENDOR_ATHEROS              0x168c
+#endif
+#define        PCI_PRODUCT_ATHEROS_AR5210      0x0007
+#define        PCI_PRODUCT_ATHEROS_AR5210_OLD  0x0004
+
+/* DMA Registers */
+#define        AR_TXDP0        0x0000          /* TX queue pointer 0 register */
+#define        AR_TXDP1        0x0004          /* TX queue pointer 1 register */
+#define        AR_CR           0x0008          /* Command register */
+#define        AR_RXDP         0x000c          /* RX queue descriptor ptr register */
+#define        AR_CFG          0x0014          /* Configuration and status register */
+#define        AR_ISR          0x001c          /* Interrupt status register */
+#define        AR_IMR          0x0020          /* Interrupt mask register */
+#define        AR_IER          0x0024          /* Interrupt global enable register */
+#define        AR_BCR          0x0028          /* Beacon control register */
+#define        AR_BSR          0x002c          /* Beacon status register */
+#define        AR_TXCFG        0x0030          /* TX configuration register */
+#define        AR_RXCFG        0x0034          /* RX configuration register */
+#define        AR_MIBC         0x0040          /* MIB control register */
+#define        AR_TOPS         0x0044          /* Timeout prescale register */
+#define        AR_RXNOFRM      0x0048          /* RX no frame timeout register */
+#define        AR_TXNOFRM      0x004c          /* TX no frame timeout register */
+#define        AR_RPGTO        0x0050          /* RX frame gap timeout register */
+#define        AR_RFCNT        0x0054          /* RX frame count limit register */
+#define        AR_MISC         0x0058          /* Misc control and status register */
+#define        AR_RC           0x4000          /* Reset control */
+#define        AR_SCR          0x4004          /* Sleep control */
+#define        AR_INTPEND      0x4008          /* Interrupt pending */
+#define        AR_SFR          0x400c          /* Force sleep */
+#define        AR_PCICFG       0x4010          /* PCI configuration */
+#define        AR_GPIOCR       0x4014          /* GPIO configuration */
+#define        AR_GPIODO       0x4018          /* GPIO data output */
+#define        AR_GPIODI       0x401c          /* GPIO data input */
+#define        AR_SREV         0x4020          /* Silicon revision */
+/* EEPROM Access Registers */
+#define        AR_EP_AIR_BASE  0x6000          /* EEPROM access initiation regs base */
+#define        AR_EP_AIR(n)    (AR_EP_AIR_BASE + (n)*4)
+#define        AR_EP_RDATA     0x6800          /* EEPROM read data register */
+#define        AR_EP_STA       0x6c00          /* EEPROM access status register */
+/* PCU Registers */
+#define        AR_STA_ID0      0x8000          /* Lower 32bits of MAC address */
+#define        AR_STA_ID1      0x8004          /* Upper 16bits of MAC address */
+#define        AR_BSS_ID0      0x8008          /* Lower 32bits of BSSID */
+#define        AR_BSS_ID1      0x800c          /* Upper 16bits of BSSID */
+#define        AR_SLOT_TIME    0x8010          /* Length of a back-off */
+#define        AR_TIME_OUT     0x8014          /* Timeout to wait for ACK and CTS */
+#define        AR_RSSI_THR     0x8018          /* Beacon RSSI warning threshold */
+#define        AR_RETRY_LMT    0x801c          /* Short and long frame retry limit */
+#define        AR_USEC         0x8020          /* Transmit latency */
+#define        AR_BEACON       0x8024          /* Beacon control */
+#define        AR_CFP_PERIOD   0x8028          /* CFP period */
+#define        AR_TIMER0       0x802c          /* Next beacon time */
+#define        AR_TIMER1       0x8030          /* Next DMA beacon alert time */
+#define        AR_TIMER2       0x8034          /* Next software beacon alert time */
+#define        AR_TIMER3       0x8038          /* Next ATIM window time */
+#define        AR_IFS0         0x8040          /* Protocol timers */
+#define        AR_IFS1         0x8044          /* Protocol time and control */
+#define        AR_CFP_DUR      0x8048          /* Maximum CFP duration */
+#define        AR_RX_FILTER    0x804c          /* Receive filter */
+#define        AR_MCAST_FIL0   0x8050          /* Lower 32bits of mcast filter mask */
+#define        AR_MCAST_FIL1   0x8054          /* Upper 16bits of mcast filter mask */
+#define        AR_TX_MASK0     0x8058          /* Lower 32bits of TX mask */
+#define        AR_TX_MASK1     0x805c          /* Upper 16bits of TX mask */
+#define        AR_CLR_TMASK    0x8060          /* Clear TX mask */
+#define        AR_TRIG_LEV     0x8064          /* Minimum FIFO fill level before TX */
+#define        AR_DIAG_SW      0x8068          /* PCU control */
+#define        AR_TSF_L32      0x806c          /* Lower 32bits of local clock */
+#define        AR_TSF_U32      0x8070          /* Upper 32bits of local clock */
+#define        AR_LAST_TSTP    0x8080          /* Lower 32bits of last beacon tstamp */
+#define        AR_RETRY_CNT    0x8084          /* Current short or long retry cnt */
+#define        AR_BACKOFF      0x8088          /* Back-off status */
+#define        AR_NAV          0x808c          /* Current NAV value */
+#define        AR_RTS_OK       0x8090          /* RTS success counter */
+#define        AR_RTS_FAIL     0x8094          /* RTS failure counter */
+#define        AR_ACK_FAIL     0x8098          /* ACK failure counter */
+#define        AR_FCS_FAIL     0x809c          /* FCS failure counter */
+#define        AR_BEACON_CNT   0x80a0          /* Valid beacon counter */
+#define        AR_KEYTABLE_0   0x9000          /* Encryption key table */
+#define        AR_KEYTABLE(n)  (AR_KEYTABLE_0 + ((n)*32))
+
+#define        AR_CR_TXE0              0x00000001      /* TX queue 0 enable */
+#define        AR_CR_TXE1              0x00000002      /* TX queue 1 enable */
+#define        AR_CR_RXE               0x00000004      /* RX enable */
+#define        AR_CR_TXD0              0x00000008      /* TX queue 0 disable */
+#define        AR_CR_TXD1              0x00000010      /* TX queue 1 disable */
+#define        AR_CR_RXD               0x00000020      /* RX disable */
+#define        AR_CR_SWI               0x00000040      /* software interrupt */
+#define        AR_CR_BITS \
+       "\20\1TXE0\2TXE1\3RXE\4TXD0\5TXD1\6RXD\7SWI"
+
+#define        AR_CFG_SWTD             0x00000001      /* BE for TX desc */
+#define        AR_CFG_SWTB             0x00000002      /* BE for TX data */
+#define        AR_CFG_SWRD             0x00000004      /* BE for RX desc */
+#define        AR_CFG_SWRB             0x00000008      /* BE for RX data */
+#define        AR_CFG_SWRG             0x00000010      /* BE for registers */
+#define        AR_CFG_EEBS             0x00000200      /* EEPROM busy */
+#define        AR_CFG_TXCNT            0x00007800      /* number of TX desc in Q */
+#define        AR_CFG_TXCNT_S          11
+#define        AR_CFG_TXFSTAT          0x00008000      /* TX DMA status */
+#define        AR_CFG_TXFSTRT          0x00010000      /* re-enable TX DMA */
+#define        AR_CFG_BITS \
+       "\20\1SWTD\2SWTB\3SWRD\4SWRB\5SWRG\14EEBS\17TXFSTAT\20TXFSTRT"
+
+#define        AR_ISR_RXOK_INT         0x00000001      /* RX frame OK */
+#define        AR_ISR_RXDESC_INT       0x00000002      /* RX intr request */
+#define        AR_ISR_RXERR_INT        0x00000004      /* RX error */
+#define        AR_ISR_RXNOFRM_INT      0x00000008      /* no frame received */
+#define        AR_ISR_RXEOL_INT        0x00000010      /* RX desc empty */
+#define        AR_ISR_RXORN_INT        0x00000020      /* RX fifo overrun */
+#define        AR_ISR_TXOK_INT         0x00000040      /* TX frame OK */
+#define        AR_ISR_TXDESC_INT       0x00000080      /* TX intr request */
+#define        AR_ISR_TXERR_INT        0x00000100      /* TX error */
+#define        AR_ISR_TXNOFRM_INT      0x00000200      /* no frame transmitted */
+#define        AR_ISR_TXEOL_INT        0x00000400      /* TX desc empty */
+#define        AR_ISR_TXURN_INT        0x00000800      /* TX fifo underrun */
+#define        AR_ISR_MIB_INT          0x00001000      /* MIB interrupt */
+#define        AR_ISR_SWI_INT          0x00002000      /* software interrupt */
+#define        AR_ISR_RXPHY_INT        0x00004000      /* PHY RX error */
+#define        AR_ISR_RXKCM_INT        0x00008000      /* Key cache miss */
+#define        AR_ISR_SWBA_INT         0x00010000      /* software beacon alert */
+#define        AR_ISR_BRSSI_INT        0x00020000      /* beacon threshold */
+#define        AR_ISR_BMISS_INT        0x00040000      /* beacon missed */
+#define        AR_ISR_MCABT_INT        0x00100000      /* master cycle abort */
+#define        AR_ISR_SSERR_INT        0x00200000      /* SERR on PCI */
+#define        AR_ISR_DPERR_INT        0x00400000      /* Parity error on PCI */
+#define        AR_ISR_GPIO_INT         0x01000000      /* GPIO interrupt */
+#define        AR_ISR_BITS \
+       "\20\1RXOK\2RXDESC\3RXERR\4RXNOFM\5RXEOL\6RXORN\7TXOK\10TXDESC"\
+       "\11TXERR\12TXNOFRM\13TXEOL\14TXURN\15MIB\16SWI\17RXPHY\20RXKCM"\
+       "\21SWBA\22BRSSI\23BMISS\24MCABT\25SSERR\26DPERR\27GPIO"
+
+#define        AR_IMR_RXOK_INT         0x00000001      /* RX frame OK */
+#define        AR_IMR_RXDESC_INT       0x00000002      /* RX intr request */
+#define        AR_IMR_RXERR_INT        0x00000004      /* RX error */
+#define        AR_IMR_RXNOFRM_INT      0x00000008      /* no frame received */
+#define        AR_IMR_RXEOL_INT        0x00000010      /* RX desc empty */
+#define        AR_IMR_RXORN_INT        0x00000020      /* RX fifo overrun */
+#define        AR_IMR_TXOK_INT         0x00000040      /* TX frame OK */
+#define        AR_IMR_TXDESC_INT       0x00000080      /* TX intr request */
+#define        AR_IMR_TXERR_INT        0x00000100      /* TX error */
+#define        AR_IMR_TXNOFRM_INT      0x00000200      /* no frame transmitted */
+#define        AR_IMR_TXEOL_INT        0x00000400      /* TX desc empty */
+#define        AR_IMR_TXURN_INT        0x00000800      /* TX fifo underrun */
+#define        AR_IMR_MIB_INT          0x00001000      /* MIB interrupt */
+#define        AR_IMR_SWI_INT          0x00002000      /* software interrupt */
+#define        AR_IMR_RXPHY_INT        0x00004000      /* PHY RX error */
+#define        AR_IMR_RXKCM_INT        0x00008000      /* Key cache miss */
+#define        AR_IMR_SWBA_INT         0x00010000      /* software beacon alert */
+#define        AR_IMR_BRSSI_INT        0x00020000      /* beacon threshold */
+#define        AR_IMR_BMISS_INT        0x00040000      /* beacon missed */
+#define        AR_IMR_MCABT_INT        0x00100000      /* master cycle abort */
+#define        AR_IMR_SSERR_INT        0x00200000      /* SERR on PCI */
+#define        AR_IMR_DPERR_INT        0x00400000      /* Parity error on PCI */
+#define        AR_IMR_GPIO_INT         0x01000000      /* GPIO interrupt */
+#define        AR_IMR_BITS     AR_ISR_BITS
+
+#define        AR_IER_DISABLE          0x00000000      /* pseudo-flag */
+#define        AR_IER_ENABLE           0x00000001      /* global interrupt enable */
+#define        AR_IER_BITS     "\20\1ENABLE"
+
+#define        AR_BCR_BCMD             0x00000001      /* ad hoc beacon mode */
+#define        AR_BCR_BDMAE            0x00000002      /* beacon DMA enable */
+#define        AR_BCR_TQ1FV            0x00000004      /* use TXQ1 for non-beacon */
+#define        AR_BCR_TQ1V             0x00000008      /* TXQ1 valid for beacon */
+#define        AR_BCR_BCGET            0x00000010      /* force a beacon fetch */
+#define        AR_BCR_BITS     "\20\1BCMD\2BDMAE\3TQ1FV\4TQ1V\5BCGET"
+
+#define        AR_BSR_BDLYSW           0x00000001      /* software beacon delay */
+#define        AR_BSR_BDLYDMA          0x00000002      /* DMA beacon delay */
+#define        AR_BSR_TXQ1F            0x00000004      /* TXQ1 fetch */
+#define        AR_BSR_ATIMDLY          0x00000008      /* ATIM delay */
+#define        AR_BSR_SNPBCMD          0x00000100      /* snapshot of BCMD */
+#define        AR_BSR_SNPBDMAE         0x00000200      /* snapshot of BDMAE */
+#define        AR_BSR_SNPTQ1FV         0x00000400      /* snapshot of TQ1FV */
+#define        AR_BSR_SNPTQ1V          0x00000800      /* snapshot of TQ1V */
+#define        AR_BSR_SNAPPEDBCRVALID  0x00001000      /* snapshot of BCR are valid */
+#define        AR_BSR_SWBA_CNT         0x00ff0000      /* software beacon alert cnt */
+#define        AR_BSR_BITS \
+       "\20\1BDLYSW\2BDLYDMA\3TXQ1F\4ATIMDLY\11SNPBCMD\12SNPBDMAE"\
+       "\13SNPTQ1FV\14SNPTQ1V\15SNAPPEDBCRVALID"
+
+#define        AR_TXCFG_SDMAMR         0x00000007      /* DMA burst size 2^(2+x) */
+#define        AR_TXCFG_TXFSTP         0x00000008      /* Stop TX DMA on filtered */
+#define        AR_TXCFG_TXFULL         0x00000070      /* TX DMA desc Q full thresh */
+#define        AR_TXCFG_TXCONT_EN      0x00000080      /* Enable continuous TX mode */
+#define        AR_TXCFG_BITS   "\20\3TXFSTP\7TXCONT_EN"
+
+#define        AR_RXCFG_SDMAMW         0x00000007      /* DMA burst size 2^(2+x) */
+#define        AR_RXCFG_ZLFDMA         0x00000010      /* enable zero length DMA */
+
+/* DMA sizes used for both AR_TXCFG_SDMAMR and AR_RXCFG_SDMAMW */
+#define        AR_DMASIZE_4B           0               /* DMA size 4 bytes */
+#define        AR_DMASIZE_8B           1               /* DMA size 8 bytes */
+#define        AR_DMASIZE_16B          2               /* DMA size 16 bytes */
+#define        AR_DMASIZE_32B          3               /* DMA size 32 bytes */
+#define        AR_DMASIZE_64B          4               /* DMA size 64 bytes */
+#define        AR_DMASIZE_128B         5               /* DMA size 128 bytes */
+#define        AR_DMASIZE_256B         6               /* DMA size 256 bytes */
+#define        AR_DMASIZE_512B         7               /* DMA size 512 bytes */
+
+#define        AR_MIBC_COW             0x00000001      /* counter overflow warning */
+#define        AR_MIBC_FMC             0x00000002      /* freeze MIB counters */
+#define        AR_MIBC_CMC             0x00000004      /* clear MIB counters */
+#define        AR_MIBC_MCS             0x00000008      /* MIB counter strobe */
+
+#define        AR_RFCNT_RFCL           0x0000000f      /* RX frame count limit */
+
+#define        AR_MISC_LED_DECAY       0x001c0000      /* LED decay rate */
+#define        AR_MISC_LED_BLINK       0x00e00000      /* LED blink rate */
+
+#define        AR_RC_RPCU              0x00000001      /* PCU Warm Reset */
+#define        AR_RC_RDMA              0x00000002      /* DMA Warm Reset */
+#define        AR_RC_RMAC              0x00000004      /* MAC Warm Reset */
+#define        AR_RC_RPHY              0x00000008      /* PHY Warm Reset */
+#define        AR_RC_RPCI              0x00000010      /* PCI Core Warm Reset */
+#define        AR_RC_BITS      "\20\1RPCU\2RDMA\3RMAC\4RPHY\5RPCI"
+
+#define        AR_SCR_SLDUR            0x0000ffff      /* sleep duration */
+#define        AR_SCR_SLE              0x00030000      /* sleep enable */
+#define        AR_SCR_SLE_S            16
+#define        AR_SCR_SLE_WAKE         0x00000000      /* force wake */
+#define        AR_SCR_SLE_SLP          0x00010000      /* force sleep */
+#define        AR_SCR_SLE_ALLOW        0x00020000      /* allow to control sleep */
+#define        AR_SCR_BITS     "\20\20SLE_SLP\21SLE_ALLOW"
+
+#define        AR_INTPEND_IP           0x00000001      /* interrupt pending */
+#define        AR_INTPEND_BITS "\20\1IP"
+
+#define        AR_SFR_SF               0x00000001      /* force sleep immediately */
+
+#define        AR_PCICFG_EEPROMSEL     0x00000001      /* EEPROM access enable */
+#define        AR_PCICFG_CLKRUNEN      0x00000004      /* CLKRUN enable */
+#define        AR_PCICFG_LED_PEND      0x00000020      /* LED for assoc pending */
+#define        AR_PCICFG_LED_ACT       0x00000040      /* LED for assoc active */
+#define        AR_PCICFG_SL_INTEN      0x00000800      /* Enable sleep intr */
+#define        AR_PCICFG_LED_BCTL      0x00001000      /* LED blink for local act */
+#define        AR_PCICFG_SL_INPEN      0x00002800      /* sleep even intr pending */
+#define        AR_PCICFG_SPWR_DN       0x00010000      /* sleep indication */
+#define        AR_PCICFG_BITS \
+       "\20\1EEPROMSEL\3CLKRUNEN\5LED_PEND\6LED_ACT\13SL_INTEN"\
+       "\14LED_BCTL\20SPWR_DN"
+
+#define        AR_GPIOCR_IN(n)         (0<<((n)*2))    /* input-only */
+#define        AR_GPIOCR_OUT0(n)       (1<<((n)*2))    /* output-only if GPIODO = 0 */
+#define        AR_GPIOCR_OUT1(n)       (2<<((n)*2))    /* output-only if GPIODO = 1 */
+#define        AR_GPIOCR_OUT(n)        (3<<((n)*2))    /* always output */
+#define        AR_GPIOCR_ALL(n)        (3<<((n)*2))    /* all bits for pin */
+#define        AR_GPIOCR_INT_SEL(n)    ((n)<<12)       /* GPIO interrupt pin select */
+#define        AR_GPIOCR_INT_ENA       0x00008000      /* Enable GPIO interrupt */
+#define        AR_GPIOCR_INT_SELL      0x00000000      /* Interrupt if pin is low */
+#define        AR_GPIOCR_INT_SELH      0x00010000      /* Interrupt if pin is high */
+
+#define        AR_SREV_CRETE           4               /* Crete 1st version */
+#define        AR_SREV_CRETE_MS        5               /* Crete FCS version */
+#define        AR_SREV_CRETE_23        8               /* Crete version 2.3 */
+
+#define        AR_EP_STA_RDERR         0x00000001      /* read error */
+#define        AR_EP_STA_RDCMPLT       0x00000002      /* read complete */
+#define        AR_EP_STA_WRERR         0x00000004      /* write error */
+#define        AR_EP_STA_WRCMPLT       0x00000008      /* write complete */
+#define        AR_EP_STA_BITS \
+       "\20\1RDERR\2RDCMPLT\3WRERR\4WRCMPLT"
+
+#define        AR_STA_ID1_AP           0x00010000      /* Access Point Operation */
+#define        AR_STA_ID1_ADHOC        0x00020000      /* ad hoc Operation */
+#define        AR_STA_ID1_PWR_SV       0x00040000      /* power save report enable */
+#define        AR_STA_ID1_NO_KEYSRCH   0x00080000      /* key table search disable */
+#define        AR_STA_ID1_NO_PSPOLL    0x00100000      /* auto PS-POLL disable */
+#define        AR_STA_ID1_PCF          0x00200000      /* PCF observation enable */
+#define        AR_STA_ID1_DESC_ANTENNA 0x00400000      /* use antenna in TX desc */
+#define        AR_STA_ID1_DEFAULT_ANTENNA 0x00800000   /* toggle default antenna */
+#define        AR_STA_ID1_ACKCTS_6MB   0x01000000      /* use 6Mbps for ACK/CTS */
+#define        AR_STA_ID1_BITS \
+       "\20\20AP\21ADHOC\22PWR_SV\23NO_KEYSRCH\24NO_PSPOLL\25PCF"\
+       "\26DESC_ANTENNA\27DEFAULT_ANTENNA\30ACKCTS_6MB"
+
+#define        AR_BSS_ID1_AID          0xffff0000      /* association ID */
+#define        AR_BSS_ID1_AID_S        16
+
+#define        AR_TIME_OUT_ACK         0x00001fff      /* ACK timeout */
+#define        AR_TIME_OUT_ACK_S       0
+#define        AR_TIME_OUT_CTS         0x1fff0000      /* CTS timeout */
+#define        AR_TIME_OUT_CTS_S       16
+
+#define        AR_RSSI_THR_BM_THR      0x00000700      /* missed beacon threshold */
+#define        AR_RSSI_THR_BM_THR_S    8
+
+#define        AR_RETRY_LMT_SH_RETRY   0x0000000f      /* short frame retry limit */
+#define        AR_RETRY_LMT_SH_RETRY_S 0
+#define        AR_RETRY_LMT_LG_RETRY   0x000000f0      /* long frame retry limit */
+#define        AR_RETRY_LMT_LG_RETRY_S 4
+#define        AR_RETRY_LMT_SSH_RETRY  0x00003f00      /* short station retry limit */
+#define        AR_RETRY_LMT_SSH_RETRY_S        8
+#define        AR_RETRY_LMT_SLG_RETRY  0x000fc000      /* long station retry limit */
+#define        AR_RETRY_LMT_SLG_RETRY_S        14
+#define        AR_RETRY_LMT_CW_MIN     0x3ff00000      /* minimum contention window */
+#define        AR_RETRY_LMT_CW_MIN_S           20
+
+#define        AR_USEC_1               0x0000007f      /* number of clk in 1us */
+#define        AR_USEC_1_S             0
+#define        AR_USEC_32              0x00003f80      /* number of 32MHz clk in 1us */
+#define        AR_USEC_32_S            7
+#define        AR_USEC_TX_LATENCY      0x000fc000      /* transmit latency in us */
+#define        AR_USEC_TX_LATENCY_S    14
+#define        AR_USEC_RX_LATENCY      0x03f00000      /* receive latency in us */
+#define        AR_USEC_RX_LATENCY_S    20
+
+#define        AR_BEACON_PERIOD        0x0000ffff      /* beacon period in TU/ms */
+#define        AR_BEACON_PERIOD_S      0
+#define        AR_BEACON_TIM           0x007f0000      /* byte offset */
+#define        AR_BEACON_TIM_S 16
+#define        AR_BEACON_EN            0x00800000      /* beacon transmission enable */
+#define        AR_BEACON_RESET_TSF     0x01000000      /* TSF reset oneshot */
+#define        AR_BEACON_BITS  "\20\27ENABLE\30RESET_TSF"
+
+#define        AR_IFS0_SIFS            0x000007ff      /* SIFS in core clock cycles */
+#define        AR_IFS0_SIFS_S          0
+#define        AR_IFS0_DIFS            0x007ff800      /* DIFS in core clock cycles */
+#define        AR_IFS0_DIFS_S          11
+
+#define        AR_IFS1_PIFS            0x00000fff      /* Programmable IFS */
+#define        AR_IFS1_PIFS_S          0
+#define        AR_IFS1_EIFS            0x03fff000      /* EIFS in core clock cycles */
+#define        AR_IFS1_EIFS_S          12
+#define        AR_IFS1_CS_EN           0x04000000      /* carrier sense enable */
+
+#define        AR_RX_FILTER_UNICAST    0x00000001      /* unicast frame enable */
+#define        AR_RX_FILTER_MULTICAST  0x00000002      /* multicast frame enable */
+#define        AR_RX_FILTER_BROADCAST  0x00000004      /* broadcast frame enable */
+#define        AR_RX_FILTER_CONTROL    0x00000008      /* control frame enable */
+#define        AR_RX_FILTER_BEACON     0x00000010      /* beacon frame enable */
+#define        AR_RX_FILTER_PROMISCUOUS 0x00000020     /* promiscuous receive enable */
+#define        AR_RX_FILTER_BITS \
+       "\20\1UCAST\2MCAST\3BCAST\4CONTROL\5BEACON\6PROMISC"
+
+#define        AR_DIAG_SW_DIS_WEP_ACK  0x00000001      /* disable ACK if no key found*/
+#define        AR_DIAG_SW_DIS_ACK      0x00000002      /* disable ACK generation */
+#define        AR_DIAG_SW_DIS_CTS      0x00000004      /* disable CTS generation */
+#define        AR_DIAG_SW_DIS_ENC      0x00000008      /* encryption disable */
+#define        AR_DIAG_SW_DIS_DEC      0x00000010      /* decryption disable */
+#define        AR_DIAG_SW_DIS_TX       0x00000020      /* TX disable */
+#define        AR_DIAG_SW_DIS_RX       0x00000040      /* RX disable */
+#define        AR_DIAG_SW_LOOP_BACK    0x00000080      /* TX data loopback enable */
+#define        AR_DIAG_SW_CORR_FCS     0x00000100      /* corrupt FCS enable */
+#define        AR_DIAG_SW_CHAN_INFO    0x00000200      /* channel information enable */
+#define        AR_DIAG_SW_EN_SCRAM_SEED 0x00000400     /* use fixed scrambler seed */
+#define        AR_DIAG_SW_SCVRAM_SEED  0x0003f800      /* fixed scrambler seed */
+#define        AR_DIAG_SW_DIS_SEQ_INC  0x00040000      /* seq increment disable */
+#define        AR_DIAG_SW_FRAME_NV0    0x00080000      /* accept frame vers != 0 */
+#define        AR_DIAG_SW_BITS \
+       "\20\1DIS_WEP_ACK\2DIS_ACK\3DIS_CTS\4DIS_ENC\5DIS_DEC\6DIS_TX"\
+       "\7DIS_RX\10LOOP_BACK\11CORR_FCS\12CHAN_INFO\13EN_SCRAM_SEED"\
+       "\22DIS_SEQ_INC\24FRAME_NV0"
+
+#define        AR_RETRY_CNT_SSH        0x0000003f      /* current short retry count */
+#define        AR_RETRY_CNT_SLG        0x00000fc0      /* current long retry count */
+
+#define        AR_BACKOFF_CW           0x000003ff      /* current contention window */
+#define        AR_BACKOFF_CNT          0x03ff0000      /* backoff count */
+
+#define        AR_KEYTABLE_KEY0(n)     (AR_KEYTABLE(n) + 0)    /* key bit 0-31 */
+#define        AR_KEYTABLE_KEY1(n)     (AR_KEYTABLE(n) + 4)    /* key bit 32-47 */
+#define        AR_KEYTABLE_KEY2(n)     (AR_KEYTABLE(n) + 8)    /* key bit 48-79 */
+#define        AR_KEYTABLE_KEY3(n)     (AR_KEYTABLE(n) + 12)   /* key bit 80-95 */
+#define        AR_KEYTABLE_KEY4(n)     (AR_KEYTABLE(n) + 16)   /* key bit 96-127 */
+#define        AR_KEYTABLE_TYPE(n)     (AR_KEYTABLE(n) + 20)   /* key type */
+#define        AR_KEYTABLE_TYPE_40     0x00000000      /* 40 bit key */
+#define        AR_KEYTABLE_TYPE_104    0x00000001      /* 104 bit key */
+#define        AR_KEYTABLE_TYPE_128    0x00000003      /* 128 bit key */
+#define        AR_KEYTABLE_MAC0(n)     (AR_KEYTABLE(n) + 24)   /* MAC address 1-32 */
+#define        AR_KEYTABLE_MAC1(n)     (AR_KEYTABLE(n) + 28)   /* MAC address 33-47 */
+#define        AR_KEYTABLE_VALID       0x00008000      /* key and MAC address valid */
+
+#endif /* _DEV_ATH_AR5210REG_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5k_0007.ini      2009-03-23 17:36:55.000000000 +0000
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2004 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5k_0007.ini,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+
+    /* crete register init */
+    { 0x00009800, 0x00000047 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0x09848ea6 },
+    { 0x00009810, 0x3d32e000 },
+    { 0x00009814, 0x0000076b },
+    { 0x0000981c, 0x00000000 },
+    { 0x00009820, 0x02020200 },
+    { 0x00009824, 0x00000e0e },
+    { 0x00009828, 0x0a020201 },
+    { 0x0000982c, 0x00036ffc },
+    { 0x00009830, 0x00000000 },
+    { 0x00009834, 0x00000e0e },
+    { 0x00009838, 0x00000007 },
+    { 0x0000983c, 0x00020100 },
+    { 0x00009840, 0x89630000 },
+    { 0x00009844, 0x1372169c },
+    { 0x00009848, 0x0018b633 },
+    { 0x0000984c, 0x1284613c },
+    { 0x00009850, 0x0de8b8e0 },
+    { 0x00009854, 0x00074859 },
+    { 0x00009858, 0x7e80beba },
+    { 0x0000985c, 0x313a665e },
+    { 0x00009860, 0x00001d08 },
+    { 0x00009864, 0x0001ce00 },
+    { 0x00009868, 0x409a4190 },
+    { 0x00009870, 0x0000000f },
+    { 0x00009874, 0x00000080 },
+    { 0x00009878, 0x00000004 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00800000 },
+    { 0x00009910, 0x00000003 },
+
+
+    /* bb gain table */
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b04, 0x00000020 },
+    { 0x00009b08, 0x00000010 },
+    { 0x00009b0c, 0x00000030 },
+    { 0x00009b10, 0x00000008 },
+    { 0x00009b14, 0x00000028 },
+    { 0x00009b18, 0x00000028 },
+    { 0x00009b1c, 0x00000004 },
+    { 0x00009b20, 0x00000024 },
+    { 0x00009b24, 0x00000014 },
+    { 0x00009b28, 0x00000034 },
+    { 0x00009b2c, 0x0000000c },
+    { 0x00009b30, 0x0000002c },
+    { 0x00009b34, 0x00000002 },
+    { 0x00009b38, 0x00000022 },
+    { 0x00009b3c, 0x00000012 },
+    { 0x00009b40, 0x00000032 },
+    { 0x00009b44, 0x0000000a },
+    { 0x00009b48, 0x0000002a },
+    { 0x00009b4c, 0x00000001 },
+    { 0x00009b50, 0x00000021 },
+    { 0x00009b54, 0x00000011 },
+    { 0x00009b58, 0x00000031 },
+    { 0x00009b5c, 0x00000009 },
+    { 0x00009b60, 0x00000029 },
+    { 0x00009b64, 0x00000005 },
+    { 0x00009b68, 0x00000025 },
+    { 0x00009b6c, 0x00000015 },
+    { 0x00009b70, 0x00000035 },
+    { 0x00009b74, 0x0000000d },
+    { 0x00009b78, 0x0000002d },
+    { 0x00009b7c, 0x00000003 },
+    { 0x00009b80, 0x00000023 },
+    { 0x00009b84, 0x00000013 },
+    { 0x00009b88, 0x00000033 },
+    { 0x00009b8c, 0x0000000b },
+    { 0x00009b90, 0x0000002b },
+    { 0x00009b94, 0x00000007 },
+    { 0x00009b98, 0x00000027 },
+    { 0x00009b9c, 0x00000017 },
+    { 0x00009ba0, 0x00000037 },
+    { 0x00009ba4, 0x0000000f },
+    { 0x00009ba8, 0x0000002f },
+    { 0x00009bac, 0x0000002f },
+    { 0x00009bb0, 0x0000002f },
+    { 0x00009bb4, 0x0000002f },
+    { 0x00009bb8, 0x0000002f },
+    { 0x00009bbc, 0x0000002f },
+    { 0x00009bc0, 0x0000002f },
+    { 0x00009bc4, 0x0000002f },
+    { 0x00009bc8, 0x0000002f },
+    { 0x00009bcc, 0x0000002f },
+    { 0x00009bd0, 0x0000002f },
+    { 0x00009bd4, 0x0000002f },
+    { 0x00009bd8, 0x0000002f },
+    { 0x00009bdc, 0x0000002f },
+    { 0x00009be0, 0x0000002f },
+    { 0x00009be4, 0x0000002f },
+    { 0x00009be8, 0x0000002f },
+    { 0x00009bec, 0x0000002f },
+    { 0x00009bf0, 0x0000002f },
+    { 0x00009bf4, 0x0000002f },
+    { 0x00009bf8, 0x0000002f },
+    { 0x00009bfc, 0x0000002f },
+
+    /* rf gain table */
+    { 0x00009a00, 0x0000001d },
+    { 0x00009a04, 0x0000005d },
+    { 0x00009a08, 0x0000009d },
+    { 0x00009a0c, 0x000000dd },
+    { 0x00009a10, 0x0000011d },
+    { 0x00009a14, 0x00000021 },
+    { 0x00009a18, 0x00000061 },
+    { 0x00009a1c, 0x000000a1 },
+    { 0x00009a20, 0x000000e1 },
+    { 0x00009a24, 0x00000031 },
+    { 0x00009a28, 0x00000071 },
+    { 0x00009a2c, 0x000000b1 },
+    { 0x00009a30, 0x0000001c },
+    { 0x00009a34, 0x0000005c },
+    { 0x00009a38, 0x00000029 },
+    { 0x00009a3c, 0x00000069 },
+    { 0x00009a40, 0x000000a9 },
+    { 0x00009a44, 0x00000020 },
+    { 0x00009a48, 0x00000019 },
+    { 0x00009a4c, 0x00000059 },
+    { 0x00009a50, 0x00000099 },
+    { 0x00009a54, 0x00000030 },
+    { 0x00009a58, 0x00000005 },
+    { 0x00009a5c, 0x00000025 },
+    { 0x00009a60, 0x00000065 },
+    { 0x00009a64, 0x000000a5 },
+    { 0x00009a68, 0x00000028 },
+    { 0x00009a6c, 0x00000068 },
+    { 0x00009a70, 0x0000001f },
+    { 0x00009a74, 0x0000001e },
+    { 0x00009a78, 0x00000018 },
+    { 0x00009a7c, 0x00000058 },
+    { 0x00009a80, 0x00000098 },
+    { 0x00009a84, 0x00000003 },
+    { 0x00009a88, 0x00000004 },
+    { 0x00009a8c, 0x00000044 },
+    { 0x00009a90, 0x00000084 },
+    { 0x00009a94, 0x00000013 },
+    { 0x00009a98, 0x00000012 },
+    { 0x00009a9c, 0x00000052 },
+    { 0x00009aa0, 0x00000092 },
+    { 0x00009aa4, 0x000000d2 },
+    { 0x00009aa8, 0x0000002b },
+    { 0x00009aac, 0x0000002a },
+    { 0x00009ab0, 0x0000006a },
+    { 0x00009ab4, 0x000000aa },
+    { 0x00009ab8, 0x0000001b },
+    { 0x00009abc, 0x0000001a },
+    { 0x00009ac0, 0x0000005a },
+    { 0x00009ac4, 0x0000009a },
+    { 0x00009ac8, 0x000000da },
+    { 0x00009acc, 0x00000006 },
+    { 0x00009ad0, 0x00000006 },
+    { 0x00009ad4, 0x00000006 },
+    { 0x00009ad8, 0x00000006 },
+    { 0x00009adc, 0x00000006 },
+    { 0x00009ae0, 0x00000006 },
+    { 0x00009ae4, 0x00000006 },
+    { 0x00009ae8, 0x00000006 },
+    { 0x00009aec, 0x00000006 },
+    { 0x00009af0, 0x00000006 },
+    { 0x00009af4, 0x00000006 },
+    { 0x00009af8, 0x00000006 },
+    { 0x00009afc, 0x00000006 },
+
+    /* fez register init */
+    { 0x000098d4, 0x00000020 },
+    { 0x000098cc, 0x00000004 },
+    { 0x000098c8, 0x00060106 },
+    { 0x0000989c, 0x0000006d },
+    { 0x000098c0, 0x00000000 },
+    { 0x000098d0, 0x00000014 },
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar2133.c   2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar2133.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#define N(a)    (sizeof(a)/sizeof(a[0]))
+
+struct ar2133State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[1];
+
+       uint32_t        *Bank0Data;
+       uint32_t        *Bank1Data;
+       uint32_t        *Bank2Data;
+       uint32_t        *Bank3Data;
+       uint32_t        *Bank6Data;
+       uint32_t        *Bank7Data;
+
+       /* NB: Bank*Data storage follows */
+};
+#define        AR2133(ah)      ((struct ar2133State *) AH5212(ah)->ah_rfHal)
+
+#define        ar5416ModifyRfBuffer    ar5212ModifyRfBuffer    /*XXX*/
+
+extern  void ar5416ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+       uint32_t numBits, uint32_t firstBit, uint32_t column);
+HAL_BOOL ar2133GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL
+       *chans, uint32_t nchans);
+
+static HAL_BOOL ar2133GetChannelMaxMinPower(struct ath_hal *, HAL_CHANNEL *,
+               int16_t *maxPow,int16_t *minPow);
+int16_t ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c);
+
+static void
+ar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int writes)
+{
+       (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain,
+               freqIndex, writes);
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar2133SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t channelSel  = 0;
+       uint32_t bModeSynth  = 0;
+       uint32_t aModeRefSel = 0;
+       uint32_t reg32       = 0;
+       uint16_t freq;
+       CHAN_CENTERS centers;
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       ar5416GetChannelCenters(ah,  chan, &centers);
+       freq = centers.synth_center;
+
+       if (freq < 4800) {
+               uint32_t txctl;
+
+               if (((freq - 2192) % 5) == 0) {
+                       channelSel = ((freq - 672) * 2 - 3040)/10;
+                       bModeSynth = 0;
+               } else if (((freq - 2224) % 5) == 0) {
+                       channelSel = ((freq - 704) * 2 - 3040) / 10;
+                       bModeSynth = 1;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid channel %u MHz\n", __func__, freq);
+                       return AH_FALSE;
+               }
+
+               channelSel = (channelSel << 2) & 0xff;
+               channelSel = ath_hal_reverseBits(channelSel, 8);
+
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (freq == 2484) {
+                       /* Enable channel spreading for channel 14 */
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                       txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+       } else if ((freq % 20) == 0 && freq >= 5120) {
+               channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8);
+               if (AR_SREV_SOWL_10_OR_LATER(ah))
+                       aModeRefSel = ath_hal_reverseBits(3, 2);
+               else
+                       aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else if ((freq % 10) == 0) {
+               channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8);
+               if (AR_SREV_SOWL_10_OR_LATER(ah))
+                       aModeRefSel = ath_hal_reverseBits(2, 2);
+               else
+                       aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else if ((freq % 5) == 0) {
+               channelSel = ath_hal_reverseBits((freq - 4800) / 5, 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
+                   __func__, freq);
+               return AH_FALSE;
+       }
+
+       reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
+               (1 << 5) | 0x1;
+
+       OS_REG_WRITE(ah, AR_PHY(0x37), reg32);
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar2133GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar2133State *priv = AR2133(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar2133SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
+                uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+       struct ar2133State *priv = AR2133(ah);
+       int writes;
+
+       HALASSERT(priv);
+
+       /* Setup Bank 0 Write */
+       ath_hal_ini_bank_setup(priv->Bank0Data, &AH5416(ah)->ah_ini_bank0, 1);
+
+       /* Setup Bank 1 Write */
+       ath_hal_ini_bank_setup(priv->Bank1Data, &AH5416(ah)->ah_ini_bank1, 1);
+
+       /* Setup Bank 2 Write */
+       ath_hal_ini_bank_setup(priv->Bank2Data, &AH5416(ah)->ah_ini_bank2, 1);
+
+       /* Setup Bank 3 Write */
+       ath_hal_ini_bank_setup(priv->Bank3Data, &AH5416(ah)->ah_ini_bank3, modesIndex);
+
+       /* Setup Bank 6 Write */
+       ath_hal_ini_bank_setup(priv->Bank6Data, &AH5416(ah)->ah_ini_bank6, modesIndex);
+
+       /* Only the 5 or 2 GHz OB/DB need to be set for a mode */
+       if (IS_CHAN_2GHZ(chan)) {
+               ar5416ModifyRfBuffer(priv->Bank6Data,
+                   ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 3, 197, 0);
+               ar5416ModifyRfBuffer(priv->Bank6Data,
+                   ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL), 3, 194, 0);
+       } else {
+               ar5416ModifyRfBuffer(priv->Bank6Data,
+                   ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 3, 203, 0);
+               ar5416ModifyRfBuffer(priv->Bank6Data,
+                   ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL), 3, 200, 0);
+       }
+       /* Setup Bank 7 Setup */
+       ath_hal_ini_bank_setup(priv->Bank7Data, &AH5416(ah)->ah_ini_bank7, 1);
+
+       /* Write Analog registers */
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank0,
+           priv->Bank0Data, 0);
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank1,
+           priv->Bank1Data, writes);
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank2,
+           priv->Bank2Data, writes);
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank3,
+           priv->Bank3Data, writes);
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6,
+           priv->Bank6Data, writes);
+       (void) ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank7,
+           priv->Bank7Data, writes);
+
+       return AH_TRUE;
+#undef  RF_BANK_SETUP
+}
+
+/*
+ * Read the transmit power levels from the structures taken from EEPROM
+ * Interpolate read transmit power values for this channel
+ * Organize the transmit power values into a table for writing into the hardware
+ */
+
+static HAL_BOOL
+ar2133SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax,
+       HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain)
+{
+       return AH_TRUE;
+}
+
+#if 0
+static int16_t
+ar2133GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data)
+{
+    int i, minIndex;
+    int16_t minGain,minPwr,minPcdac,retVal;
+
+    /* Assume NUM_POINTS_XPD0 > 0 */
+    minGain = data->pDataPerXPD[0].xpd_gain;
+    for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) {
+        if (data->pDataPerXPD[i].xpd_gain < minGain) {
+            minIndex = i;
+            minGain = data->pDataPerXPD[i].xpd_gain;
+        }
+    }
+    minPwr = data->pDataPerXPD[minIndex].pwr_t4[0];
+    minPcdac = data->pDataPerXPD[minIndex].pcdac[0];
+    for (i=1; i<NUM_POINTS_XPD0; i++) {
+        if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) {
+            minPwr = data->pDataPerXPD[minIndex].pwr_t4[i];
+            minPcdac = data->pDataPerXPD[minIndex].pcdac[i];
+        }
+    }
+    retVal = minPwr - (minPcdac*2);
+    return(retVal);
+}
+#endif
+
+static HAL_BOOL
+ar2133GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow,
+                int16_t *minPow)
+{
+#if 0
+    struct ath_hal_5212 *ahp = AH5212(ah);
+    int numChannels=0,i,last;
+    int totalD, totalF,totalMin;
+    EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL;
+    EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL;
+
+    *maxPow = 0;
+    if (IS_CHAN_A(chan)) {
+        powerArray = ahp->ah_modePowerArray5112;
+        data = powerArray[headerInfo11A].pDataPerChannel;
+        numChannels = powerArray[headerInfo11A].numChannels;
+    } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) {
+        /* XXX - is this correct? Should we also use the same power for turbo G? */
+        powerArray = ahp->ah_modePowerArray5112;
+        data = powerArray[headerInfo11G].pDataPerChannel;
+        numChannels = powerArray[headerInfo11G].numChannels;
+    } else if (IS_CHAN_B(chan)) {
+        powerArray = ahp->ah_modePowerArray5112;
+        data = powerArray[headerInfo11B].pDataPerChannel;
+        numChannels = powerArray[headerInfo11B].numChannels;
+    } else {
+        return (AH_TRUE);
+    }
+    /* Make sure the channel is in the range of the TP values
+     *  (freq piers)
+     */
+    if ((numChannels < 1) ||
+        (chan->channel < data[0].channelValue) ||
+        (chan->channel > data[numChannels-1].channelValue))
+        return(AH_FALSE);
+
+    /* Linearly interpolate the power value now */
+    for (last=0,i=0;
+         (i<numChannels) && (chan->channel > data[i].channelValue);
+         last=i++);
+    totalD = data[i].channelValue - data[last].channelValue;
+    if (totalD > 0) {
+        totalF = data[i].maxPower_t4 - data[last].maxPower_t4;
+        *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD);
+
+        totalMin = ar2133GetMinPower(ah,&data[i]) - ar2133GetMinPower(ah, &data[last]);
+        *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2133GetMinPower(ah, &data[last])*totalD)/totalD);
+        return (AH_TRUE);
+    } else {
+        if (chan->channel == data[i].channelValue) {
+            *maxPow = data[i].maxPower_t4;
+            *minPow = ar2133GetMinPower(ah, &data[i]);
+            return(AH_TRUE);
+        } else
+            return(AH_FALSE);
+    }
+#else
+    *maxPow = *minPow = 0;
+       return AH_FALSE;
+#endif
+}
+
+static void
+ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[])
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       int16_t nf;
+
+       switch (ahp->ah_rx_chainmask) {
+        case 0x7:
+               nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ctl] [chain 2] is %d\n", nf);
+               nfarray[4] = nf;
+
+               nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ext] [chain 2] is %d\n", nf);
+               nfarray[5] = nf;
+               /* fall thru... */
+        case 0x3:
+        case 0x5:
+               nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ctl] [chain 1] is %d\n", nf);
+               nfarray[2] = nf;
+
+
+               nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ext] [chain 1] is %d\n", nf);
+               nfarray[3] = nf;
+               /* fall thru... */
+        case 0x1:
+               nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ctl] [chain 0] is %d\n", nf);
+               nfarray[0] = nf;
+
+               nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ext] [chain 0] is %d\n", nf);
+               nfarray[1] = nf;
+
+               break;
+       }
+}
+
+/*
+ * Adjust NF based on statistical values for 5GHz frequencies.
+ * Stubbed:Not used by Fowl
+ */
+int16_t
+ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
+{
+       return 0;
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar2133RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for analog bank scratch buffers
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+HAL_BOOL
+ar2133RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar2133State *priv;
+       uint32_t *bankData;
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar2133State)
+           + AH5416(ah)->ah_ini_bank0.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank1.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank2.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank3.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank6.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank7.rows * sizeof(uint32_t)
+       );
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar2133RfDetach;
+       priv->base.writeRegs            = ar2133WriteRegs;
+       priv->base.getRfBank            = ar2133GetRfBank;
+       priv->base.setChannel           = ar2133SetChannel;
+       priv->base.setRfRegs            = ar2133SetRfRegs;
+       priv->base.setPowerTable        = ar2133SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar2133GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar2133GetNfAdjust;
+
+       bankData = (uint32_t *) &priv[1];
+       priv->Bank0Data = bankData, bankData += AH5416(ah)->ah_ini_bank0.rows;
+       priv->Bank1Data = bankData, bankData += AH5416(ah)->ah_ini_bank1.rows;
+       priv->Bank2Data = bankData, bankData += AH5416(ah)->ah_ini_bank2.rows;
+       priv->Bank3Data = bankData, bankData += AH5416(ah)->ah_ini_bank3.rows;
+       priv->Bank6Data = bankData, bankData += AH5416(ah)->ah_ini_bank6.rows;
+       priv->Bank7Data = bankData, bankData += AH5416(ah)->ah_ini_bank7.rows;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+       /*
+        * Set noise floor adjust method; we arrange a
+        * direct call instead of thunking.
+        */
+       AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust;
+       AH_PRIVATE(ah)->ah_getNoiseFloor = ar2133GetNoiseFloor;
+
+       return AH_TRUE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416.h   2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _ATH_AR5416_H_
+#define _ATH_AR5416_H_
+
+#include "ar5212/ar5212.h"
+#include "ar5416_cal.h"
+
+#define        AR5416_MAGIC    0x20065416
+
+enum {
+       HAL_RESET_POWER_ON,
+       HAL_RESET_WARM,
+       HAL_RESET_COLD,
+};
+
+typedef struct {
+       uint16_t        synth_center;
+       uint16_t        ctl_center;
+       uint16_t        ext_center;
+} CHAN_CENTERS;
+
+#define        AR5416_DEFAULT_RXCHAINMASK      7
+#define        AR5416_DEFAULT_TXCHAINMASK      1
+#define        AR5416_MAX_RATE_POWER           63
+#define        AR5416_KEYTABLE_SIZE            128
+
+#define        AR5416_CCA_MAX_GOOD_VALUE       -85
+#define        AR5416_CCA_MAX_HIGH_VALUE       -62
+#define        AR5416_CCA_MIN_BAD_VALUE        -140
+
+struct ath_hal_5416 {
+       struct ath_hal_5212 ah_5212;
+
+       /* NB: RF data setup at attach */
+       HAL_INI_ARRAY   ah_ini_bb_rfgain;
+       HAL_INI_ARRAY   ah_ini_bank0;
+       HAL_INI_ARRAY   ah_ini_bank1;
+       HAL_INI_ARRAY   ah_ini_bank2;
+       HAL_INI_ARRAY   ah_ini_bank3;
+       HAL_INI_ARRAY   ah_ini_bank6;
+       HAL_INI_ARRAY   ah_ini_bank7;
+       HAL_INI_ARRAY   ah_ini_addac;
+
+       u_int           ah_globaltxtimeout;     /* global tx timeout */
+       int             ah_hangs;               /* h/w hangs state */
+       uint8_t         ah_keytype[AR5416_KEYTABLE_SIZE];
+       /*
+        * Extension Channel Rx Clear State
+        */
+       uint32_t        ah_cycleCount;
+       uint32_t        ah_ctlBusy;
+       uint32_t        ah_extBusy;
+       uint32_t        ah_rx_chainmask;
+       uint32_t        ah_tx_chainmask;
+
+       struct ar5416PerCal ah_cal;             /* periodic calibration state */
+};
+#define        AH5416(_ah)     ((struct ath_hal_5416 *)(_ah))
+
+#define IS_5416_PCI(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCI)
+#define IS_5416_PCIE(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCIE)
+#undef IS_PCIE
+#define IS_PCIE(ah) (IS_5416_PCIE(ah))
+
+extern HAL_BOOL ar2133RfAttach(struct ath_hal *, HAL_STATUS *);
+
+struct ath_hal;
+
+extern struct ath_hal * ar5416Attach(uint16_t devid, HAL_SOFTC sc,
+               HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status);
+extern void ar5416InitState(struct ath_hal_5416 *, uint16_t devid,
+               HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh,
+               HAL_STATUS *status);
+extern void ar5416Detach(struct ath_hal *ah);
+extern HAL_BOOL ar5416FillCapabilityInfo(struct ath_hal *ah);
+
+#define        IS_5GHZ_FAST_CLOCK_EN(_ah, _c) \
+       (IS_CHAN_5GHZ(_c) && ath_hal_eepromGetFlag(ah, AR_EEP_FSTCLK_5G))
+
+extern void ar5416AniAttach(struct ath_hal *, const struct ar5212AniParams *,
+               const struct ar5212AniParams *, HAL_BOOL ena);
+extern void ar5416AniDetach(struct ath_hal *);
+extern HAL_BOOL ar5416AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param);
+extern HAL_BOOL ar5416AniSetParams(struct ath_hal *,
+               const struct ar5212AniParams *, const struct ar5212AniParams *);
+extern void ar5416ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *);
+extern void ar5416AniPoll(struct ath_hal *, const HAL_NODE_STATS *,
+                            HAL_CHANNEL *);
+extern void ar5416AniReset(struct ath_hal *, HAL_CHANNEL_INTERNAL *,
+               HAL_OPMODE, int);
+
+extern void ar5416SetBeaconTimers(struct ath_hal *, const HAL_BEACON_TIMERS *);
+extern void ar5416BeaconInit(struct ath_hal *ah,
+               uint32_t next_beacon, uint32_t beacon_period);
+extern void ar5416ResetStaBeaconTimers(struct ath_hal *ah);
+extern void ar5416SetStaBeaconTimers(struct ath_hal *ah,
+               const HAL_BEACON_STATE *);
+
+extern HAL_BOOL ar5416EepromRead(struct ath_hal *, u_int off, uint16_t *data);
+extern HAL_BOOL ar5416EepromWrite(struct ath_hal *, u_int off, uint16_t data);
+
+extern HAL_BOOL ar5416IsInterruptPending(struct ath_hal *ah);
+extern HAL_BOOL ar5416GetPendingInterrupts(struct ath_hal *, HAL_INT *masked);
+extern HAL_INT ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints);
+
+extern HAL_BOOL ar5416GpioCfgOutput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5416GpioCfgInput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5416GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val);
+extern uint32_t ar5416GpioGet(struct ath_hal *ah, uint32_t gpio);
+extern void ar5416GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel);
+
+extern u_int ar5416GetWirelessModes(struct ath_hal *ah);
+extern void ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state);
+extern void ar5416ResetTsf(struct ath_hal *ah);
+extern HAL_BOOL ar5416SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
+extern HAL_BOOL ar5416SetDecompMask(struct ath_hal *, uint16_t, int);
+extern void ar5416SetCoverageClass(struct ath_hal *, uint8_t, int);
+extern uint32_t ar5416Get11nExtBusy(struct ath_hal *ah);
+extern void ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode);
+extern HAL_HT_RXCLEAR ar5416Get11nRxClear(struct ath_hal *ah);
+extern void ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear);
+extern HAL_STATUS ar5416GetCapability(struct ath_hal *ah,
+           HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result);
+extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request,
+           const void *args, uint32_t argsize,
+           void **result, uint32_t *resultsize);
+
+extern HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
+               int setChip);
+extern HAL_POWER_MODE ar5416GetPowerMode(struct ath_hal *ah);
+extern HAL_BOOL ar5416GetPowerStatus(struct ath_hal *ah);
+
+extern HAL_BOOL ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry);
+extern HAL_BOOL ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
+              const HAL_KEYVAL *k, const uint8_t *mac, int xorKey);
+
+extern void ar5416StartPcuReceive(struct ath_hal *ah);
+extern void ar5416StopPcuReceive(struct ath_hal *ah);
+extern HAL_BOOL ar5416SetupRxDesc(struct ath_hal *,
+               struct ath_desc *, uint32_t size, u_int flags);
+extern HAL_STATUS ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *,
+               uint32_t, struct ath_desc *, uint64_t,
+               struct ath_rx_status *);
+
+extern HAL_BOOL ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+               HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status);
+extern HAL_BOOL ar5416PhyDisable(struct ath_hal *ah);
+extern HAL_RFGAIN ar5416GetRfgain(struct ath_hal *ah);
+extern HAL_BOOL ar5416Disable(struct ath_hal *ah);
+extern HAL_BOOL ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *);
+extern HAL_BOOL ar5416SetResetReg(struct ath_hal *, uint32_t type);
+extern HAL_BOOL ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit);
+extern HAL_BOOL ar5416GetChipPowerLimits(struct ath_hal *ah,
+               HAL_CHANNEL *chans, uint32_t nchans);
+extern void ar5416GetChannelCenters(struct ath_hal *,
+               HAL_CHANNEL_INTERNAL *chan, CHAN_CENTERS *centers);
+
+extern HAL_BOOL ar5416StopTxDma(struct ath_hal *ah, u_int q);
+extern HAL_BOOL ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+               u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower,
+               u_int txRate0, u_int txTries0,
+               u_int keyIx, u_int antMode, u_int flags,
+               u_int rtsctsRate, u_int rtsctsDuration,
+               u_int compicvLen, u_int compivLen, u_int comp);
+extern HAL_BOOL ar5416SetupXTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int txRate1, u_int txRetries1,
+               u_int txRate2, u_int txRetries2,
+               u_int txRate3, u_int txRetries3);
+extern HAL_BOOL ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+               u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+               const struct ath_desc *ds0);
+extern HAL_STATUS ar5416ProcTxDesc(struct ath_hal *ah,
+               struct ath_desc *, struct ath_tx_status *);
+
+extern const HAL_RATE_TABLE *ar5416GetRateTable(struct ath_hal *, u_int mode);
+#endif /* _ATH_AR5416_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416.ini 2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416.ini,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+/* Auto Generated PCI Register Writes.  Created: 09/20/06 */
+
+static const uint32_t ar5416Modes[][6] = {
+   /* Register    A           A-20/40     G-20/40     G           G-Turbo    */
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 },
+    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009844, 0x1372161e, 0x13721c1e, 0x13721c30, 0x137216a4, 0x13721c25 },
+    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x00009850, 0x6c28b4e0, 0x6c28b4e0, 0x6d68b0de, 0x6d68b0de, 0x6c28b0de },
+    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
+    { 0x0000985c, 0x313a5d5e, 0x313a5d5e, 0x313a605e, 0x313a605e, 0x313a5d5e },
+    { 0x00009860, 0x00049d10, 0x00049d10, 0x00049d20, 0x00049d20, 0x00049d10 },
+    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000370 },
+    { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a19, 0xd0058a13, 0xd0058a0b },
+    { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
+#ifdef TB243
+    { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 },
+#else
+    { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+    { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+    { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+#ifdef __LINUX_ARM_ARCH__
+    { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
+#else
+    { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
+#endif
+#endif
+    { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 },
+    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, 0x00000440 },
+    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
+    { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
+    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
+    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
+    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
+    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
+    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
+    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
+    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
+    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
+    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
+    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
+    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const uint32_t ar5416Common[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+#ifdef AR9100
+    { 0x00020010, 0x00000000 },
+#else
+    { 0x00007010, 0x00000000 },
+#endif
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0x00000000 },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c4, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x00008300, 0x00000000 },
+    { 0x00008304, 0x00000000 },
+    { 0x00008308, 0x00000000 },
+    { 0x0000830c, 0x00000000 },
+    { 0x00008310, 0x00000000 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008318, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00000000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xad848e19 },
+    { 0x00009810, 0x7d14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x00009840, 0x206a016e },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009854, 0x00000859 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x05100000 },
+    { 0x0000a920, 0x05100000 },
+    { 0x0000b920, 0x05100000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280b212 },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5d50e188 },
+    { 0x00009958, 0x00081fff },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x0000c968, 0x000003ce },
+    { 0x00009970, 0x190c0514 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x001fff00 },
+    { 0x000099ac, 0x000000c4 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000200 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x000000aa },
+    { 0x000099fc, 0x00001042 },
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b28, 0x0000000c },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b38, 0x00000012 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b64, 0x00000021 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b8c, 0x0000002d },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009b9c, 0x00000033 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+    { 0x0000a210, 0x40806333 },
+    { 0x0000a214, 0x00106c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x018830c6 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x00000bb5 },
+    { 0x0000a22c, 0x00000011 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000c26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x051701ce },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa1f },
+    { 0x0000d35c, 0x066c420f },
+    { 0x0000d360, 0x0f282207 },
+    { 0x0000d364, 0x17601685 },
+    { 0x0000d368, 0x1f801104 },
+    { 0x0000d36c, 0x37a00c03 },
+    { 0x0000d370, 0x3fc40883 },
+    { 0x0000d374, 0x57c00803 },
+    { 0x0000d378, 0x5fd80682 },
+    { 0x0000d37c, 0x7fe00482 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x08000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+};
+
+static const uint32_t ar5416Bank0[][2] = {
+    { 0x000098b0, 0x1e5795e5 },
+    { 0x000098e0, 0x02008020 },
+};
+
+static const uint32_t ar5416BB_RfGain[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000040, 0x00000040 },
+    { 0x00009a08, 0x00000080, 0x00000080 },
+    { 0x00009a0c, 0x000001a1, 0x00000141 },
+    { 0x00009a10, 0x000001e1, 0x00000181 },
+    { 0x00009a14, 0x00000021, 0x000001c1 },
+    { 0x00009a18, 0x00000061, 0x00000001 },
+    { 0x00009a1c, 0x00000168, 0x00000041 },
+    { 0x00009a20, 0x000001a8, 0x000001a8 },
+    { 0x00009a24, 0x000001e8, 0x000001e8 },
+    { 0x00009a28, 0x00000028, 0x00000028 },
+    { 0x00009a2c, 0x00000068, 0x00000068 },
+    { 0x00009a30, 0x00000189, 0x000000a8 },
+    { 0x00009a34, 0x000001c9, 0x00000169 },
+    { 0x00009a38, 0x00000009, 0x000001a9 },
+    { 0x00009a3c, 0x00000049, 0x000001e9 },
+    { 0x00009a40, 0x00000089, 0x00000029 },
+    { 0x00009a44, 0x00000170, 0x00000069 },
+    { 0x00009a48, 0x000001b0, 0x00000190 },
+    { 0x00009a4c, 0x000001f0, 0x000001d0 },
+    { 0x00009a50, 0x00000030, 0x00000010 },
+    { 0x00009a54, 0x00000070, 0x00000050 },
+    { 0x00009a58, 0x00000191, 0x00000090 },
+    { 0x00009a5c, 0x000001d1, 0x00000151 },
+    { 0x00009a60, 0x00000011, 0x00000191 },
+    { 0x00009a64, 0x00000051, 0x000001d1 },
+    { 0x00009a68, 0x00000091, 0x00000011 },
+    { 0x00009a6c, 0x000001b8, 0x00000051 },
+    { 0x00009a70, 0x000001f8, 0x00000198 },
+    { 0x00009a74, 0x00000038, 0x000001d8 },
+    { 0x00009a78, 0x00000078, 0x00000018 },
+    { 0x00009a7c, 0x00000199, 0x00000058 },
+    { 0x00009a80, 0x000001d9, 0x00000098 },
+    { 0x00009a84, 0x00000019, 0x00000159 },
+    { 0x00009a88, 0x00000059, 0x00000199 },
+    { 0x00009a8c, 0x00000099, 0x000001d9 },
+    { 0x00009a90, 0x000000d9, 0x00000019 },
+    { 0x00009a94, 0x000000f9, 0x00000059 },
+    { 0x00009a98, 0x000000f9, 0x00000099 },
+    { 0x00009a9c, 0x000000f9, 0x000000d9 },
+    { 0x00009aa0, 0x000000f9, 0x000000f9 },
+    { 0x00009aa4, 0x000000f9, 0x000000f9 },
+    { 0x00009aa8, 0x000000f9, 0x000000f9 },
+    { 0x00009aac, 0x000000f9, 0x000000f9 },
+    { 0x00009ab0, 0x000000f9, 0x000000f9 },
+    { 0x00009ab4, 0x000000f9, 0x000000f9 },
+    { 0x00009ab8, 0x000000f9, 0x000000f9 },
+    { 0x00009abc, 0x000000f9, 0x000000f9 },
+    { 0x00009ac0, 0x000000f9, 0x000000f9 },
+    { 0x00009ac4, 0x000000f9, 0x000000f9 },
+    { 0x00009ac8, 0x000000f9, 0x000000f9 },
+    { 0x00009acc, 0x000000f9, 0x000000f9 },
+    { 0x00009ad0, 0x000000f9, 0x000000f9 },
+    { 0x00009ad4, 0x000000f9, 0x000000f9 },
+    { 0x00009ad8, 0x000000f9, 0x000000f9 },
+    { 0x00009adc, 0x000000f9, 0x000000f9 },
+    { 0x00009ae0, 0x000000f9, 0x000000f9 },
+    { 0x00009ae4, 0x000000f9, 0x000000f9 },
+    { 0x00009ae8, 0x000000f9, 0x000000f9 },
+    { 0x00009aec, 0x000000f9, 0x000000f9 },
+    { 0x00009af0, 0x000000f9, 0x000000f9 },
+    { 0x00009af4, 0x000000f9, 0x000000f9 },
+    { 0x00009af8, 0x000000f9, 0x000000f9 },
+    { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const uint32_t ar5416Bank1[][2] = {
+    { 0x000098b0, 0x02108421 },
+    { 0x000098ec, 0x00000008 },
+};
+
+static const uint32_t ar5416Bank2[][2] = {
+    { 0x000098b0, 0x0e73ff17 },
+    { 0x000098e0, 0x00000420 },
+};
+
+static const uint32_t ar5416Bank3[][3] = {
+    { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+#ifdef USE_NONTPC_BANK
+static const uint32_t ar5416Bank6[][3] = {
+/*    Reg      A            G            */
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x004210a2, 0x004210a2 },
+    { 0x0000989c, 0x0014008f, 0x0014008f },
+    { 0x0000989c, 0x00c40003, 0x00c40003 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000f1, 0x000000f1 },
+    { 0x0000989c, 0x00002081, 0x00002081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+#else
+/* TPC bank */
+static const uint32_t ar5416Bank6[][3] = {
+/*    Reg      A            G            */
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x00421022, 0x00421022 },
+    { 0x0000989c, 0x001400df, 0x001400df },
+    { 0x0000989c, 0x00c40002, 0x00c40002 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000e1, 0x000000e1 },
+    { 0x0000989c, 0x00002081, 0x00002081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+#endif
+
+static const uint32_t ar5416Bank7[][2] = {
+    { 0x0000989c, 0x00000500 },
+    { 0x0000989c, 0x00000800 },
+    { 0x000098cc, 0x0000000e },
+};
+
+static const uint32_t ar5416Addac[][2] = {
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000003 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x0000000c },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000030 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000060 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000058 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x098c4,  0x00000000 },
+};
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_ani.c       2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,886 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_ani.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+/*
+ * XXX this is virtually the same code as for 5212; we reuse
+ * storage in the 5212 state block; need to refactor.
+ */
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/*
+ * Anti noise immunity support.  We track phy errors and react
+ * to excessive errors by adjusting the noise immunity parameters.
+ */
+
+#define HAL_EP_RND(x, mul) \
+       ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+#define        BEACON_RSSI(ahp) \
+       HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \
+               HAL_RSSI_EP_MULTIPLIER)
+
+/*
+ * ANI processing tunes radio parameters according to PHY errors
+ * and related information.  This is done for for noise and spur
+ * immunity in all operating modes if the device indicates it's
+ * capable at attach time.  In addition, when there is a reference
+ * rssi value (e.g. beacon frames from an ap in station mode)
+ * further tuning is done.
+ *
+ * ANI_ENA indicates whether any ANI processing should be done;
+ * this is specified at attach time.
+ *
+ * ANI_ENA_RSSI indicates whether rssi-based processing should
+ * done, this is enabled based on operating mode and is meaningful
+ * only if ANI_ENA is true.
+ *
+ * ANI parameters are typically controlled only by the hal.  The
+ * AniControl interface however permits manual tuning through the
+ * diagnostic api.
+ */
+#define ANI_ENA(ah) \
+       (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA)
+#define ANI_ENA_RSSI(ah) \
+       (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA)
+
+#define        ah_mibStats     ah_stats.ast_mibstats
+
+static void
+enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: "
+           "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n",
+           __func__, params->ofdmPhyErrBase, params->cckPhyErrBase);
+
+       OS_REG_WRITE(ah, AR_FILTOFDM, 0);
+       OS_REG_WRITE(ah, AR_FILTCCK, 0);
+
+       OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/
+       ar5212EnableMibCounters(ah);                    /* enable everything */
+}
+
+static void
+disableAniMIBCounters(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n");
+
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */
+       ar5212DisableMibCounters(ah);                   /* disable everything */
+
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, 0);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, 0);
+}
+
+/*
+ * This routine returns the index into the aniState array that
+ * corresponds to the channel in *chan.  If no match is found and the
+ * array is still not fully utilized, a new entry is created for the
+ * channel.  We assume the attach function has already initialized the
+ * ah_ani values and only the channel field needs to be set.
+ */
+static int
+ar5416GetAniChannelIndex(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+#define N(a)     (sizeof(a) / sizeof(a[0]))
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       int i;
+
+       for (i = 0; i < N(ahp->ah_ani); i++) {
+               struct ar5212AniState *asp = &ahp->ah_ani[i];
+               if (asp->c.channel == chan->channel)
+                       return i;
+               if (asp->c.channel == 0) {
+                       asp->c.channel = chan->channel;
+                       asp->c.channelFlags = chan->channelFlags;
+                       asp->c.privFlags = chan->privFlags;
+                       asp->isSetup = AH_FALSE;
+                       if (IS_CHAN_2GHZ(chan))
+                               asp->params = &ahp->ah_aniParams24;
+                       else
+                               asp->params = &ahp->ah_aniParams5;
+                       return i;
+               }
+       }
+       /* XXX statistic */
+       HALDEBUG(ah, HAL_DEBUG_ANY,
+           "No more channel states left. Using channel 0\n");
+       return 0;               /* XXX gotta return something valid */
+#undef N
+}
+
+static void
+setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params)
+{
+       if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "OFDM Trigger %d is too high for hw counters, using max\n",
+                   params->ofdmTrigHigh);
+               params->ofdmPhyErrBase = 0;
+       } else
+               params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh;
+       if (params->cckTrigHigh >= AR_PHY_COUNTMAX) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "CCK Trigger %d is too high for hw counters, using max\n",
+                   params->cckTrigHigh);
+               params->cckPhyErrBase = 0;
+       } else
+               params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh;
+}
+
+/*
+ * Setup ANI handling.  Sets all thresholds and reset the
+ * channel statistics.  Note that ar5416AniReset should be
+ * called by ar5416Reset before anything else happens and
+ * that's where we force initial settings.
+ */
+void
+ar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24,
+       const struct ar5212AniParams *params5, HAL_BOOL enable)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       if (params24 != AH_NULL) {
+               OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));
+               setPhyErrBase(ah, &ahp->ah_aniParams24);
+       }
+       if (params5 != AH_NULL) {
+               OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));
+               setPhyErrBase(ah, &ahp->ah_aniParams5);
+       }
+
+       OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));
+       /* Enable MIB Counters */
+       enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/);
+
+       if (enable) {           /* Enable ani now */
+               HALASSERT(params24 != AH_NULL && params5 != AH_NULL);
+               ahp->ah_procPhyErr |= HAL_ANI_ENA;
+       } else {
+               ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
+       }
+}
+
+/*
+ * Cleanup any ANI state setup.
+ */
+void
+ar5416AniDetach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n");
+       disableAniMIBCounters(ah);
+}
+
+/*
+ * Control Adaptive Noise Immunity Parameters
+ */
+HAL_BOOL
+ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
+{
+       typedef int TABLE[];
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState = ahp->ah_curani;
+       const struct ar5212AniParams *params = aniState->params;
+
+       OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);
+
+       switch (cmd) {
+       case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxNoiseImmunityLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxNoiseImmunityLevel);
+                       return AH_FALSE;
+               }
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+                   AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+                   AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+                   AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                   AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]);
+
+               if (level > aniState->noiseImmunityLevel)
+                       ahp->ah_stats.ast_ani_niup++;
+               else if (level < aniState->noiseImmunityLevel)
+                       ahp->ah_stats.ast_ani_nidown++;
+               aniState->noiseImmunityLevel = level;
+               break;
+       }
+       case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
+               static const TABLE m1ThreshLow   = { 127,   50 };
+               static const TABLE m2ThreshLow   = { 127,   40 };
+               static const TABLE m1Thresh      = { 127, 0x4d };
+               static const TABLE m2Thresh      = { 127, 0x40 };
+               static const TABLE m2CountThr    = {  31,   16 };
+               static const TABLE m2CountThrLow = {  63,   48 };
+               u_int on = param ? 1 : 0;
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]);
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                       AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                       AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                       AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                       AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]);
+
+               if (on) {
+                       OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+                               AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               } else {
+                       OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+                               AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               }
+               if (on)
+                       ahp->ah_stats.ast_ani_ofdmon++;
+               else
+                       ahp->ah_stats.ast_ani_ofdmoff++;
+               aniState->ofdmWeakSigDetectOff = !on;
+               break;
+       }
+       case HAL_ANI_CCK_WEAK_SIGNAL_THR: {
+               static const TABLE weakSigThrCck = { 8, 6 };
+               u_int high = param ? 1 : 0;
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+                   AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]);
+               if (high)
+                       ahp->ah_stats.ast_ani_cckhigh++;
+               else
+                       ahp->ah_stats.ast_ani_ccklow++;
+               aniState->cckWeakSigThreshold = high;
+               break;
+       }
+       case HAL_ANI_FIRSTEP_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxFirstepLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxFirstepLevel);
+                       return AH_FALSE;
+               }
+               OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                   AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]);
+               if (level > aniState->firstepLevel)
+                       ahp->ah_stats.ast_ani_stepup++;
+               else if (level < aniState->firstepLevel)
+                       ahp->ah_stats.ast_ani_stepdown++;
+               aniState->firstepLevel = level;
+               break;
+       }
+       case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxSpurImmunityLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxSpurImmunityLevel);
+                       return AH_FALSE;
+               }
+               OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+                   AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]);
+               if (level > aniState->spurImmunityLevel)
+                       ahp->ah_stats.ast_ani_spurup++;
+               else if (level < aniState->spurImmunityLevel)
+                       ahp->ah_stats.ast_ani_spurdown++;
+               aniState->spurImmunityLevel = level;
+               break;
+       }
+       case HAL_ANI_PRESENT:
+               break;
+       case HAL_ANI_MODE:
+               if (param == 0) {
+                       ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
+                       /* Turn off HW counters if we have them */
+                       ar5416AniDetach(ah);
+                       ar5212SetRxFilter(ah,
+                               ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
+               } else {                        /* normal/auto mode */
+                       /* don't mess with state if already enabled */
+                       if (ahp->ah_procPhyErr & HAL_ANI_ENA)
+                               break;
+                       ar5212SetRxFilter(ah,
+                               ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
+                       /* Enable MIB Counters */
+                       enableAniMIBCounters(ah, ahp->ah_curani != AH_NULL ?
+                           ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/);
+                       ahp->ah_procPhyErr |= HAL_ANI_ENA;
+               }
+               break;
+#ifdef AH_PRIVATE_DIAG
+       case HAL_ANI_PHYERR_RESET:
+               ahp->ah_stats.ast_ani_ofdmerrs = 0;
+               ahp->ah_stats.ast_ani_cckerrs = 0;
+               break;
+#endif /* AH_PRIVATE_DIAG */
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n",
+                   __func__, cmd);
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+static void
+ar5416AniOfdmErrTrigger(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(chan != AH_NULL);
+
+       if (!ANI_ENA(ah))
+               return;
+
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       /* First, raise noise immunity level, up to max */
+       if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel + 1);
+               return;
+       }
+       /* then, raise spur immunity level, up to max */
+       if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) {
+               ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel + 1);
+               return;
+       }
+
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi > params->rssiThrHigh) {
+                       /*
+                        * Beacon rssi is high, can turn off ofdm
+                        * weak sig detect.
+                        */
+                       if (!aniState->ofdmWeakSigDetectOff) {
+                               ar5416AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_FALSE);
+                               ar5416AniControl(ah,
+                                   HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
+                               return;
+                       }
+                       /*
+                        * If weak sig detect is already off, as last resort,
+                        * raise firstep level
+                        */
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel + 1);
+                               return;
+                       }
+               } else if (rssi > params->rssiThrLow) {
+                       /*
+                        * Beacon rssi in mid range, need ofdm weak signal
+                        * detect, but we can raise firststepLevel.
+                        */
+                       if (aniState->ofdmWeakSigDetectOff)
+                               ar5416AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_TRUE);
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel)
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                    aniState->firstepLevel + 1);
+                       return;
+               } else {
+                       /*
+                        * Beacon rssi is low, if in 11b/g mode, turn off ofdm
+                        * weak signal detection and zero firstepLevel to
+                        * maximize CCK sensitivity
+                        */
+                       /* XXX can optimize */
+                       if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) {
+                               if (!aniState->ofdmWeakSigDetectOff)
+                                       ar5416AniControl(ah,
+                                           HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                           AH_FALSE);
+                               if (aniState->firstepLevel > 0)
+                                       ar5416AniControl(ah,
+                                            HAL_ANI_FIRSTEP_LEVEL, 0);
+                               return;
+                       }
+               }
+       }
+}
+
+static void
+ar5416AniCckErrTrigger(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(chan != AH_NULL);
+
+       if (!ANI_ENA(ah))
+               return;
+
+       /* first, raise noise immunity level, up to max */
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel + 1);
+               return;
+       }
+
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi >  params->rssiThrLow) {
+                       /*
+                        * Beacon signal in mid and high range,
+                        * raise firstep level.
+                        */
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel)
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel + 1);
+               } else {
+                       /*
+                        * Beacon rssi is low, zero firstep level to maximize
+                        * CCK sensitivity in 11b/g mode.
+                        */
+                       /* XXX can optimize */
+                       if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) {
+                               if (aniState->firstepLevel > 0)
+                                       ar5416AniControl(ah,
+                                           HAL_ANI_FIRSTEP_LEVEL, 0);
+                       }
+               }
+       }
+}
+
+static void
+ar5416AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const struct ar5212AniParams *params = aniState->params;
+
+       aniState->listenTime = 0;
+       /*
+        * NB: these are written on reset based on the
+        *     ini so we must re-write them!
+        */
+       HALDEBUG(ah, HAL_DEBUG_ANI,
+           "%s: Writing ofdmbase=%u   cckbase=%u\n", __func__,
+           params->ofdmPhyErrBase, params->cckPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHY_ERR_1, params->ofdmPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHY_ERR_2, params->cckPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_CCK_TIMING);
+
+       /* Clear the mib counters and save them in the stats */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+       aniState->ofdmPhyErrCount = 0;
+       aniState->cckPhyErrCount = 0;
+}
+
+/*
+ * Restore/reset the ANI parameters and reset the statistics.
+ * This routine must be called for every channel change.
+ *
+ * NOTE: This is where ah_curani is set; other ani code assumes
+ *       it is setup to reflect the current channel.
+ */
+void
+ar5416AniReset(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
+       HAL_OPMODE opmode, int restore)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       uint32_t rxfilter;
+       int index;
+
+       index = ar5416GetAniChannelIndex(ah, chan);
+       aniState = &ahp->ah_ani[index];
+       ahp->ah_curani = aniState;
+#if 0
+       ath_hal_printf(ah,"%s: chan %u/0x%x restore %d setup %d opmode %u\n",
+           __func__, chan->channel, chan->channelFlags, restore,
+           aniState->isSetup, opmode);
+#else
+       HALDEBUG(ah, HAL_DEBUG_ANI,
+           "%s: chan %u/0x%x restore %d setup %d opmode %u\n",
+           __func__, chan->channel, chan->channelFlags, restore,
+           aniState->isSetup, opmode);
+#endif
+       OS_MARK(ah, AH_MARK_ANI_RESET, opmode);
+
+       /*
+        * Turn off PHY error frame delivery while we futz with settings.
+        */
+       rxfilter = ar5212GetRxFilter(ah);
+       ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
+       /*
+        * Automatic processing is done only in station mode right now.
+        */
+       if (opmode == HAL_M_STA)
+               ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA;
+       else
+               ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA;
+       /*
+        * Set all ani parameters.  We either set them to initial
+        * values or restore the previous ones for the channel.
+        * XXX if ANI follows hardware, we don't care what mode we're
+        * XXX in, we should keep the ani parameters
+        */
+       if (restore && aniState->isSetup) {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel);
+               ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel);
+               ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                !aniState->ofdmWeakSigDetectOff);
+               ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
+                                aniState->cckWeakSigThreshold);
+               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                aniState->firstepLevel);
+       } else {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
+               ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
+               ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                       AH_TRUE);
+               ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);
+               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
+               aniState->isSetup = AH_TRUE;
+       }
+       ar5416AniRestart(ah, aniState);
+
+       /* restore RX filter mask */
+       ar5212SetRxFilter(ah, rxfilter);
+}
+
+/*
+ * Process a MIB interrupt.  We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
+void
+ar5416ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t phyCnt1, phyCnt2;
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x "
+           "filtofdm 0x%x filtcck 0x%x\n",
+           __func__, OS_REG_READ(ah, AR_MIBC),
+           OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2),
+           OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK));
+
+       /*
+        * First order of business is to clear whatever caused
+        * the interrupt so we don't keep getting interrupted.
+        * We have the usual mib counters that are reset-on-read
+        * and the additional counters that appeared starting in
+        * Hainan.  We collect the mib counters and explicitly
+        * zero additional counters we are not using.  Anything
+        * else is reset only if it caused the interrupt.
+        */
+       /* NB: these are not reset-on-read */
+       phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);
+       phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);
+       /* not used, always reset them in case they are the cause */
+       OS_REG_WRITE(ah, AR_FILTOFDM, 0);
+       OS_REG_WRITE(ah, AR_FILTCCK, 0);
+       if ((OS_REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING) == 0)
+               OS_REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+
+       /* Clear the mib counters and save them in the stats */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+       ahp->ah_stats.ast_nodestats = *stats;
+
+       /*
+        * Check for an ani stat hitting the trigger threshold.
+        * When this happens we get a MIB interrupt and the top
+        * 2 bits of the counter register will be 0b11, hence
+        * the mask check of phyCnt?.
+        */
+       if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
+           ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+               struct ar5212AniState *aniState = ahp->ah_curani;
+               const struct ar5212AniParams *params = aniState->params;
+               uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+               ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
+               ahp->ah_stats.ast_ani_ofdmerrs +=
+                       ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+               aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+               cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
+               ahp->ah_stats.ast_ani_cckerrs +=
+                       cckPhyErrCnt - aniState->cckPhyErrCount;
+               aniState->cckPhyErrCount = cckPhyErrCnt;
+
+               /*
+                * NB: figure out which counter triggered.  If both
+                * trigger we'll only deal with one as the processing
+                * clobbers the error counter so the trigger threshold
+                * check will never be true.
+                */
+               if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh)
+                       ar5416AniOfdmErrTrigger(ah);
+               if (aniState->cckPhyErrCount > params->cckTrigHigh)
+                       ar5416AniCckErrTrigger(ah);
+               /* NB: always restart to insure the h/w counters are reset */
+               ar5416AniRestart(ah, aniState);
+       }
+}
+
+static void
+ar5416AniLowerImmunity(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(ANI_ENA(ah));
+
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi > params->rssiThrHigh) {
+                       /*
+                        * Beacon signal is high, leave ofdm weak signal
+                        * detection off or it may oscillate.  Let it fall
+                        * through.
+                        */
+               } else if (rssi > params->rssiThrLow) {
+                       /*
+                        * Beacon rssi in mid range, turn on ofdm weak signal
+                        * detection or lower firstep level.
+                        */
+                       if (aniState->ofdmWeakSigDetectOff) {
+                               ar5416AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_TRUE);
+                               return;
+                       }
+                       if (aniState->firstepLevel > 0) {
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel - 1);
+                               return;
+                       }
+               } else {
+                       /*
+                        * Beacon rssi is low, reduce firstep level.
+                        */
+                       if (aniState->firstepLevel > 0) {
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel - 1);
+                               return;
+                       }
+               }
+       }
+       /* then lower spur immunity level, down to zero */
+       if (aniState->spurImmunityLevel > 0) {
+               ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel - 1);
+               return;
+       }
+       /*
+        * if all else fails, lower noise immunity level down to a min value
+        * zero for now
+        */
+       if (aniState->noiseImmunityLevel > 0) {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel - 1);
+               return;
+       }
+}
+
+#define CLOCK_RATE 44000       /* XXX use mac_usec or similar */
+/* convert HW counter values to ms using 11g clock rate, goo9d enough
+   for 11a and Turbo */
+
+/*
+ * Return an approximation of the time spent ``listening'' by
+ * deducting the cycles spent tx'ing and rx'ing from the total
+ * cycle count since our last call.  A return value <0 indicates
+ * an invalid/inconsistent time.
+ */
+static int32_t
+ar5416AniGetListenTime(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       uint32_t txFrameCount, rxFrameCount, cycleCount;
+       int32_t listenTime;
+
+       txFrameCount = OS_REG_READ(ah, AR_TFCNT);
+       rxFrameCount = OS_REG_READ(ah, AR_RFCNT);
+       cycleCount = OS_REG_READ(ah, AR_CCCNT);
+
+       aniState = ahp->ah_curani;
+       if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
+               /*
+                * Cycle counter wrap (or initial call); it's not possible
+                * to accurately calculate a value because the registers
+                * right shift rather than wrap--so punt and return 0.
+                */
+               listenTime = 0;
+               ahp->ah_stats.ast_ani_lzero++;
+       } else {
+               int32_t ccdelta = cycleCount - aniState->cycleCount;
+               int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
+               int32_t tfdelta = txFrameCount - aniState->txFrameCount;
+               listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
+       }
+       aniState->cycleCount = cycleCount;
+       aniState->txFrameCount = txFrameCount;
+       aniState->rxFrameCount = rxFrameCount;
+       return listenTime;
+}
+
+/*
+ * Update ani stats in preparation for listen time processing.
+ */
+static void
+updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const struct ar5212AniParams *params = aniState->params;
+       uint32_t phyCnt1, phyCnt2;
+       int32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+       /* Clear the mib counters and save them in the stats */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+
+       /* NB: these are not reset-on-read */
+       phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);
+       phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);
+
+       /* NB: these are spec'd to never roll-over */
+       ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
+       if (ofdmPhyErrCnt < 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n",
+                   ofdmPhyErrCnt, phyCnt1);
+               ofdmPhyErrCnt = AR_PHY_COUNTMAX;
+       }
+       ahp->ah_stats.ast_ani_ofdmerrs +=
+            ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+       aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+       cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
+       if (cckPhyErrCnt < 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n",
+                   cckPhyErrCnt, phyCnt2);
+               cckPhyErrCnt = AR_PHY_COUNTMAX;
+       }
+       ahp->ah_stats.ast_ani_cckerrs +=
+               cckPhyErrCnt - aniState->cckPhyErrCount;
+       aniState->cckPhyErrCount = cckPhyErrCnt;
+}
+
+/*
+ * Do periodic processing.  This routine is called from the
+ * driver's rx interrupt handler after processing frames.
+ */
+void
+ar5416AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
+               HAL_CHANNEL *chan)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState = ahp->ah_curani;
+       const struct ar5212AniParams *params;
+       int32_t listenTime;
+
+       ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi;
+
+       /* XXX can aniState be null? */
+       if (aniState == AH_NULL)
+               return;
+       if (!ANI_ENA(ah))
+               return;
+
+       listenTime = ar5416AniGetListenTime(ah);
+       if (listenTime < 0) {
+               ahp->ah_stats.ast_ani_lneg++;
+               /* restart ANI period if listenTime is invalid */
+               ar5416AniRestart(ah, aniState);
+       }
+       /* XXX beware of overflow? */
+       aniState->listenTime += listenTime;
+
+       OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime);
+
+       params = aniState->params;
+       if (aniState->listenTime > 5*params->period) {
+               /*
+                * Check to see if need to lower immunity if
+                * 5 aniPeriods have passed
+                */
+               updateMIBStats(ah, aniState);
+               if (aniState->ofdmPhyErrCount <= aniState->listenTime *
+                   params->ofdmTrigLow/1000 &&
+                   aniState->cckPhyErrCount <= aniState->listenTime *
+                   params->cckTrigLow/1000)
+                       ar5416AniLowerImmunity(ah);
+               ar5416AniRestart(ah, aniState);
+       } else if (aniState->listenTime > params->period) {
+               updateMIBStats(ah, aniState);
+               /* check to see if need to raise immunity */
+               if (aniState->ofdmPhyErrCount > aniState->listenTime *
+                   params->ofdmTrigHigh / 1000) {
+                       ar5416AniOfdmErrTrigger(ah);
+                       ar5416AniRestart(ah, aniState);
+               } else if (aniState->cckPhyErrCount > aniState->listenTime *
+                          params->cckTrigHigh / 1000) {
+                       ar5416AniCckErrTrigger(ah);
+                       ar5416AniRestart(ah, aniState);
+               }
+       }
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_attach.c    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_attach.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#include "ar5416/ar5416.ini"
+
+static void
+ar5416AniSetup(struct ath_hal *ah)
+{
+       static const struct ar5212AniParams aniparams = {
+               .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
+               .totalSizeDesired       = { -55, -55, -55, -55, -62 },
+               .coarseHigh             = { -14, -14, -14, -14, -12 },
+               .coarseLow              = { -64, -64, -64, -64, -70 },
+               .firpwr                 = { -78, -78, -78, -78, -80 },
+               .maxSpurImmunityLevel   = 2,
+               .cycPwrThr1             = { 2, 4, 6 },
+               .maxFirstepLevel        = 2,    /* levels 0..2 */
+               .firstep                = { 0, 4, 8 },
+               .ofdmTrigHigh           = 500,
+               .ofdmTrigLow            = 200,
+               .cckTrigHigh            = 200,
+               .cckTrigLow             = 100,
+               .rssiThrHigh            = 40,
+               .rssiThrLow             = 7,
+               .period                 = 100,
+       };
+       /* NB: ANI is not enabled yet */
+       ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE);
+}
+
+/*
+ * Attach for an AR5416 part.
+ */
+void
+ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp;
+       struct ath_hal *ah;
+
+       ahp = &ahp5416->ah_5212;
+       ar5212InitState(ahp, devid, sc, st, sh, status);
+       ah = &ahp->ah_priv.h;
+
+       /* override 5212 methods for our needs */
+       ah->ah_magic                    = AR5416_MAGIC;
+       ah->ah_getRateTable             = ar5416GetRateTable;
+       ah->ah_detach                   = ar5416Detach;
+
+       /* Reset functions */
+       ah->ah_reset                    = ar5416Reset;
+       ah->ah_phyDisable               = ar5416PhyDisable;
+       ah->ah_disable                  = ar5416Disable;
+       ah->ah_perCalibration           = ar5416PerCalibration;
+       ah->ah_perCalibrationN          = ar5416PerCalibrationN,
+       ah->ah_resetCalValid            = ar5416ResetCalValid,
+       ah->ah_setTxPowerLimit          = ar5416SetTxPowerLimit;
+
+       /* Transmit functions */
+       ah->ah_stopTxDma                = ar5416StopTxDma;
+       ah->ah_setupTxDesc              = ar5416SetupTxDesc;
+       ah->ah_setupXTxDesc             = ar5416SetupXTxDesc;
+       ah->ah_fillTxDesc               = ar5416FillTxDesc;
+       ah->ah_procTxDesc               = ar5416ProcTxDesc;
+
+       /* Receive Functions */
+       ah->ah_startPcuReceive          = ar5416StartPcuReceive;
+       ah->ah_stopPcuReceive           = ar5416StopPcuReceive;
+       ah->ah_setupRxDesc              = ar5416SetupRxDesc;
+       ah->ah_procRxDesc               = ar5416ProcRxDesc;
+       ah->ah_rxMonitor                = ar5416AniPoll,
+       ah->ah_procMibEvent             = ar5416ProcessMibIntr,
+
+       /* Misc Functions */
+       ah->ah_getDiagState             = ar5416GetDiagState;
+       ah->ah_setLedState              = ar5416SetLedState;
+       ah->ah_gpioCfgOutput            = ar5416GpioCfgOutput;
+       ah->ah_gpioCfgInput             = ar5416GpioCfgInput;
+       ah->ah_gpioGet                  = ar5416GpioGet;
+       ah->ah_gpioSet                  = ar5416GpioSet;
+       ah->ah_gpioSetIntr              = ar5416GpioSetIntr;
+       ah->ah_resetTsf                 = ar5416ResetTsf;
+       ah->ah_getRfGain                = ar5416GetRfgain;
+       ah->ah_setAntennaSwitch         = ar5416SetAntennaSwitch;
+       ah->ah_setDecompMask            = ar5416SetDecompMask;
+       ah->ah_setCoverageClass         = ar5416SetCoverageClass;
+
+       ah->ah_resetKeyCacheEntry       = ar5416ResetKeyCacheEntry;
+       ah->ah_setKeyCacheEntry         = ar5416SetKeyCacheEntry;
+
+       /* Power Management Functions */
+       ah->ah_setPowerMode             = ar5416SetPowerMode;
+
+       /* Beacon Management Functions */
+       ah->ah_setBeaconTimers          = ar5416SetBeaconTimers;
+       ah->ah_beaconInit               = ar5416BeaconInit;
+       ah->ah_setStationBeaconTimers   = ar5416SetStaBeaconTimers;
+       ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers;
+
+       /* XXX 802.11n Functions */
+#if 0
+       ah->ah_chainTxDesc              = ar5416ChainTxDesc;
+       ah->ah_setupFirstTxDesc         = ar5416SetupFirstTxDesc;
+       ah->ah_setupLastTxDesc          = ar5416SetupLastTxDesc;
+       ah->ah_set11nRateScenario       = ar5416Set11nRateScenario;
+       ah->ah_set11nAggrMiddle         = ar5416Set11nAggrMiddle;
+       ah->ah_clr11nAggr               = ar5416Clr11nAggr;
+       ah->ah_set11nBurstDuration      = ar5416Set11nBurstDuration;
+       ah->ah_get11nExtBusy            = ar5416Get11nExtBusy;
+       ah->ah_set11nMac2040            = ar5416Set11nMac2040;
+       ah->ah_get11nRxClear            = ar5416Get11nRxClear;
+       ah->ah_set11nRxClear            = ar5416Set11nRxClear;
+#endif
+
+       /* Interrupt functions */
+       ah->ah_isInterruptPending       = ar5416IsInterruptPending;
+       ah->ah_getPendingInterrupts     = ar5416GetPendingInterrupts;
+       ah->ah_setInterrupts            = ar5416SetInterrupts;
+
+       ahp->ah_priv.ah_getWirelessModes= ar5416GetWirelessModes;
+       ahp->ah_priv.ah_eepromRead      = ar5416EepromRead;
+#ifdef AH_SUPPORT_WRITE_EEPROM
+       ahp->ah_priv.ah_eepromWrite     = ar5416EepromWrite;
+#endif
+       ahp->ah_priv.ah_gpioCfgOutput   = ar5416GpioCfgOutput;
+       ahp->ah_priv.ah_gpioCfgInput    = ar5416GpioCfgInput;
+       ahp->ah_priv.ah_gpioGet         = ar5416GpioGet;
+       ahp->ah_priv.ah_gpioSet         = ar5416GpioSet;
+       ahp->ah_priv.ah_gpioSetIntr     = ar5416GpioSetIntr;
+       ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits;
+
+       /*
+        * Start by setting all Owl devices to 2x2
+        */
+       AH5416(ah)->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK;
+       AH5416(ah)->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK;
+}
+
+/*
+ * Attach for an AR5416 part.
+ */
+struct ath_hal *
+ar5416Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+       struct ath_hal_5416 *ahp5416;
+       struct ath_hal_5212 *ahp;
+       struct ath_hal *ah;
+       uint32_t val;
+       HAL_STATUS ecode;
+       HAL_BOOL rfStatus;
+
+       HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
+           __func__, sc, (void*) st, (void*) sh);
+
+       /* NB: memory is returned zero'd */
+       ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416) +
+               /* extra space for Owl 2.1/2.2 WAR */
+               sizeof(ar5416Addac)
+       );
+       if (ahp5416 == AH_NULL) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                   "%s: cannot allocate memory for state block\n", __func__);
+               *status = HAL_ENOMEM;
+               return AH_NULL;
+       }
+       ar5416InitState(ahp5416, devid, sc, st, sh, status);
+       ahp = &ahp5416->ah_5212;
+       ah = &ahp->ah_priv.h;
+
+       if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
+               /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+       /* Read Revisions from Chips before taking out of reset */
+       val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
+       AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;
+       AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION;
+
+       /* setup common ini data; rf backends handle remainder */
+       HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes, 6);
+       HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common, 2);
+
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac, 2);
+
+       if (!IS_5416V2_2(ah)) {         /* Owl 2.1/2.0 */
+               struct ini {
+                       uint32_t        *data;          /* NB: !const */
+                       int             rows, cols;
+               };
+               /* override CLKDRV value */
+               OS_MEMCPY(&AH5416(ah)[1], ar5416Addac, sizeof(ar5416Addac));
+               AH5416(ah)->ah_ini_addac.data = (uint32_t *) &AH5416(ah)[1];
+               HAL_INI_VAL((struct ini *)&AH5416(ah)->ah_ini_addac, 31, 1) = 0;
+       }
+
+       if (!ar5416ChipReset(ah, AH_NULL)) {    /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",
+                   __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
+
+       if (!ar5212ChipTest(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
+                   __func__);
+               ecode = HAL_ESELFTEST;
+               goto bad;
+       }
+
+       /*
+        * Set correct Baseband to analog shift
+        * setting to access analog chips.
+        */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       /* Read Radio Chip Rev Extract */
+       AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
+       switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
+        case AR_RAD5122_SREV_MAJOR:    /* Fowl: 5G/2x2 */
+        case AR_RAD2122_SREV_MAJOR:    /* Fowl: 2+5G/2x2 */
+        case AR_RAD2133_SREV_MAJOR:    /* Fowl: 2G/3x3 */
+       case AR_RAD5133_SREV_MAJOR:     /* Fowl: 2+5G/3x3 */
+               break;
+       default:
+               if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
+                       /*
+                        * When RF_Silen is used the analog chip is reset.
+                        * So when the system boots with radio switch off
+                        * the RF chip rev reads back as zero and we need
+                        * to use the mac+phy revs to set the radio rev.
+                        */
+                       AH_PRIVATE(ah)->ah_analog5GhzRev =
+                               AR_RAD5133_SREV_MAJOR;
+                       break;
+               }
+               /* NB: silently accept anything in release code per Atheros */
+#ifdef AH_DEBUG
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: 5G Radio Chip Rev 0x%02X is not supported by "
+                   "this driver\n", __func__,
+                   AH_PRIVATE(ah)->ah_analog5GhzRev);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+#endif
+       }
+
+       ecode = ath_hal_v14EepromAttach(ah);
+       if (ecode != HAL_OK)
+               goto bad;
+
+       /*
+        * Got everything we need now to setup the capabilities.
+        */
+       if (!ar5416FillCapabilityInfo(ah)) {
+               ecode = HAL_EEREAD;
+               goto bad;
+       }
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error getting mac address from EEPROM\n", __func__);
+               goto bad;
+        }
+       /* XXX How about the serial number ? */
+       /* Read Reg Domain */
+       AH_PRIVATE(ah)->ah_currentRD =
+           ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
+
+       /*
+        * ah_miscMode is populated by ar5416FillCapabilityInfo()
+        * starting from griffin. Set here to make sure that
+        * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
+        * placed into hardware.
+        */
+       if (ahp->ah_miscMode != 0)
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: Attaching AR2133 radio\n",
+           __func__);
+       rfStatus = ar2133RfAttach(ah, &ecode);
+       if (!rfStatus) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
+                   __func__, ecode);
+               goto bad;
+       }
+
+       ar5416AniSetup(ah);                     /* Anti Noise Immunity */
+       ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
+
+       return ah;
+bad:
+       if (ahp)
+               ar5416Detach((struct ath_hal *) ahp);
+       if (status)
+               *status = ecode;
+       return AH_NULL;
+}
+
+void
+ar5416Detach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
+
+       HALASSERT(ah != AH_NULL);
+       HALASSERT(ah->ah_magic == AR5416_MAGIC);
+
+       ar5416AniDetach(ah);
+       ar5212RfDetach(ah);
+       ah->ah_disable(ah);
+       ar5416SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
+       ath_hal_eepromDetach(ah);
+       ath_hal_free(ah);
+}
+
+/*
+ * Fill all software cached or static hardware state information.
+ * Return failure if capabilities are to come from EEPROM and
+ * cannot be read.
+ */
+HAL_BOOL
+ar5416FillCapabilityInfo(struct ath_hal *ah)
+{
+       struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
+       HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
+       uint16_t val;
+
+       /* Construct wireless mode from EEPROM */
+       pCap->halWirelessModes = 0;
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
+               pCap->halWirelessModes |= HAL_MODE_11A
+                                      |  HAL_MODE_11NA_HT20
+                                      |  HAL_MODE_11NA_HT40PLUS
+                                      |  HAL_MODE_11NA_HT40MINUS
+                                      ;
+       }
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE)) {
+               pCap->halWirelessModes |= HAL_MODE_11G
+                                      |  HAL_MODE_11NG_HT20
+                                      |  HAL_MODE_11NG_HT40PLUS
+                                      |  HAL_MODE_11NG_HT40MINUS
+                                      ;
+               pCap->halWirelessModes |= HAL_MODE_11A
+                                      |  HAL_MODE_11NA_HT20
+                                      |  HAL_MODE_11NA_HT40PLUS
+                                      |  HAL_MODE_11NA_HT40MINUS
+                                      ;
+       }
+
+       pCap->halLow2GhzChan = 2312;
+       pCap->halHigh2GhzChan = 2732;
+
+       pCap->halLow5GhzChan = 4915;
+       pCap->halHigh5GhzChan = 6100;
+
+       pCap->halCipherCkipSupport = AH_FALSE;
+       pCap->halCipherTkipSupport = AH_TRUE;
+       pCap->halCipherAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES);
+
+       pCap->halMicCkipSupport    = AH_FALSE;
+       pCap->halMicTkipSupport    = AH_TRUE;
+       pCap->halMicAesCcmSupport  = ath_hal_eepromGetFlag(ah, AR_EEP_AES);
+       /*
+        * Starting with Griffin TX+RX mic keys can be combined
+        * in one key cache slot.
+        */
+       pCap->halTkipMicTxRxKeySupport = AH_TRUE;
+       pCap->halChanSpreadSupport = AH_TRUE;
+       pCap->halSleepAfterBeaconBroken = AH_TRUE;
+
+       pCap->halCompressSupport = AH_FALSE;
+       pCap->halBurstSupport = AH_TRUE;
+       pCap->halFastFramesSupport = AH_FALSE;  /* XXX? */
+       pCap->halChapTuningSupport = AH_TRUE;
+       pCap->halTurboPrimeSupport = AH_TRUE;
+
+       pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G;
+
+       pCap->halPSPollBroken = AH_TRUE;        /* XXX fixed in later revs? */
+       pCap->halVEOLSupport = AH_TRUE;
+       pCap->halBssIdMaskSupport = AH_TRUE;
+       pCap->halMcastKeySrchSupport = AH_FALSE;
+       pCap->halTsfAddSupport = AH_TRUE;
+
+       if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)
+               pCap->halTotalQueues = val;
+       else
+               pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
+
+       if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK)
+               pCap->halKeyCacheSize = val;
+       else
+               pCap->halKeyCacheSize = AR5416_KEYTABLE_SIZE;
+
+       /* XXX not needed */
+       pCap->halChanHalfRate = AH_FALSE;       /* XXX ? */
+       pCap->halChanQuarterRate = AH_FALSE;    /* XXX ? */
+
+       pCap->halTstampPrecision = 32;
+       pCap->halHwPhyCounterSupport = AH_TRUE;
+
+       pCap->halFastCCSupport = AH_TRUE;
+       pCap->halNumGpioPins = 6;
+       pCap->halWowSupport = AH_FALSE;
+       pCap->halWowMatchPatternExact = AH_FALSE;
+       pCap->halBtCoexSupport = AH_FALSE;      /* XXX need support */
+       pCap->halAutoSleepSupport = AH_FALSE;
+#if 0  /* XXX not yet */
+       pCap->halNumAntCfg2GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_2GHZ);
+       pCap->halNumAntCfg5GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_5GHZ);
+#endif
+       pCap->halHTSupport = AH_TRUE;
+       pCap->halTxChainMask = ath_hal_eepromGet(ah, AR_EEP_TXMASK, AH_NULL);
+       /* XXX CB71 uses GPIO 0 to indicate 3 rx chains */
+       pCap->halRxChainMask = ath_hal_eepromGet(ah, AR_EEP_RXMASK, AH_NULL);
+       pCap->halRtsAggrLimit = 8*1024;         /* Owl 2.0 limit */
+       pCap->halMbssidAggrSupport = AH_TRUE;
+       pCap->halForcePpmSupport = AH_TRUE;
+       pCap->halEnhancedPmSupport = AH_TRUE;
+
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
+           ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
+               /* NB: enabled by default */
+               ahpriv->ah_rfkillEnabled = AH_TRUE;
+               pCap->halRfSilentSupport = AH_TRUE;
+       }
+
+       ahpriv->ah_rxornIsFatal = AH_FALSE;
+
+       return AH_TRUE;
+}
+
+static const char*
+ar5416Probe(uint16_t vendorid, uint16_t devid)
+{
+       if (vendorid == ATHEROS_VENDOR_ID &&
+           (devid == AR5416_DEVID_PCI || devid == AR5416_DEVID_PCIE))
+               return "Atheros 5416";
+       return AH_NULL;
+}
+AH_CHIP(AR5416, ar5416Probe, ar5416Attach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_beacon.c    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_beacon.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#define TU_TO_USEC(_tu)                ((_tu) << 10)
+
+/*
+ * Initialize all of the hardware registers used to
+ * send beacons.  Note that for station operation the
+ * driver calls ar5416SetStaBeaconTimers instead.
+ */
+void
+ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
+{
+       uint32_t bperiod;
+
+       OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bt->bt_nexttbtt));
+       OS_REG_WRITE(ah, AR_NEXT_DBA, TU_TO_USEC(bt->bt_nextdba) >> 3);
+       OS_REG_WRITE(ah, AR_NEXT_SWBA, TU_TO_USEC(bt->bt_nextswba) >> 3);
+       OS_REG_WRITE(ah, AR_NEXT_NDP, TU_TO_USEC(bt->bt_nextatim));
+
+       bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD);
+       OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, bperiod);
+       OS_REG_WRITE(ah, AR_DBA_PERIOD, bperiod);
+       OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod);
+       OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod);
+
+       /*
+        * Reset TSF if required.
+        */
+       if (bt->bt_intval & AR_BEACON_RESET_TSF)
+               ar5416ResetTsf(ah);
+
+       /* enable timers */
+       /* NB: flags == 0 handled specially for backwards compatibility */
+       OS_REG_SET_BIT(ah, AR_TIMER_MODE,
+           bt->bt_flags != 0 ? bt->bt_flags :
+               AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA);
+}
+
+/*
+ * Initializes all of the hardware registers used to
+ * send beacons.  Note that for station operation the
+ * driver calls ar5212SetStaBeaconTimers instead.
+ */
+void
+ar5416BeaconInit(struct ath_hal *ah,
+       uint32_t next_beacon, uint32_t beacon_period)
+{
+       HAL_BEACON_TIMERS bt;
+
+       bt.bt_nexttbtt = next_beacon;
+       /*
+        * TIMER1: in AP/adhoc mode this controls the DMA beacon
+        * alert timer; otherwise it controls the next wakeup time.
+        * TIMER2: in AP mode, it controls the SBA beacon alert
+        * interrupt; otherwise it sets the start of the next CFP.
+        */
+       bt.bt_flags = 0;
+       switch (AH_PRIVATE(ah)->ah_opmode) {
+       case HAL_M_STA:
+       case HAL_M_MONITOR:
+               bt.bt_nextdba = 0xffff;
+               bt.bt_nextswba = 0x7ffff;
+               bt.bt_flags |= AR_TIMER_MODE_TBTT;
+               break;
+       case HAL_M_IBSS:
+               OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ATIM_TXPOLICY);
+               bt.bt_flags |= AR_TIMER_MODE_NDP;
+               /* fall thru... */
+       case HAL_M_HOSTAP:
+               bt.bt_nextdba = (next_beacon -
+                       ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */
+               bt.bt_nextswba = (next_beacon -
+                       ath_hal_sw_beacon_response_time) << 3;  /* 1/8 TU */
+               bt.bt_flags |= AR_TIMER_MODE_TBTT
+                           |  AR_TIMER_MODE_DBA
+                           |  AR_TIMER_MODE_SWBA;
+               break;
+       }
+       /*
+        * Set the ATIM window
+        * Our hardware does not support an ATIM window of 0
+        * (beacons will not work).  If the ATIM windows is 0,
+        * force it to 1.
+        */
+       bt.bt_nextatim = next_beacon + 1;
+       bt.bt_intval = beacon_period &
+               (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
+       ar5416SetBeaconTimers(ah, &bt);
+}
+
+#define AR_BEACON_PERIOD_MAX   0xffff
+
+void
+ar5416ResetStaBeaconTimers(struct ath_hal *ah)
+{
+       uint32_t val;
+
+       OS_REG_WRITE(ah, AR_NEXT_TBTT, 0);              /* no beacons */
+       val = OS_REG_READ(ah, AR_STA_ID1);
+       val |= AR_STA_ID1_PWR_SAV;              /* XXX */
+       /* tell the h/w that the associated AP is not PCF capable */
+       OS_REG_WRITE(ah, AR_STA_ID1,
+               val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF));
+       OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, AR_BEACON_PERIOD_MAX);
+       OS_REG_WRITE(ah, AR_DBA_PERIOD, AR_BEACON_PERIOD_MAX);
+}
+
+/*
+ * Set all the beacon related bits on the h/w for stations
+ * i.e. initializes the corresponding h/w timers;
+ * also tells the h/w whether to anticipate PCF beacons
+ */
+void
+ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
+{
+       uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod;
+
+       HALASSERT(bs->bs_intval != 0);
+
+       /* NB: no cfp setting since h/w automatically takes care */
+
+       OS_REG_WRITE(ah, AR_NEXT_TBTT, bs->bs_nexttbtt);
+
+       /*
+        * Start the beacon timers by setting the BEACON register
+        * to the beacon interval; no need to write tim offset since
+        * h/w parses IEs.
+        */
+       OS_REG_WRITE(ah, AR5416_BEACON_PERIOD,
+                        TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
+       OS_REG_WRITE(ah, AR_DBA_PERIOD,
+                        TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
+
+       /*
+        * Configure the BMISS interrupt.  Note that we
+        * assume the caller blocks interrupts while enabling
+        * the threshold.
+        */
+       HALASSERT(bs->bs_bmissthreshold <=
+               (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S));
+       OS_REG_RMW_FIELD(ah, AR_RSSI_THR,
+               AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
+
+       /*
+        * Program the sleep registers to correlate with the beacon setup.
+        */
+
+       /*
+        * Oahu beacons timers on the station were used for power
+        * save operation (waking up in anticipation of a beacon)
+        * and any CFP function; Venice does sleep/power-save timers
+        * differently - so this is the right place to set them up;
+        * don't think the beacon timers are used by venice sta hw
+        * for any useful purpose anymore
+        * Setup venice's sleep related timers
+        * Current implementation assumes sw processing of beacons -
+        *   assuming an interrupt is generated every beacon which
+        *   causes the hardware to become awake until the sw tells
+        *   it to go to sleep again; beacon timeout is to allow for
+        *   beacon jitter; cab timeout is max time to wait for cab
+        *   after seeing the last DTIM or MORE CAB bit
+        */
+#define CAB_TIMEOUT_VAL     10 /* in TU */
+#define BEACON_TIMEOUT_VAL  10 /* in TU */
+#define SLEEP_SLOP          3  /* in TU */
+
+       /*
+        * For max powersave mode we may want to sleep for longer than a
+        * beacon period and not want to receive all beacons; modify the
+        * timers accordingly; make sure to align the next TIM to the
+        * next DTIM if we decide to wake for DTIMs only
+        */
+       beaconintval = bs->bs_intval & HAL_BEACON_PERIOD;
+       HALASSERT(beaconintval != 0);
+       if (bs->bs_sleepduration > beaconintval) {
+               HALASSERT(roundup(bs->bs_sleepduration, beaconintval) ==
+                               bs->bs_sleepduration);
+               beaconintval = bs->bs_sleepduration;
+       }
+       dtimperiod = bs->bs_dtimperiod;
+       if (bs->bs_sleepduration > dtimperiod) {
+               HALASSERT(dtimperiod == 0 ||
+                       roundup(bs->bs_sleepduration, dtimperiod) ==
+                               bs->bs_sleepduration);
+               dtimperiod = bs->bs_sleepduration;
+       }
+       HALASSERT(beaconintval <= dtimperiod);
+       if (beaconintval == dtimperiod)
+               nextTbtt = bs->bs_nextdtim;
+       else
+               nextTbtt = bs->bs_nexttbtt;
+       nextdtim = bs->bs_nextdtim;
+
+       OS_REG_WRITE(ah, AR_NEXT_DTIM,
+               TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
+       OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
+
+       /* cab timeout is now in 1/8 TU */
+       OS_REG_WRITE(ah, AR_SLEEP1,
+               SM((CAB_TIMEOUT_VAL << 3), AR5416_SLEEP1_CAB_TIMEOUT)
+               | AR_SLEEP1_ASSUME_DTIM);
+       /* beacon timeout is now in 1/8 TU */
+       OS_REG_WRITE(ah, AR_SLEEP2,
+               SM((BEACON_TIMEOUT_VAL << 3), AR5416_SLEEP2_BEACON_TIMEOUT));
+
+       OS_REG_WRITE(ah, AR_TIM_PERIOD, beaconintval);
+       OS_REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod);
+       OS_REG_SET_BIT(ah, AR_TIMER_MODE,
+            AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n",
+           __func__, bs->bs_nextdtim);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n",
+           __func__, nextTbtt);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n",
+           __func__, beaconintval);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n",
+           __func__, dtimperiod);
+#undef CAB_TIMEOUT_VAL
+#undef BEACON_TIMEOUT_VAL
+#undef SLEEP_SLOP
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_cal.c       2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,663 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/* Owl specific stuff */
+#define NUM_NOISEFLOOR_READINGS 6       /* 3 chains * (ctl + ext) */
+
+static void ar5416StartNFCal(struct ath_hal *ah);
+static void ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *);
+static int16_t ar5416GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+
+/*
+ * Determine if calibration is supported by device and channel flags
+ */
+static OS_INLINE HAL_BOOL
+ar5416IsCalSupp(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_CAL_TYPE calType)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+
+       switch (calType & cal->suppCals) {
+       case IQ_MISMATCH_CAL:
+               /* Run IQ Mismatch for non-CCK only */
+               return !IS_CHAN_B(chan);
+       case ADC_GAIN_CAL:
+       case ADC_DC_CAL:
+               /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
+               return !IS_CHAN_B(chan) &&
+                   !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan));
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Setup HW to collect samples used for current cal
+ */
+static void
+ar5416SetupMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal)
+{
+       /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+           AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+           currCal->calData->calCountMax);
+
+       /* Select calibration to run */
+       switch (currCal->calData->calType) {
+       case IQ_MISMATCH_CAL:
+               OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: start IQ Mismatch calibration\n", __func__);
+               break;
+       case ADC_GAIN_CAL:
+               OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: start ADC Gain calibration\n", __func__);
+               break;
+       case ADC_DC_CAL:
+               OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: start ADC DC calibration\n", __func__);
+               break;
+       case ADC_DC_INIT_CAL:
+               OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: start Init ADC DC calibration\n", __func__);
+               break;
+       }
+       /* Kick-off cal */
+       OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+/*
+ * Initialize shared data structures and prepare a cal to be run.
+ */
+static void
+ar5416ResetMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+
+       /* Reset data structures shared between different calibrations */
+       OS_MEMZERO(cal->caldata, sizeof(cal->caldata));
+       cal->calSamples = 0;
+
+       /* Setup HW for new calibration */
+       ar5416SetupMeasurement(ah, currCal);
+
+       /* Change SW state to RUNNING for this calibration */
+       currCal->calState = CAL_RUNNING;
+}
+
+#if 0
+/*
+ * Run non-periodic calibrations.
+ */
+static HAL_BOOL
+ar5416RunInitCals(struct ath_hal *ah, int init_cal_count)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CHANNEL_INTERNAL ichan;     /* XXX bogus */
+       HAL_CAL_LIST *curCal = ahp->ah_cal_curr;
+       HAL_BOOL isCalDone;
+       int i;
+
+       if (curCal == AH_NULL)
+               return AH_FALSE;
+
+       ichan.calValid = 0;
+       for (i = 0; i < init_cal_count; i++) {
+               /* Reset this Cal */
+               ar5416ResetMeasurement(ah, curCal);
+               /* Poll for offset calibration complete */
+               if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: Cal %d failed to finish in 100ms.\n",
+                           __func__, curCal->calData->calType);
+                       /* Re-initialize list pointers for periodic cals */
+                       cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;
+                       return AH_FALSE;
+               }
+               /* Run this cal */
+               ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask,
+                   curCal, &isCalDone);
+               if (!isCalDone)
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: init cal %d did not complete.\n",
+                           __func__, curCal->calData->calType);
+               if (curCal->calNext != AH_NULL)
+                       curCal = curCal->calNext;
+       }
+
+       /* Re-initialize list pointers for periodic cals */
+       cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;
+       return AH_TRUE;
+}
+#endif
+
+/*
+ * Initialize Calibration infrastructure.
+ */
+HAL_BOOL
+ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       ichan = ath_hal_checkchannel(ah, chan);
+       HALASSERT(ichan != AH_NULL);
+
+       if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+               /* Enable Rx Filter Cal */
+               OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+               OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+
+               /* Clear the carrier leak cal bit */
+               OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+
+               /* kick off the cal */
+               OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+
+               /* Poll for offset calibration complete */
+               if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: offset calibration failed to complete in 1ms; "
+                           "noisy environment?\n", __func__);
+                       return AH_FALSE;
+               }
+
+               /* Set the cl cal bit and rerun the cal a 2nd time */
+               /* Enable Rx Filter Cal */
+               OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+               OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+
+               OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+       }
+
+       /* Calibrate the AGC */
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+
+       /* Poll for offset calibration complete */
+       if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: offset calibration did not complete in 1ms; "
+                   "noisy environment?\n", __func__);
+               return AH_FALSE;
+       }
+
+       /*
+        * Do NF calibration after DC offset and other CALs.
+        * Per system engineers, noise floor value can sometimes be 20 dB
+        * higher than normal value if DC offset and noise floor cal are
+        * triggered at the same time.
+        */
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+       /* Initialize list pointers */
+       cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;
+
+       /*
+        * Enable IQ, ADC Gain, ADC DC Offset Cals
+        */
+       if (AR_SREV_SOWL_10_OR_LATER(ah)) {
+               /* Setup all non-periodic, init time only calibrations */
+               /* XXX: Init DC Offset not working yet */
+#if 0
+               if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) {
+                       INIT_CAL(&cal->adcDcCalInitData);
+                       INSERT_CAL(cal, &cal->adcDcCalInitData);
+               }
+               /* Initialize current pointer to first element in list */
+               cal->cal_curr = cal->cal_list;
+
+               if (cal->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0))
+                       return AH_FALSE;
+#endif
+       }
+
+       /* If Cals are supported, add them to list via INIT/INSERT_CAL */
+       if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) {
+               INIT_CAL(&cal->adcGainCalData);
+               INSERT_CAL(cal, &cal->adcGainCalData);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: enable ADC Gain Calibration.\n", __func__);
+       }
+       if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) {
+               INIT_CAL(&cal->adcDcCalData);
+               INSERT_CAL(cal, &cal->adcDcCalData);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: enable ADC DC Calibration.\n", __func__);
+       }
+       if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) {
+               INIT_CAL(&cal->iqCalData);
+               INSERT_CAL(cal, &cal->iqCalData);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: enable IQ Calibration.\n", __func__);
+       }
+       /* Initialize current pointer to first element in list */
+       cal->cal_curr = cal->cal_list;
+
+       /* Kick off measurements for the first cal */
+       if (cal->cal_curr != AH_NULL)
+               ar5416ResetMeasurement(ah, cal->cal_curr);
+
+       /* Mark all calibrations on this channel as being invalid */
+       ichan->calValid = 0;
+
+       return AH_TRUE;
+}
+
+/*
+ * Entry point for upper layers to restart current cal.
+ * Reset the calibration valid bit in channel.
+ */
+HAL_BOOL
+ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
+       HAL_CAL_LIST *currCal = cal->cal_curr;
+
+       if (!AR_SREV_SOWL_10_OR_LATER(ah))
+               return AH_FALSE;
+       if (currCal == AH_NULL)
+               return AH_FALSE;
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               return AH_FALSE;
+       }
+       /*
+        * Expected that this calibration has run before, post-reset.
+        * Current state should be done
+        */
+       if (currCal->calState != CAL_DONE) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: Calibration state incorrect, %d\n",
+                   __func__, currCal->calState);
+               return AH_FALSE;
+       }
+
+       /* Verify Cal is supported on this channel */
+       if (!ar5416IsCalSupp(ah, chan, currCal->calData->calType))
+               return AH_FALSE;
+
+       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+           "%s: Resetting Cal %d state for channel %u/0x%x\n",
+           __func__, currCal->calData->calType, chan->channel,
+           chan->channelFlags);
+
+       /* Disable cal validity in channel */
+       ichan->calValid &= ~currCal->calData->calType;
+       currCal->calState = CAL_WAITING;
+
+       return AH_TRUE;
+}
+
+/*
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+static void
+ar5416DoCalibration(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *ichan,
+       uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+
+       /* Cal is assumed not done until explicitly set below */
+       *isCalDone = AH_FALSE;
+
+       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+           "%s: %s Calibration, state %d, calValid 0x%x\n",
+           __func__, currCal->calData->calName, currCal->calState,
+           ichan->calValid);
+
+       /* Calibration in progress. */
+       if (currCal->calState == CAL_RUNNING) {
+               /* Check to see if it has finished. */
+               if (!(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_CAL)) {
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "%s: sample %d of %d finished\n",
+                           __func__, cal->calSamples,
+                           currCal->calData->calNumSamples);
+                       /*
+                        * Collect measurements for active chains.
+                        */
+                       currCal->calData->calCollect(ah);
+                       if (++cal->calSamples >= currCal->calData->calNumSamples) {
+                               int i, numChains = 0;
+                               for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+                                       if (rxchainmask & (1 << i))
+                                               numChains++;
+                               }
+                               /*
+                                * Process accumulated data
+                                */
+                               currCal->calData->calPostProc(ah, numChains);
+
+                               /* Calibration has finished. */
+                               ichan->calValid |= currCal->calData->calType;
+                               currCal->calState = CAL_DONE;
+                               *isCalDone = AH_TRUE;
+                       } else {
+                               /*
+                                * Set-up to collect of another sub-sample.
+                                */
+                               ar5416SetupMeasurement(ah, currCal);
+                       }
+               }
+       } else if (!(ichan->calValid & currCal->calData->calType)) {
+               /* If current cal is marked invalid in channel, kick it off */
+               ar5416ResetMeasurement(ah, currCal);
+       }
+}
+
+/*
+ * Internal interface to schedule periodic calibration work.
+ */
+HAL_BOOL
+ar5416PerCalibrationN(struct ath_hal *ah,  HAL_CHANNEL *chan,
+       u_int rxchainmask, HAL_BOOL longcal, HAL_BOOL *isCalDone)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CAL_LIST *currCal = cal->cal_curr;
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       OS_MARK(ah, AH_MARK_PERCAL, chan->channel);
+
+       *isCalDone = AH_TRUE;
+
+       /* Invalid channel check */
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /*
+        * For given calibration:
+        * 1. Call generic cal routine
+        * 2. When this cal is done (isCalDone) if we have more cals waiting
+        *    (eg after reset), mask this to upper layers by not propagating
+        *    isCalDone if it is set to TRUE.
+        *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
+        *    to be run.
+        */
+       if (currCal != AH_NULL &&
+           (currCal->calState == CAL_RUNNING ||
+            currCal->calState == CAL_WAITING)) {
+               ar5416DoCalibration(ah, ichan, rxchainmask, currCal, isCalDone);
+               if (*isCalDone == AH_TRUE) {
+                       cal->cal_curr = currCal = currCal->calNext;
+                       if (currCal->calState == CAL_WAITING) {
+                               *isCalDone = AH_FALSE;
+                               ar5416ResetMeasurement(ah, currCal);
+                       }
+               }
+       }
+
+       /* Do NF cal only at longer intervals */
+       if (longcal) {
+               /*
+                * Get the value from the previous NF cal
+                * and update the history buffer.
+                */
+               ar5416GetNf(ah, ichan);
+
+               /*
+                * Load the NF from history buffer of the current channel.
+                * NF is slow time-variant, so it is OK to use a
+                * historical value.
+                */
+               ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan);
+
+               /* start NF calibration, without updating BB NF register*/
+               ar5416StartNFCal(ah);
+
+               if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
+                       /* report up and clear internal state */
+                       chan->channelFlags |= CHANNEL_CW_INT;
+                       ichan->channelFlags &= ~CHANNEL_CW_INT;
+               }
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+HAL_BOOL
+ar5416PerCalibration(struct ath_hal *ah,  HAL_CHANNEL *chan, HAL_BOOL *isIQdone)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CAL_LIST *curCal = cal->cal_curr;
+
+       if (curCal != AH_NULL && curCal->calData->calType == IQ_MISMATCH_CAL) {
+               return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask,
+                   AH_TRUE, isIQdone);
+       } else {
+               HAL_BOOL isCalDone;
+
+               *isIQdone = AH_FALSE;
+               return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask,
+                   AH_TRUE, &isCalDone);
+       }
+}
+
+static HAL_BOOL
+ar5416GetEepromNoiseFloorThresh(struct ath_hal *ah,
+       const HAL_CHANNEL_INTERNAL *chan, int16_t *nft)
+{
+       switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+               ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_5, nft);
+               break;
+       case CHANNEL_B:
+       case CHANNEL_G:
+       case CHANNEL_G_HT20:
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_2, nft);
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+static void
+ar5416StartNFCal(struct ath_hal *ah)
+{
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+static void
+ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       static const uint32_t ar5416_cca_regs[] = {
+               AR_PHY_CCA,
+               AR_PHY_CH1_CCA,
+               AR_PHY_CH2_CCA,
+               AR_PHY_EXT_CCA,
+               AR_PHY_CH1_EXT_CCA,
+               AR_PHY_CH2_EXT_CCA
+       };
+       struct ar5212NfCalHist *h;
+       int i, j;
+       int32_t val;
+       uint8_t chainmask;
+
+       /*
+        * Force NF calibration for all chains.
+        */
+       if (AR_SREV_KITE(ah)) {
+               /* Kite has only one chain */
+               chainmask = 0x9;
+       } else if (AR_SREV_MERLIN(ah)) {
+               /* Merlin has only two chains */
+               chainmask = 0x1B;
+       } else {
+               chainmask = 0x3F;
+       }
+
+       /*
+        * Write filtered NF values into maxCCApwr register parameter
+        * so we can load below.
+        */
+       h = AH5416(ah)->ah_cal.nfCalHist;
+       for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
+               if (chainmask & (1 << i)) {
+                       val = OS_REG_READ(ah, ar5416_cca_regs[i]);
+                       val &= 0xFFFFFE00;
+                       val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff);
+                       OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
+               }
+
+       /* Load software filtered NF value into baseband internal minCCApwr variable. */
+       OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
+       OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+       /* Wait for load to complete, should be fast, a few 10s of us. */
+       for (j = 0; j < 1000; j++) {
+               if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0)
+                       break;
+               OS_DELAY(10);
+       }
+
+       /*
+        * Restore maxCCAPower register parameter again so that we're not capped
+        * by the median we just loaded.  This will be initial (and max) value
+        * of next noise floor calibration the baseband does.
+        */
+       for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
+               if (chainmask & (1 << i)) {
+                       val = OS_REG_READ(ah, ar5416_cca_regs[i]);
+                       val &= 0xFFFFFE00;
+                       val |= (((uint32_t)(-50) << 1) & 0x1ff);
+                       OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
+               }
+}
+
+void
+ar5416InitNfHistBuff(struct ar5212NfCalHist *h)
+{
+       int i, j;
+
+       for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) {
+               h[i].currIndex = 0;
+               h[i].privNF = AR5416_CCA_MAX_GOOD_VALUE;
+               h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX;
+               for (j = 0; j < AR512_NF_CAL_HIST_MAX; j ++)
+                       h[i].nfCalBuffer[j] = AR5416_CCA_MAX_GOOD_VALUE;
+       }
+}
+
+/*
+ * Update the noise floor buffer as a ring buffer
+ */
+static void
+ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray)
+{
+       int i;
+
+       for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) {
+               h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+               if (++h[i].currIndex >= AR512_NF_CAL_HIST_MAX)
+                       h[i].currIndex = 0;
+               if (h[i].invalidNFcount > 0) {
+                       if (nfarray[i] < AR5416_CCA_MIN_BAD_VALUE ||
+                           nfarray[i] > AR5416_CCA_MAX_HIGH_VALUE) {
+                               h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX;
+                       } else {
+                               h[i].invalidNFcount--;
+                               h[i].privNF = nfarray[i];
+                       }
+               } else {
+                       h[i].privNF = ar5212GetNfHistMid(h[i].nfCalBuffer);
+               }
+       }
+}
+
+/*
+ * Read the NF and check it against the noise floor threshhold
+ */
+static int16_t
+ar5416GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       int16_t nf, nfThresh;
+
+       if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: NF didn't complete in calibration window\n", __func__);
+               nf = 0;
+       } else {
+               /* Finished NF cal, check against threshold */
+               int16_t nfarray[NUM_NOISEFLOOR_READINGS] = { 0 };
+
+               /* TODO - enhance for multiple chains and ext ch */
+               ath_hal_getNoiseFloor(ah, nfarray);
+               nf = nfarray[0];
+               if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) {
+                       if (nf > nfThresh) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "%s: noise floor failed detected; "
+                                   "detected %d, threshold %d\n", __func__,
+                                   nf, nfThresh);
+                               /*
+                                * NB: Don't discriminate 2.4 vs 5Ghz, if this
+                                *     happens it indicates a problem regardless
+                                *     of the band.
+                                */
+                               chan->channelFlags |= CHANNEL_CW_INT;
+                               nf = 0;
+                       }
+               } else {
+                       nf = 0;
+               }
+               ar5416UpdateNFHistBuff(AH5416(ah)->ah_cal.nfCalHist, nfarray);
+               chan->rawNoiseFloor = nf;
+       }
+       return nf;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_cal.h       2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _ATH_AR5416_CAL_H_
+#define _ATH_AR5416_CAL_H_
+
+typedef enum {
+       ADC_DC_INIT_CAL = 0x1,
+       ADC_GAIN_CAL    = 0x2,
+       ADC_DC_CAL      = 0x4,
+       IQ_MISMATCH_CAL = 0x8
+} HAL_CAL_TYPE;
+
+/* Calibrate state */
+typedef enum {
+       CAL_INACTIVE,
+       CAL_WAITING,
+       CAL_RUNNING,
+       CAL_DONE
+} HAL_CAL_STATE;
+
+typedef union {
+       uint32_t        u;
+       int32_t         s;
+} HAL_CAL_SAMPLE;
+
+#define        MIN_CAL_SAMPLES     1
+#define        MAX_CAL_SAMPLES    64
+#define        INIT_LOG_COUNT      5
+#define        PER_MIN_LOG_COUNT   2
+#define        PER_MAX_LOG_COUNT  10
+
+/* Per Calibration data structure */
+typedef struct per_cal_data {
+       const char      *calName;               /* for diagnostics */
+       HAL_CAL_TYPE    calType;                /* Type of calibration */
+       uint32_t        calNumSamples;          /* # SW samples to collect */
+       uint32_t        calCountMax;            /* # HW samples to collect */
+       void (*calCollect)(struct ath_hal *);   /* Accumulator function */
+                                               /* Post-processing function */
+       void (*calPostProc)(struct ath_hal *, uint8_t);
+} HAL_PERCAL_DATA;
+
+/* List structure for calibration data */
+typedef struct cal_list {
+       struct cal_list         *calNext;
+       HAL_CAL_STATE           calState;
+       const HAL_PERCAL_DATA   *calData;
+} HAL_CAL_LIST;
+
+struct ar5416PerCal {
+       /*
+        * Periodic calibration state.
+        */
+       HAL_CAL_TYPE    suppCals;
+       HAL_CAL_LIST    iqCalData;
+       HAL_CAL_LIST    adcGainCalData;
+       HAL_CAL_LIST    adcDcCalInitData;
+       HAL_CAL_LIST    adcDcCalData;
+       HAL_CAL_LIST    *cal_list;
+       HAL_CAL_LIST    *cal_last;
+       HAL_CAL_LIST    *cal_curr;
+#define AR5416_MAX_CHAINS              3       /* XXX dup's eeprom def */
+       HAL_CAL_SAMPLE  caldata[4][AR5416_MAX_CHAINS];
+       int             calSamples;
+       /*
+        * Noise floor cal histogram support.
+        * XXX be nice to re-use space in ar5212
+        */
+#define        AR5416_NUM_NF_READINGS          6       /* (3 chains * (ctl + ext) */
+       struct ar5212NfCalHist nfCalHist[AR5416_NUM_NF_READINGS];
+};
+
+#define INIT_CAL(_perCal) do {                                         \
+       (_perCal)->calState = CAL_WAITING;                              \
+       (_perCal)->calNext = AH_NULL;                                   \
+} while (0)
+
+#define INSERT_CAL(_cal, _perCal) do {                                 \
+       if ((_cal)->cal_last == AH_NULL) {                              \
+               (_cal)->cal_list = (_cal)->cal_last = (_perCal);        \
+               ((_cal)->cal_last)->calNext = (_perCal);                \
+       } else {                                                        \
+               ((_cal)->cal_last)->calNext = (_perCal);                \
+               (_cal)->cal_last = (_perCal);                           \
+               (_perCal)->calNext = (_cal)->cal_list;                  \
+       }                                                               \
+} while (0)
+
+HAL_BOOL ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan);
+HAL_BOOL ar5416PerCalibration(struct ath_hal *,  HAL_CHANNEL *,
+           HAL_BOOL *isIQdone);
+HAL_BOOL ar5416PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan,
+           u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone);
+HAL_BOOL ar5416ResetCalValid(struct ath_hal *ah,  HAL_CHANNEL *chan);
+
+void   ar5416IQCalCollect(struct ath_hal *ah);
+void   ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains);
+void   ar5416AdcGainCalCollect(struct ath_hal *ah);
+void   ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains);
+void   ar5416AdcDcCalCollect(struct ath_hal *ah);
+void   ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains);
+void   ar5416InitNfHistBuff(struct ar5212NfCalHist *h);
+#endif /* _ATH_AR5416_CAL_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_cal_adcdc.c 2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal_adcdc.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/* Adc DC Offset Cal aliases */
+#define        totalAdcDcOffsetIOddPhase(i)    caldata[0][i].s
+#define        totalAdcDcOffsetIEvenPhase(i)   caldata[1][i].s
+#define        totalAdcDcOffsetQOddPhase(i)    caldata[2][i].s
+#define        totalAdcDcOffsetQEvenPhase(i)   caldata[3][i].s
+
+void
+ar5416AdcDcCalCollect(struct ath_hal *ah)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       int i;
+
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               cal->totalAdcDcOffsetIOddPhase(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               cal->totalAdcDcOffsetIEvenPhase(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               cal->totalAdcDcOffsetQOddPhase(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               cal->totalAdcDcOffsetQEvenPhase(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+                  cal->calSamples, i,
+                  cal->totalAdcDcOffsetIOddPhase(i),
+                  cal->totalAdcDcOffsetIEvenPhase(i),
+                  cal->totalAdcDcOffsetQOddPhase(i),
+                  cal->totalAdcDcOffsetQEvenPhase(i));
+       }
+}
+
+void
+ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       const HAL_PERCAL_DATA *calData = cal->cal_curr->calData;
+       uint32_t numSamples;
+       int i;
+
+       numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
+       for (i = 0; i < numChains; i++) {
+               uint32_t iOddMeasOffset = cal->totalAdcDcOffsetIOddPhase(i);
+               uint32_t iEvenMeasOffset = cal->totalAdcDcOffsetIEvenPhase(i);
+               int32_t qOddMeasOffset = cal->totalAdcDcOffsetQOddPhase(i);
+               int32_t qEvenMeasOffset = cal->totalAdcDcOffsetQEvenPhase(i);
+               int32_t qDcMismatch, iDcMismatch;
+               uint32_t val;
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "Starting ADC DC Offset Cal for Chain %d\n", i);
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_i = %d\n",
+                   iOddMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_i = %d\n",
+                   iEvenMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_q = %d\n",
+                   qOddMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_q = %d\n",
+                   qEvenMeasOffset);
+
+               HALASSERT(numSamples);
+
+               iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
+                   numSamples) & 0x1ff;
+               qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
+                   numSamples) & 0x1ff;
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   " dc_offset_mismatch_i = 0x%08x\n", iDcMismatch);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   " dc_offset_mismatch_q = 0x%08x\n", qDcMismatch);
+
+               val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+               val &= 0xc0000fff;
+               val |= (qDcMismatch << 12) | (iDcMismatch << 21);
+               OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "ADC DC Offset Cal done for Chain %d\n", i);
+       }
+       OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+           AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_cal_adcgain.c       2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal_adcgain.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/* Adc Gain Cal aliases */
+#define        totalAdcIOddPhase(i)    caldata[0][i].u
+#define        totalAdcIEvenPhase(i)   caldata[1][i].u
+#define        totalAdcQOddPhase(i)    caldata[2][i].u
+#define        totalAdcQEvenPhase(i)   caldata[3][i].u
+
+/*
+ * Collect data from HW to later perform ADC Gain Calibration
+ */
+void
+ar5416AdcGainCalCollect(struct ath_hal *ah)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       int i;
+
+       /*
+       * Accumulate ADC Gain cal measures for active chains
+       */
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               cal->totalAdcIOddPhase(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               cal->totalAdcIEvenPhase(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               cal->totalAdcQOddPhase(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               cal->totalAdcQEvenPhase(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+                   cal->calSamples, i, cal->totalAdcIOddPhase(i),
+                   cal->totalAdcIEvenPhase(i), cal->totalAdcQOddPhase(i),
+                   cal->totalAdcQEvenPhase(i));
+       }
+}
+
+/*
+ * Use HW data to do ADC Gain Calibration
+ */
+void
+ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       uint32_t i;
+
+       for (i = 0; i < numChains; i++) {
+               uint32_t iOddMeasOffset  = cal->totalAdcIOddPhase(i);
+               uint32_t iEvenMeasOffset = cal->totalAdcIEvenPhase(i);
+               uint32_t qOddMeasOffset  = cal->totalAdcQOddPhase(i);
+               uint32_t qEvenMeasOffset = cal->totalAdcQEvenPhase(i);
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "Start ADC Gain Cal for Chain %d\n", i);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "  pwr_meas_odd_i = 0x%08x\n", iOddMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "  pwr_meas_even_i = 0x%08x\n", iEvenMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "  pwr_meas_odd_q = 0x%08x\n", qOddMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "  pwr_meas_even_q = 0x%08x\n", qEvenMeasOffset);
+
+               if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
+                       uint32_t iGainMismatch =
+                           ((iEvenMeasOffset*32)/iOddMeasOffset) & 0x3f;
+                       uint32_t qGainMismatch =
+                           ((qOddMeasOffset*32)/qEvenMeasOffset) & 0x3f;
+                       uint32_t val;
+
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           " gain_mismatch_i = 0x%08x\n",
+                           iGainMismatch);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           " gain_mismatch_q = 0x%08x\n",
+                           qGainMismatch);
+
+                       val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+                       val &= 0xfffff000;
+                       val |= (qGainMismatch) | (iGainMismatch << 6);
+                       OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+                       HALDEBUG(ah,  HAL_DEBUG_PERCAL,
+                           "ADC Gain Cal done for Chain %d\n", i);
+               }
+       }
+       OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+           AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_cal_iq.c    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal_iq.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/* IQ Cal aliases */
+#define        totalPowerMeasI(i)      caldata[0][i].u
+#define        totalPowerMeasQ(i)      caldata[1][i].u
+#define        totalIqCorrMeas(i)      caldata[2][i].s
+
+/*
+ * Collect data from HW to later perform IQ Mismatch Calibration
+ */
+void
+ar5416IQCalCollect(struct ath_hal *ah)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       int i;
+
+       /*
+        * Accumulate IQ cal measures for active chains
+        */
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               cal->totalPowerMeasI(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               cal->totalPowerMeasQ(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               cal->totalIqCorrMeas(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+                   cal->calSamples, i, cal->totalPowerMeasI(i),
+                   cal->totalPowerMeasQ(i), cal->totalIqCorrMeas(i));
+       }
+}
+
+/*
+ * Use HW data to do IQ Mismatch Calibration
+ */
+void
+ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       int i;
+
+       for (i = 0; i < numChains; i++) {
+               uint32_t powerMeasI = cal->totalPowerMeasI(i);
+               uint32_t powerMeasQ = cal->totalPowerMeasQ(i);
+               uint32_t iqCorrMeas = cal->totalIqCorrMeas(i);
+               uint32_t qCoffDenom, iCoffDenom;
+               int iqCorrNeg;
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "Start IQ Cal and Correction for Chain %d\n", i);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "Orignal: iq_corr_meas = 0x%08x\n", iqCorrMeas);
+
+               iqCorrNeg = 0;
+               /* iqCorrMeas is always negative. */
+               if (iqCorrMeas > 0x80000000)  {
+                       iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+                       iqCorrNeg = 1;
+               }
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_i = 0x%08x\n",
+                   powerMeasI);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_q = 0x%08x\n",
+                   powerMeasQ);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " iqCorrNeg is 0x%08x\n",
+                   iqCorrNeg);
+
+               iCoffDenom = (powerMeasI/2 + powerMeasQ/2)/ 128;
+               qCoffDenom = powerMeasQ / 64;
+               /* Protect against divide-by-0 */
+               if (powerMeasQ != 0) {
+                       /* IQ corr_meas is already negated if iqcorr_neg == 1 */
+                       int32_t iCoff = iqCorrMeas/iCoffDenom;
+                       int32_t qCoff = powerMeasI/qCoffDenom - 64;
+
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, " iCoff = 0x%08x\n",
+                           iCoff);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, " qCoff = 0x%08x\n",
+                           qCoff);
+
+                       /* Negate iCoff if iqCorrNeg == 0 */
+                       iCoff = iCoff & 0x3f;
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "New:  iCoff = 0x%08x\n", iCoff);
+
+                       if (iqCorrNeg == 0x0)
+                               iCoff = 0x40 - iCoff;
+                       if (qCoff > 15)
+                               qCoff = 15;
+                       else if (qCoff <= -16)
+                               qCoff = 16;
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           " : iCoff = 0x%x  qCoff = 0x%x\n", iCoff, qCoff);
+
+                       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i),
+                           AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff);
+                       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i),
+                           AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "IQ Cal and Correction done for Chain %d\n", i);
+               }
+       }
+       OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
+           AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_eeprom.c    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_eeprom.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/*
+ * Read 16 bits of data from offset into *data
+ */
+HAL_BOOL
+ar5416EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
+{
+        OS_REG_READ(ah,  AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+               if (!ath_hal_wait(ah, AR_EEPROM_STATUS_DATA,
+           AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0))
+               return AH_FALSE;
+               *data = MS(OS_REG_READ(ah, AR_EEPROM_STATUS_DATA),
+                  AR_EEPROM_STATUS_DATA_VAL);
+       return AH_TRUE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_gpio.c      2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_gpio.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#ifdef AH_DEBUG
+#include "ah_desc.h"                   /* NB: for HAL_PHYERR* */
+#endif
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#define        AR_NUM_GPIO     6               /* 6 GPIO pins */
+#define AR_GPIO_BIT(_gpio)     (1 << _gpio)
+
+/*
+ * Configure GPIO Output lines
+ */
+HAL_BOOL
+ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio)
+{
+       HALASSERT(gpio < AR_NUM_GPIO);
+       OS_REG_CLR_BIT(ah, AR_GPIO_INTR_OUT, AR_GPIO_BIT(gpio));
+       return AH_TRUE;
+}
+
+/*
+ * Configure GPIO Input lines
+ */
+HAL_BOOL
+ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
+{
+       HALASSERT(gpio < AR_NUM_GPIO);
+       OS_REG_SET_BIT(ah, AR_GPIO_INTR_OUT, AR_GPIO_BIT(gpio));
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - set output lines
+ */
+HAL_BOOL
+ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
+{
+       uint32_t reg;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+       reg = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_OUT_VAL);
+       if (val & 1)
+               reg |= AR_GPIO_BIT(gpio);
+       else
+               reg &= ~AR_GPIO_BIT(gpio);
+
+       OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_OUT_VAL, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - get input lines
+ */
+uint32_t
+ar5416GpioGet(struct ath_hal *ah, uint32_t gpio)
+{
+       if (gpio >= AR_NUM_GPIO)
+               return 0xffffffff;
+       return ((OS_REG_READ(ah, AR_GPIO_IN) & AR_GPIO_BIT(gpio)) >> gpio);
+}
+
+/*
+ * Set the GPIO Interrupt
+ */
+void
+ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
+{
+       uint32_t val;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+       /* XXX bounds check gpio */
+       val = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_INTR_CTRL);
+       if (ilevel)             /* 0 == interrupt on pin high */
+               val &= ~AR_GPIO_BIT(gpio);
+       else                    /* 1 == interrupt on pin low */
+               val |= AR_GPIO_BIT(gpio);
+       OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_INTR_CTRL, val);
+
+       /* Change the interrupt mask. */
+       val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), AR_INTR_GPIO);
+       val |= AR_GPIO_BIT(gpio);
+       OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_GPIO, val);
+
+       val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), AR_INTR_GPIO);
+       val |= AR_GPIO_BIT(gpio);
+       OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, AR_INTR_GPIO, val);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_interrupts.c        2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_interrupts.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+
+/*
+ * Checks to see if an interrupt is pending on our NIC
+ *
+ * Returns: TRUE    if an interrupt is pending
+ *          FALSE   if not
+ */
+HAL_BOOL
+ar5416IsInterruptPending(struct ath_hal *ah)
+{
+       uint32_t isr;
+       /*
+        * Some platforms trigger our ISR before applying power to
+        * the card, so make sure the INTPEND is really 1, not 0xffffffff.
+        */
+       isr = OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE);
+       if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_MAC_IRQ) != 0)
+               return AH_TRUE;
+
+       isr = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
+       if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_SYNC_DEFAULT))
+               return AH_TRUE;
+
+       return AH_FALSE;
+}
+
+/*
+ * Reads the Interrupt Status Register value from the NIC, thus deasserting
+ * the interrupt line, and returns both the masked and unmasked mapped ISR
+ * values.  The value returned is mapped to abstract the hw-specific bit
+ * locations in the Interrupt Status Register.
+ *
+ * Returns: A hardware-abstracted bitmap of all non-masked-out
+ *          interrupts pending, as well as an unmasked value
+ */
+HAL_BOOL
+ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)
+{
+       uint32_t isr, isr0, isr1, sync_cause;
+
+       /*
+        * Verify there's a mac interrupt and the RTC is on.
+        */
+       if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) &&
+           (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON)
+               isr = OS_REG_READ(ah, AR_ISR);
+       else
+               isr = 0;
+       sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
+       sync_cause &= AR_INTR_SYNC_DEFAULT;
+       if (isr == 0 && sync_cause == 0) {
+               *masked = 0;
+               return AH_FALSE;
+       }
+
+       if (isr != 0) {
+               struct ath_hal_5212 *ahp = AH5212(ah);
+               uint32_t mask2;
+
+               mask2 = 0;
+               if (isr & AR_ISR_BCNMISC) {
+                       uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2);
+                       if (isr2 & AR_ISR_S2_TIM)
+                               mask2 |= HAL_INT_TIM;
+                       if (isr2 & AR_ISR_S2_DTIM)
+                               mask2 |= HAL_INT_DTIM;
+                       if (isr2 & AR_ISR_S2_DTIMSYNC)
+                               mask2 |= HAL_INT_DTIMSYNC;
+                       if (isr2 & (AR_ISR_S2_CABEND ))
+                               mask2 |= HAL_INT_CABEND;
+                       if (isr2 & AR_ISR_S2_GTT)
+                               mask2 |= HAL_INT_GTT;
+                       if (isr2 & AR_ISR_S2_CST)
+                               mask2 |= HAL_INT_CST;
+                       if (isr2 & AR_ISR_S2_TSFOOR)
+                               mask2 |= HAL_INT_TSFOOR;
+               }
+
+               isr = OS_REG_READ(ah, AR_ISR_RAC);
+               if (isr == 0xffffffff) {
+                       *masked = 0;
+                       return AH_FALSE;;
+               }
+
+               *masked = isr & HAL_INT_COMMON;
+               if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+                       *masked |= HAL_INT_RX;
+               if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) {
+                       *masked |= HAL_INT_TX;
+                       isr0 = OS_REG_READ(ah, AR_ISR_S0_S);
+                       ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK);
+                       ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC);
+                       isr1 = OS_REG_READ(ah, AR_ISR_S1_S);
+                       ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR);
+                       ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL);
+               }
+
+               /* Interrupt Mitigation on AR5416 */
+#ifdef AR5416_INT_MITIGATION
+               if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+                       *masked |= HAL_INT_RX;
+               if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
+                       *masked |= HAL_INT_TX;
+#endif
+               *masked |= mask2;
+       }
+       if (sync_cause != 0) {
+               if (sync_cause & (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) {
+                       *masked |= HAL_INT_FATAL;
+               }
+               if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RADM CPL timeout\n",
+                           __func__);
+                       OS_REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
+                       OS_REG_WRITE(ah, AR_RC, 0);
+                       *masked |= HAL_INT_FATAL;
+               }
+               /*
+                * On fatal errors collect ISR state for debugging.
+                */
+               if (*masked & HAL_INT_FATAL) {
+                       AH_PRIVATE(ah)->ah_fatalState[0] = isr;
+                       AH_PRIVATE(ah)->ah_fatalState[1] = sync_cause;
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: fatal error, ISR_RAC 0x%x SYNC_CAUSE 0x%x\n",
+                           __func__, isr, sync_cause);
+               }
+
+               OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+               /* NB: flush write */
+               (void) OS_REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Atomically enables NIC interrupts.  Interrupts are passed in
+ * via the enumerated bitmask in ints.
+ */
+HAL_INT
+ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t omask = ahp->ah_maskReg;
+       uint32_t mask,mask2;
+
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",
+           __func__, omask, ints);
+
+       if (omask & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+               (void) OS_REG_READ(ah, AR_IER);
+
+               OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+               (void) OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+               OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+               (void) OS_REG_READ(ah, AR_INTR_SYNC_ENABLE);
+       }
+
+       mask = ints & HAL_INT_COMMON;
+       mask2 = 0;
+
+       if (ints & HAL_INT_TX) {
+               if (ahp->ah_txOkInterruptMask)
+                       mask |= AR_IMR_TXOK;
+               if (ahp->ah_txErrInterruptMask)
+                       mask |= AR_IMR_TXERR;
+               if (ahp->ah_txDescInterruptMask)
+                       mask |= AR_IMR_TXDESC;
+               if (ahp->ah_txEolInterruptMask)
+                       mask |= AR_IMR_TXEOL;
+       }
+       if (ints & HAL_INT_RX)
+               mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC;
+#ifdef AR5416_INT_MITIGATION
+       /*
+        * Overwrite default mask if Interrupt mitigation
+        * is specified for AR5416
+        */
+       mask = ints & HAL_INT_COMMON;
+       if (ints & HAL_INT_TX)
+               mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
+       if (ints & HAL_INT_RX)
+               mask |= AR_IMR_RXERR | AR_IMR_RXMINTR | AR_IMR_RXINTM;
+#endif
+       if (ints & (HAL_INT_BMISC)) {
+               mask |= AR_IMR_BCNMISC;
+               if (ints & HAL_INT_TIM)
+                       mask2 |= AR_IMR_S2_TIM;
+               if (ints & HAL_INT_DTIM)
+                       mask2 |= AR_IMR_S2_DTIM;
+               if (ints & HAL_INT_DTIMSYNC)
+                       mask2 |= AR_IMR_S2_DTIMSYNC;
+               if (ints & HAL_INT_CABEND)
+                       mask2 |= (AR_IMR_S2_CABEND );
+               if (ints & HAL_INT_GTT)
+                       mask2 |= AR_IMR_S2_GTT;
+               if (ints & HAL_INT_CST)
+                       mask2 |= AR_IMR_S2_CST;
+               if (ints & HAL_INT_TSFOOR)
+                       mask2 |= AR_IMR_S2_TSFOOR;
+       }
+
+       /* Write the new IMR and store off our SW copy. */
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
+       OS_REG_WRITE(ah, AR_IMR, mask);
+       mask = OS_REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
+                                       AR_IMR_S2_DTIM |
+                                       AR_IMR_S2_DTIMSYNC |
+                                       AR_IMR_S2_CABEND |
+                                       AR_IMR_S2_CABTO  |
+                                       AR_IMR_S2_TSFOOR |
+                                       AR_IMR_S2_GTT |
+                                       AR_IMR_S2_CST);
+       OS_REG_WRITE(ah, AR_IMR_S2, mask | mask2);
+
+       ahp->ah_maskReg = ints;
+
+       /* Re-enable interrupts if they were enabled before. */
+       if (ints & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+
+               OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_MAC_IRQ);
+               OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+               OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
+               OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, AR_INTR_SYNC_DEFAULT);
+       }
+
+       return omask;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_keycache.c  2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_keycache.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+
+static const int keyType[] = {
+       1,      /* HAL_CIPHER_WEP */
+       0,      /* HAL_CIPHER_AES_OCB */
+       2,      /* HAL_CIPHER_AES_CCM */
+       0,      /* HAL_CIPHER_CKIP */
+       3,      /* HAL_CIPHER_TKIP */
+       0,      /* HAL_CIPHER_CLR */
+};
+
+/*
+ * Clear the specified key cache entry and any associated MIC entry.
+ */
+HAL_BOOL
+ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+
+       if (ar5212ResetKeyCacheEntry(ah, entry)) {
+               ahp->ah_keytype[entry] = keyType[HAL_CIPHER_CLR];
+               return AH_TRUE;
+       } else
+               return AH_FALSE;
+}
+
+/*
+ * Sets the contents of the specified key cache entry
+ * and any associated MIC entry.
+ */
+HAL_BOOL
+ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
+                       const HAL_KEYVAL *k, const uint8_t *mac,
+                       int xorKey)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+
+       if (ar5212SetKeyCacheEntry(ah, entry, k, mac, xorKey)) {
+               ahp->ah_keytype[entry] = keyType[k->kv_type];
+               return AH_TRUE;
+       } else
+               return AH_FALSE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_misc.c      2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_misc.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#ifdef AH_DEBUG
+#include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
+#endif
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/*
+ * Return the wireless modes (a,b,g,t) supported by hardware.
+ *
+ * This value is what is actually supported by the hardware
+ * and is unaffected by regulatory/country code settings.
+ *
+ */
+u_int
+ar5416GetWirelessModes(struct ath_hal *ah)
+{
+       u_int mode;
+
+       mode = ar5212GetWirelessModes(ah);
+       if (mode & HAL_MODE_11A)
+               mode |= HAL_MODE_11NA_HT20
+                    |  HAL_MODE_11NA_HT40PLUS
+                    |  HAL_MODE_11NA_HT40MINUS
+                    ;
+       if (mode & HAL_MODE_11G)
+               mode |= HAL_MODE_11NG_HT20
+                    |  HAL_MODE_11NG_HT40PLUS
+                    |  HAL_MODE_11NG_HT40MINUS
+                    ;
+       return mode;
+}
+
+/*
+ * Change the LED blinking pattern to correspond to the connectivity
+ */
+void
+ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
+{
+       static const uint32_t ledbits[8] = {
+               AR_MAC_LED_ASSOC_NONE,          /* HAL_LED_INIT */
+               AR_MAC_LED_ASSOC_PEND,          /* HAL_LED_SCAN */
+               AR_MAC_LED_ASSOC_PEND,          /* HAL_LED_AUTH */
+               AR_MAC_LED_ASSOC_ACTIVE,        /* HAL_LED_ASSOC*/
+               AR_MAC_LED_ASSOC_ACTIVE,        /* HAL_LED_RUN */
+               AR_MAC_LED_ASSOC_NONE,
+               AR_MAC_LED_ASSOC_NONE,
+               AR_MAC_LED_ASSOC_NONE,
+       };
+       uint32_t bits;
+
+       bits = OS_REG_READ(ah, AR_MAC_LED);
+       bits = (bits &~ AR_MAC_LED_MODE)
+            | SM(AR_MAC_LED_MODE_POWON, AR_MAC_LED_MODE)
+#if 1
+            | SM(AR_MAC_LED_MODE_NETON, AR_MAC_LED_MODE)
+#endif
+            ;
+       bits = (bits &~ AR_MAC_LED_ASSOC)
+            | SM(ledbits[state & 0x7], AR_MAC_LED_ASSOC);
+       OS_REG_WRITE(ah, AR_MAC_LED, bits);
+}
+
+/*
+ * Reset the current hardware tsf for stamlme.
+ */
+void
+ar5416ResetTsf(struct ath_hal *ah)
+{
+       uint32_t v;
+       int i;
+
+       for (i = 0; i < 10; i++) {
+               v = OS_REG_READ(ah, AR_SLP32_MODE);
+               if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
+                       break;
+               OS_DELAY(10);
+       }
+       OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
+}
+
+HAL_BOOL
+ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
+{
+       return AH_TRUE;
+}
+
+/* Setup decompression for given key index */
+HAL_BOOL
+ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
+{
+       return HAL_OK;
+}
+
+/* Setup coverage class */
+void
+ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
+{
+}
+
+/*
+ * Return approximation of extension channel busy over an time interval
+ * 0% (clear) -> 100% (busy)
+ *
+ */
+uint32_t
+ar5416Get11nExtBusy(struct ath_hal *ah)
+{
+    struct ath_hal_5416 *ahp = AH5416(ah);
+    uint32_t busy; /* percentage */
+    uint32_t cycleCount, ctlBusy, extBusy;
+
+    ctlBusy = OS_REG_READ(ah, AR_RCCNT);
+    extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
+    cycleCount = OS_REG_READ(ah, AR_CCCNT);
+
+    if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
+        /*
+         * Cycle counter wrap (or initial call); it's not possible
+         * to accurately calculate a value because the registers
+         * right shift rather than wrap--so punt and return 0.
+         */
+        busy = 0;
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
+           __func__);
+
+    } else {
+        uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
+        uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
+        uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
+        uint32_t ctlClearDelta = 0;
+
+        /* Compute control channel rxclear.
+         * The cycle delta may be less than the control channel delta.
+         * This could be solved by freezing the timers (or an atomic read,
+         * if one was available). Checking for the condition should be
+         * sufficient.
+         */
+        if (cycleDelta > ctlBusyDelta) {
+            ctlClearDelta = cycleDelta - ctlBusyDelta;
+        }
+
+        /* Compute ratio of extension channel busy to control channel clear
+         * as an approximation to extension channel cleanliness.
+         *
+         * According to the hardware folks, ext rxclear is undefined
+         * if the ctrl rxclear is de-asserted (i.e. busy)
+         */
+        if (ctlClearDelta) {
+            busy = (extBusyDelta * 100) / ctlClearDelta;
+        } else {
+            busy = 100;
+        }
+        if (busy > 100) {
+            busy = 100;
+        }
+#if 0
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
+             "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
+             "busy %d\n",
+              __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
+#endif
+    }
+
+    ahp->ah_cycleCount = cycleCount;
+    ahp->ah_ctlBusy = ctlBusy;
+    ahp->ah_extBusy = extBusy;
+
+    return busy;
+}
+
+/*
+ * Configure 20/40 operation
+ *
+ * 20/40 = joint rx clear (control and extension)
+ * 20    = rx clear (control)
+ *
+ * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
+ *         from 20/40 => 20 only
+ */
+void
+ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
+{
+    uint32_t macmode;
+
+    /* Configure MAC for 20/40 operation */
+    if (mode == HAL_HT_MACMODE_2040) {
+        macmode = AR_2040_JOINED_RX_CLEAR;
+    } else {
+        macmode = 0;
+    }
+    OS_REG_WRITE(ah, AR_2040_MODE, macmode);
+}
+
+/*
+ * Get Rx clear (control/extension channel)
+ *
+ * Returns active low (busy) for ctrl/ext channel
+ * Owl 2.0
+ */
+HAL_HT_RXCLEAR
+ar5416Get11nRxClear(struct ath_hal *ah)
+{
+    HAL_HT_RXCLEAR rxclear = 0;
+    uint32_t val;
+
+    val = OS_REG_READ(ah, AR_DIAG_SW);
+
+    /* control channel */
+    if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
+        rxclear |= HAL_RX_CLEAR_CTL_LOW;
+    }
+    /* extension channel */
+    if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
+        rxclear |= HAL_RX_CLEAR_EXT_LOW;
+    }
+    return rxclear;
+}
+
+/*
+ * Set Rx clear (control/extension channel)
+ *
+ * Useful for forcing the channel to appear busy for
+ * debugging/diagnostics
+ * Owl 2.0
+ */
+void
+ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
+{
+    /* control channel */
+    if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
+        OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
+    } else {
+        OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
+    }
+    /* extension channel */
+    if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
+        OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
+    } else {
+        OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
+    }
+}
+
+HAL_STATUS
+ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+        uint32_t capability, uint32_t *result)
+{
+       switch (type) {
+       case HAL_CAP_BB_HANG:
+               switch (capability) {
+               case HAL_BB_HANG_RIFS:
+                       return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP;
+               case HAL_BB_HANG_DFS:
+                       return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP;
+               case HAL_BB_HANG_RX_CLEAR:
+                       return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
+               }
+               break;
+       case HAL_CAP_MAC_HANG:
+               return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
+                   (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
+                   AR_SREV_SOWL(ah)) ?
+                       HAL_OK : HAL_ENOTSUPP;
+       default:
+               break;
+       }
+       return ar5212GetCapability(ah, type, capability, result);
+}
+
+static int ar5416DetectMacHang(struct ath_hal *ah);
+static int ar5416DetectBBHang(struct ath_hal *ah);
+
+HAL_BOOL
+ar5416GetDiagState(struct ath_hal *ah, int request,
+       const void *args, uint32_t argsize,
+       void **result, uint32_t *resultsize)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       int hangs;
+
+       if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
+               return AH_TRUE;
+       switch (request) {
+       case HAL_DIAG_EEPROM:
+               return ath_hal_eepromDiag(ah, request,
+                   args, argsize, result, resultsize);
+       case HAL_DIAG_CHECK_HANGS:
+               if (argsize != sizeof(int))
+                       return AH_FALSE;
+               hangs = *(const int *) args;
+               ahp->ah_hangs = 0;
+               if (hangs & HAL_BB_HANGS)
+                       ahp->ah_hangs |= ar5416DetectBBHang(ah);
+               /* NB: if BB is hung MAC will be hung too so skip check */
+               if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
+                       ahp->ah_hangs |= ar5416DetectMacHang(ah);
+               *result = &ahp->ah_hangs;
+               *resultsize = sizeof(ahp->ah_hangs);
+               return AH_TRUE;
+       }
+       return ar5212GetDiagState(ah, request,
+           args, argsize, result, resultsize);
+}
+
+typedef struct {
+       uint32_t dma_dbg_3;
+       uint32_t dma_dbg_4;
+       uint32_t dma_dbg_5;
+       uint32_t dma_dbg_6;
+} mac_dbg_regs_t;
+
+typedef enum {
+       dcu_chain_state         = 0x1,
+       dcu_complete_state      = 0x2,
+       qcu_state               = 0x4,
+       qcu_fsp_ok              = 0x8,
+       qcu_fsp_state           = 0x10,
+       qcu_stitch_state        = 0x20,
+       qcu_fetch_state         = 0x40,
+       qcu_complete_state      = 0x80
+} hal_mac_hangs_t;
+
+typedef struct {
+       int states;
+       uint8_t dcu_chain_state;
+       uint8_t dcu_complete_state;
+       uint8_t qcu_state;
+       uint8_t qcu_fsp_ok;
+       uint8_t qcu_fsp_state;
+       uint8_t qcu_stitch_state;
+       uint8_t qcu_fetch_state;
+       uint8_t qcu_complete_state;
+} hal_mac_hang_check_t;
+
+static HAL_BOOL
+ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
+    const hal_mac_hang_check_t *check)
+{
+       int found_states;
+
+       found_states = 0;
+       if (check->states & dcu_chain_state) {
+               int i;
+
+               for (i = 0; i < 6; i++) {
+                       if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
+                           check->dcu_chain_state)
+                               found_states |= dcu_chain_state;
+               }
+               for (i = 0; i < 4; i++) {
+                       if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
+                           check->dcu_chain_state)
+                               found_states |= dcu_chain_state;
+               }
+       }
+       if (check->states & dcu_complete_state) {
+               if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
+                       found_states |= dcu_complete_state;
+       }
+       if (check->states & qcu_stitch_state) {
+               if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
+                       found_states |= qcu_stitch_state;
+       }
+       if (check->states & qcu_fetch_state) {
+               if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
+                       found_states |= qcu_fetch_state;
+       }
+       if (check->states & qcu_complete_state) {
+               if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
+                       found_states |= qcu_complete_state;
+       }
+       return (found_states == check->states);
+}
+
+#define NUM_STATUS_READS 50
+
+static int
+ar5416DetectMacHang(struct ath_hal *ah)
+{
+       static const hal_mac_hang_check_t hang_sig1 = {
+               .dcu_chain_state        = 0x6,
+               .dcu_complete_state     = 0x1,
+               .states                 = dcu_chain_state
+                                       | dcu_complete_state,
+       };
+       static const hal_mac_hang_check_t hang_sig2 = {
+               .qcu_stitch_state       = 0x9,
+               .qcu_fetch_state        = 0x8,
+               .qcu_complete_state     = 0x4,
+               .states                 = qcu_stitch_state
+                                       | qcu_fetch_state
+                                       | qcu_complete_state,
+        };
+       mac_dbg_regs_t mac_dbg;
+       int i;
+
+       mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
+       mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
+       mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
+       mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
+       for (i = 1; i <= NUM_STATUS_READS; i++) {
+               if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
+                   mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
+                   mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
+                   mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
+                       return 0;
+       }
+
+       if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
+               return HAL_MAC_HANG_SIG1;
+       if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
+               return HAL_MAC_HANG_SIG2;
+
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown MAC hang signature "
+           "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
+           __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
+           mac_dbg.dma_dbg_6);
+
+       return HAL_MAC_HANG_UNKNOWN;
+}
+
+/*
+ * Determine if the baseband using the Observation Bus Register
+ */
+static int
+ar5416DetectBBHang(struct ath_hal *ah)
+{
+#define N(a) (sizeof(a)/sizeof(a[0]))
+       /*
+        * Check the PCU Observation Bus 1 register (0x806c)
+        * NUM_STATUS_READS times
+        *
+        * 4 known BB hang signatures -
+        * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
+        * [2] bits 8,9 are 1, bit 11 is 0. State machine state
+        *     (bits 25-31) is 0x52
+        * [3] bits 8,9 are 1, bit 11 is 0. State machine state
+        *     (bits 25-31) is 0x18
+        * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
+        *     Rx State (bits 20-24) is 0x7.
+        */
+       static const struct {
+               uint32_t val;
+               uint32_t mask;
+               int code;
+       } hang_list[] = {
+               /* Reg Value   Reg Mask    Hang Code XXX */
+               { 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
+               { 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
+               { 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
+               { 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
+       };
+       uint32_t hang_sig;
+       int i;
+
+       hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
+       for (i = 1; i <= NUM_STATUS_READS; i++) {
+               if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
+                       return 0;
+       }
+       for (i = 0; i < N(hang_list); i++)
+               if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s BB hang, signature 0x%x, code 0x%x\n",
+                           __func__, hang_sig, hang_list[i].code);
+                       return hang_list[i].code;
+               }
+
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown BB hang signature! "
+           "<0x806c>=0x%x\n", __func__, hang_sig);
+
+       return HAL_BB_HANG_UNKNOWN;
+#undef N
+}
+#undef NUM_STATUS_READS
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_phy.c       2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_phy.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+
+/* shorthands to compact tables for readability */
+#define        OFDM    IEEE80211_T_OFDM
+#define        CCK     IEEE80211_T_CCK
+#define HT      IEEE80211_T_HT
+
+HAL_RATE_TABLE ar5416_11ng_table = {
+    28,  /* number of rates */
+    { 0 },
+    {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   1 Mb */ {  AH_TRUE, CCK,     1000,    0x1b,    0x00, (0x80| 2),   0, 0, 0 },
+/*   2 Mb */ {  AH_TRUE, CCK,     2000,    0x1a,    0x04, (0x80| 4),   1, 0, 0 },
+/* 5.5 Mb */ {  AH_TRUE, CCK,     5500,    0x19,    0x04, (0x80|11),   2, 0, 0 },
+/*  11 Mb */ {  AH_TRUE, CCK,    11000,    0x18,    0x04, (0x80|22),   3, 0, 0 },
+/* Remove rates 6, 9 from rate ctrl */
+/*   6 Mb */ { AH_FALSE, OFDM,    6000,    0x0b,    0x00,        12,   4, 0, 0 },
+/*   9 Mb */ { AH_FALSE, OFDM,    9000,    0x0f,    0x00,        18,   4, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,   12000,    0x0a,    0x00,        24,   6, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,   18000,    0x0e,    0x00,        36,   6, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   24000,    0x09,    0x00,        48,   8, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   36000,    0x0d,    0x00,        72,   8, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   48000,    0x08,    0x00,        96,   8, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   54000,    0x0c,    0x00,       108,   8, 0, 0 },
+/* 6.5 Mb */ {  AH_TRUE, HT,      6500,    0x80,    0x00,                0,   8, 0, 0 },
+/*  13 Mb */ {  AH_TRUE, HT,    13000,    0x81,    0x00,         1,   8, 0, 0 },
+/*19.5 Mb */ {  AH_TRUE, HT,     19500,    0x82,    0x00,         2,   8, 0, 0 },
+/*  26 Mb */ {  AH_TRUE, HT,    26000,    0x83,    0x00,         3,   8, 0, 0 },
+/*  39 Mb */ {  AH_TRUE, HT,    39000,    0x84,    0x00,         4,   8, 0, 0 },
+/*  52 Mb */ {  AH_TRUE, HT,            52000,    0x85,    0x00,         5,   8, 0, 0 },
+/*58.5 Mb */ {  AH_TRUE, HT,    58500,    0x86,    0x00,         6,   8, 0, 0 },
+/*  65 Mb */ {  AH_TRUE, HT,    65000,    0x87,    0x00,         7,   8, 0, 0 },
+/*  13 Mb */ {  AH_TRUE, HT,    13000,    0x88,    0x00,         8,   8, 0, 0 },
+/*  26 Mb */ {  AH_TRUE, HT,    26000,    0x89,    0x00,         9,   8, 0, 0 },
+/*  39 Mb */ {  AH_TRUE, HT,    39000,    0x8a,    0x00,        10,   8, 0, 0 },
+/*  52 Mb */ {  AH_TRUE, HT,    52000,    0x8b,    0x00,        11,   8, 0, 0 },
+/*  78 Mb */ {  AH_TRUE, HT,    78000,    0x8c,    0x00,        12,   8, 0, 0 },
+/* 104 Mb */ {  AH_TRUE, HT,   104000,    0x8d,    0x00,        13,   8, 0, 0 },
+/* 117 Mb */ {  AH_TRUE, HT,   117000,    0x8e,    0x00,        14,   8, 0, 0 },
+/* 130 Mb */ {  AH_TRUE, HT,   130000,    0x8f,    0x00,        15,   8, 0, 0 },
+       },
+};
+
+static HAL_RATE_TABLE ar5416_11na_table = {
+    24,  /* number of rates */
+    { 0 },
+    {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, OFDM,    6000,    0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, OFDM,    9000,    0x0f,    0x00,        18,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,   12000,    0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,   18000,    0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   24000,    0x09,    0x00, (0x80|48),   4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   36000,    0x0d,    0x00,        72,   8, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   48000,    0x08,    0x00,        96,   8, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   54000,    0x0c,    0x00,       108,   8, 0, 0 },
+/* 6.5 Mb */ {  AH_TRUE, HT,      6500,    0x80,    0x00,         0,   8, 0, 0 },
+/*  13 Mb */ {  AH_TRUE, HT,    13000,    0x81,    0x00,         1,   8, 0, 0 },
+/*19.5 Mb */ {  AH_TRUE, HT,     19500,    0x82,    0x00,         2,   8, 0, 0 },
+/*  26 Mb */ {  AH_TRUE, HT,    26000,    0x83,    0x00,         3,   8, 0, 0 },
+/*  39 Mb */ {  AH_TRUE, HT,    39000,    0x84,    0x00,         4,   8, 0, 0 },
+/*  52 Mb */ {  AH_TRUE, HT,            52000,    0x85,    0x00,         5,   8, 0, 0 },
+/*58.5 Mb */ {  AH_TRUE, HT,    58500,    0x86,    0x00,         6,   8, 0, 0 },
+/*  65 Mb */ {  AH_TRUE, HT,    65000,    0x87,    0x00,         7,   8, 0, 0 },
+/*  13 Mb */ {  AH_TRUE, HT,    13000,    0x88,    0x00,         8,   8, 0, 0 },
+/*  26 Mb */ {  AH_TRUE, HT,    26000,    0x89,    0x00,         9,   8, 0, 0 },
+/*  39 Mb */ {  AH_TRUE, HT,    39000,    0x8a,    0x00,        10,   8, 0, 0 },
+/*  52 Mb */ {  AH_TRUE, HT,    52000,    0x8b,    0x00,        11,   8, 0, 0 },
+/*  78 Mb */ {  AH_TRUE, HT,    78000,    0x8c,    0x00,        12,   8, 0, 0 },
+/* 104 Mb */ {  AH_TRUE, HT,   104000,    0x8d,    0x00,        13,   8, 0, 0 },
+/* 117 Mb */ {  AH_TRUE, HT,   117000,    0x8e,    0x00,        14,   8, 0, 0 },
+/* 130 Mb */ {  AH_TRUE, HT,   130000,    0x8f,    0x00,        15,   8, 0, 0 },
+       },
+};
+
+#undef OFDM
+#undef CCK
+#undef HT
+
+const HAL_RATE_TABLE *
+ar5416GetRateTable(struct ath_hal *ah, u_int mode)
+{
+       HAL_RATE_TABLE *rt;
+       switch (mode) {
+       case HAL_MODE_11NG_HT20:
+       case HAL_MODE_11NG_HT40PLUS:
+       case HAL_MODE_11NG_HT40MINUS:
+               rt = &ar5416_11ng_table;
+               break;
+       case HAL_MODE_11NA_HT20:
+       case HAL_MODE_11NA_HT40PLUS:
+       case HAL_MODE_11NA_HT40MINUS:
+               rt = &ar5416_11na_table;
+               break;
+       default:
+               return ar5212GetRateTable(ah, mode);
+       }
+       ath_hal_setupratetable(ah, rt);
+       return rt;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_power.c     2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_power.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+
+/*
+ * Notify Power Mgt is enabled in self-generated frames.
+ * If requested, force chip awake.
+ *
+ * Returns A_OK if chip is awake or successfully forced awake.
+ *
+ * WARNING WARNING WARNING
+ * There is a problem with the chip where sometimes it will not wake up.
+ */
+static HAL_BOOL
+ar5416SetPowerModeAwake(struct ath_hal *ah, int setChip)
+{
+#define        POWER_UP_TIME   200000
+       uint32_t val;
+       int i = 0;
+
+       if (setChip) {
+               /*
+                * Do a Power-On-Reset if OWL is shutdown
+                * the NetBSD driver  power-cycles the Cardbus slot
+                * as part of the reset procedure.
+                */
+               if ((OS_REG_READ(ah, AR_RTC_STATUS)
+                       & AR_RTC_PM_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
+                       if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON))
+                               goto bad;
+               }
+
+               OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+               OS_DELAY(50);   /* Give chip the chance to awake */
+
+               for (i = POWER_UP_TIME / 50; i != 0; i--) {
+                       val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
+                       if (val == AR_RTC_STATUS_ON)
+                               break;
+                       OS_DELAY(50);
+                       OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+               }
+       bad:
+               if (i == 0) {
+#ifdef AH_DEBUG
+                       ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n",
+                               __func__, POWER_UP_TIME/1000);
+#endif
+                       return AH_FALSE;
+               }
+       }
+
+       OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       return AH_TRUE;
+#undef POWER_UP_TIME
+}
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
+static void
+ar5416SetPowerModeSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       if (setChip) {
+               /* Clear the RTC force wake bit to allow the mac to sleep */
+               OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+               OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF);
+               /* Shutdown chip. Active low */
+               OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
+       }
+}
+
+/*
+ * Notify Power Management is enabled in self-generating
+ * fames.  If request, set power mode of chip to
+ * auto/normal.  Duration in units of 128us (1/8 TU).
+ */
+static void
+ar5416SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+       if (setChip)
+               OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+}
+
+/*
+ * Set power mgt to the requested mode, and conditionally set
+ * the chip as well
+ */
+HAL_BOOL
+ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+#ifdef AH_DEBUG
+       static const char* modes[] = {
+               "AWAKE",
+               "FULL-SLEEP",
+               "NETWORK SLEEP",
+               "UNDEFINED"
+       };
+#endif
+       int status = AH_TRUE;
+       if (!setChip)
+               return AH_TRUE;
+
+       HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
+           modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : "");
+       switch (mode) {
+       case HAL_PM_AWAKE:
+               status = ar5416SetPowerModeAwake(ah, setChip);
+               break;
+       case HAL_PM_FULL_SLEEP:
+               ar5416SetPowerModeSleep(ah, setChip);
+               break;
+       case HAL_PM_NETWORK_SLEEP:
+               ar5416SetPowerModeNetworkSleep(ah, setChip);
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode 0x%x\n",
+                   __func__, mode);
+               return AH_FALSE;
+       }
+       ahp->ah_powerMode = mode;
+       return status;
+}
+
+/*
+ * Return the current sleep mode of the chip
+ */
+HAL_POWER_MODE
+ar5416GetPowerMode(struct ath_hal *ah)
+{
+       int mode = OS_REG_READ(ah, AR_RTC_STATUS);
+       switch (mode & AR_RTC_PM_STATUS_M) {
+       case AR_RTC_STATUS_ON:
+       case AR_RTC_STATUS_WAKEUP:
+               return HAL_PM_AWAKE;
+       case AR_RTC_STATUS_SLEEP:
+               return HAL_PM_NETWORK_SLEEP;
+       case AR_RTC_STATUS_SHUTDOWN:
+               return HAL_PM_FULL_SLEEP;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: unknown power mode, RTC_STATUS 0x%x\n",
+                   __func__, mode);
+               return HAL_PM_UNDEFINED;
+       }
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_recv.c      2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_recv.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_desc.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416desc.h"
+
+/*
+ * Start receive at the PCU engine
+ */
+void
+ar5416StartPcuReceive(struct ath_hal *ah)
+{
+       struct ath_hal_private *ahp = AH_PRIVATE(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_RX, "%s: Start PCU Receive \n", __func__);
+       ar5212EnableMibCounters(ah);
+       /* NB: restore current settings */
+       ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE);
+       /*
+        * NB: must do after enabling phy errors to avoid rx
+        *     frames w/ corrupted descriptor status.
+        */
+       OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
+}
+
+/*
+ * Stop receive at the PCU engine
+ * and abort current frame in PCU
+ */
+void
+ar5416StopPcuReceive(struct ath_hal *ah)
+{
+       OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
+
+       HALDEBUG(ah, HAL_DEBUG_RX, "%s: Stop PCU Receive \n", __func__);
+       ar5212DisableMibCounters(ah);
+}
+
+/*
+ * Initialize RX descriptor, by clearing the status and setting
+ * the size (and any other flags).
+ */
+HAL_BOOL
+ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+    uint32_t size, u_int flags)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       HALASSERT((size &~ AR_BufLen) == 0);
+
+       ads->ds_ctl1 = size & AR_BufLen;
+       if (flags & HAL_RXDESC_INTREQ)
+               ads->ds_ctl1 |= AR_RxIntrReq;
+
+       /* this should be enough */
+       ads->ds_rxstatus8 &= ~AR_RxDone;
+
+       return AH_TRUE;
+}
+
+/*
+ * Process an RX descriptor, and return the status to the caller.
+ * Copy some hardware specific items into the software portion
+ * of the descriptor.
+ *
+ * NB: the caller is responsible for validating the memory contents
+ *     of the descriptor (e.g. flushing any cached copy).
+ */
+HAL_STATUS
+ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+    uint32_t pa, struct ath_desc *nds, uint64_t tsf,
+    struct ath_rx_status *rs)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       struct ar5416_desc *ands = AR5416DESC(nds);
+
+       if ((ads->ds_rxstatus8 & AR_RxDone) == 0)
+               return HAL_EINPROGRESS;
+       /*
+        * Given the use of a self-linked tail be very sure that the hw is
+        * done with this descriptor; the hw may have done this descriptor
+        * once and picked it up again...make sure the hw has moved on.
+        */
+       if ((ands->ds_rxstatus8 & AR_RxDone) == 0
+           && OS_REG_READ(ah, AR_RXDP) == pa)
+               return HAL_EINPROGRESS;
+
+       rs->rs_status = 0;
+       rs->rs_flags = 0;
+
+       rs->rs_datalen = ads->ds_rxstatus1 & AR_DataLen;
+       rs->rs_tstamp =  ads->AR_RcvTimestamp;
+
+       /* XXX what about KeyCacheMiss? */
+
+       rs->rs_rssi = MS(ads->ds_rxstatus4, AR_RxRSSICombined);
+       rs->rs_rssi_ctl[0] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt00);
+       rs->rs_rssi_ctl[1] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt01);
+       rs->rs_rssi_ctl[2] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt02);
+       rs->rs_rssi_ext[0] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt10);
+       rs->rs_rssi_ext[1] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt11);
+       rs->rs_rssi_ext[2] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt12);
+
+       if (ads->ds_rxstatus8 & AR_RxKeyIdxValid)
+               rs->rs_keyix = MS(ads->ds_rxstatus8, AR_KeyIdx);
+       else
+               rs->rs_keyix = HAL_RXKEYIX_INVALID;
+
+       /* NB: caller expected to do rate table mapping */
+       rs->rs_rate = RXSTATUS_RATE(ah, ads);
+       rs->rs_more = (ads->ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+
+       rs->rs_isaggr = (ads->ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+       rs->rs_moreaggr = (ads->ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
+       rs->rs_antenna = MS(ads->ds_rxstatus3, AR_RxAntenna);
+
+       if (ads->ds_rxstatus3 & AR_GI)
+               rs->rs_flags |= HAL_RX_GI;
+       if (ads->ds_rxstatus3 & AR_2040)
+               rs->rs_flags |= HAL_RX_2040;
+
+       if (ads->ds_rxstatus8 & AR_PreDelimCRCErr)
+               rs->rs_flags |= HAL_RX_DELIM_CRC_PRE;
+       if (ads->ds_rxstatus8 & AR_PostDelimCRCErr)
+               rs->rs_flags |= HAL_RX_DELIM_CRC_POST;
+       if (ads->ds_rxstatus8 & AR_DecryptBusyErr)
+               rs->rs_flags |= HAL_RX_DECRYPT_BUSY;
+       if (ads->ds_rxstatus8 & AR_HiRxChain)
+               rs->rs_flags |= HAL_RX_HI_RX_CHAIN;
+
+       if ((ads->ds_rxstatus8 & AR_RxFrameOK) == 0) {
+               /*
+                * These four bits should not be set together.  The
+                * 5416 spec states a Michael error can only occur if
+                * DecryptCRCErr not set (and TKIP is used).  Experience
+                * indicates however that you can also get Michael errors
+                * when a CRC error is detected, but these are specious.
+                * Consequently we filter them out here so we don't
+                * confuse and/or complicate drivers.
+                */
+               if (ads->ds_rxstatus8 & AR_CRCErr)
+                       rs->rs_status |= HAL_RXERR_CRC;
+               else if (ads->ds_rxstatus8 & AR_PHYErr) {
+                       u_int phyerr;
+
+                       rs->rs_status |= HAL_RXERR_PHY;
+                       phyerr = MS(ads->ds_rxstatus8, AR_PHYErrCode);
+                       rs->rs_phyerr = phyerr;
+               } else if (ads->ds_rxstatus8 & AR_DecryptCRCErr)
+                       rs->rs_status |= HAL_RXERR_DECRYPT;
+               else if (ads->ds_rxstatus8 & AR_MichaelErr)
+                       rs->rs_status |= HAL_RXERR_MIC;
+       }
+
+       return HAL_OK;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_reset.c     2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,2895 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_reset.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+#ifdef AH_SUPPORT_AR9280
+#include "ar5416/ar9280.h"
+#endif
+
+/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */
+#define        EEP_MINOR(_ah) \
+       (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK)
+#define IS_EEP_MINOR_V2(_ah)   (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2)
+#define IS_EEP_MINOR_V3(_ah)   (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3)
+
+/* Additional Time delay to wait after activiting the Base band */
+#define BASE_ACTIVATE_DELAY    100     /* 100 usec */
+#define PLL_SETTLE_DELAY       300     /* 300 usec */
+#define RTC_PLL_SETTLE_DELAY    1000    /* 1 ms     */
+
+static void ar5416InitDMA(struct ath_hal *ah);
+static void ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan);
+static void ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode);
+static void ar5416InitQoS(struct ath_hal *ah);
+static void ar5416InitUserSettings(struct ath_hal *ah);
+
+static HAL_BOOL ar5416SetTransmitPower(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain);
+
+#if 0
+static HAL_BOOL        ar5416ChannelChange(struct ath_hal *, HAL_CHANNEL *);
+#endif
+static void ar5416SetDeltaSlope(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+static void ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan);
+#ifdef AH_SUPPORT_AR9280
+static void ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan);
+#endif
+
+static HAL_BOOL ar5416SetResetPowerOn(struct ath_hal *ah);
+static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type);
+static void ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan);
+static HAL_BOOL ar5416SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah,
+       struct ar5416eeprom *pEepData,
+       HAL_CHANNEL_INTERNAL *chan, int16_t *ratesArray,
+       uint16_t cfgCtl, uint16_t AntennaReduction,
+       uint16_t twiceMaxRegulatoryPower,
+       uint16_t powerLimit);
+static HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah,
+       struct ar5416eeprom *pEepData,
+       HAL_CHANNEL_INTERNAL *chan,
+       int16_t *pTxPowerIndexOffset);
+static uint16_t ar5416GetMaxEdgePower(uint16_t freq,
+       CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz);
+static void ar5416GetTargetPowers(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_HT *powInfo,
+       uint16_t numChannels, CAL_TARGET_POWER_HT *pNewPower,
+       uint16_t numRates, HAL_BOOL isHt40Target);
+static void ar5416GetTargetPowersLeg(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_LEG *powInfo,
+       uint16_t numChannels, CAL_TARGET_POWER_LEG *pNewPower,
+       uint16_t numRates, HAL_BOOL isExtTarget);
+
+static int16_t interpolate(uint16_t target, uint16_t srcLeft,
+       uint16_t srcRight, int16_t targetLeft, int16_t targetRight);
+static void ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan);
+static void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet,
+       uint8_t * bChans, uint16_t availPiers,
+       uint16_t tPdGainOverlap, int16_t *pMinCalPower,
+       uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues,
+       uint16_t numXpdGains);
+static HAL_BOOL getLowerUpperIndex(uint8_t target, uint8_t *pList,
+       uint16_t listSize,  uint16_t *indexL, uint16_t *indexR);
+static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax,
+       uint8_t *pPwrList, uint8_t *pVpdList,
+       uint16_t numIntercepts, uint8_t *pRetVpdList);
+
+/*
+ * Places the device in and out of reset and then places sane
+ * values in the registers based on EEPROM config, initialization
+ * vectors (as determined by the mode), and station configuration
+ *
+ * bChannelChange is used to preserve DMA/PCU registers across
+ * a HW Reset during channel change.
+ */
+HAL_BOOL
+ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+       HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+#define        FAIL(_code)     do { ecode = _code; goto bad; } while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *ichan;
+       uint32_t softLedCfg;
+       uint32_t saveDefAntenna, saveLedState;
+       uint32_t macStaId1;
+       uint16_t rfXpdGain[2];
+       u_int modesIndex, freqIndex;
+       HAL_STATUS ecode;
+       int i, regWrites = 0;
+       uint32_t powerVal, rssiThrReg;
+       uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow;
+
+       OS_MARK(ah, AH_MARK_RESET, bChannelChange);
+#define        IS(_c,_f)       (((_c)->channelFlags & _f) || 0)
+       if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+#undef IS
+
+       /* Bring out of sleep mode */
+       if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n",
+                   __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_RESET,
+                   "%s: Ch=%u Max=%d Min=%d\n",__func__,
+                   ichan->channel, ichan->maxTxPower, ichan->minTxPower);
+       }
+       switch (opmode) {
+       case HAL_M_STA:
+       case HAL_M_IBSS:
+       case HAL_M_HOSTAP:
+       case HAL_M_MONITOR:
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
+                   __func__, opmode);
+               FAIL(HAL_EINVAL);
+               break;
+       }
+       HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
+
+       /* XXX Turn on fast channel change for 5416 */
+       /*
+        * Preserve the bmiss rssi threshold and count threshold
+        * across resets
+        */
+       rssiThrReg = OS_REG_READ(ah, AR_RSSI_THR);
+       /* If reg is zero, first time thru set to default val */
+       if (rssiThrReg == 0)
+               rssiThrReg = INIT_RSSI_THR;
+
+       /*
+        * Preserve the antenna on a channel change
+        */
+       saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
+       if (saveDefAntenna == 0)                /* XXX magic constants */
+               saveDefAntenna = 1;
+
+       /* Save hardware flag before chip reset clears the register */
+       macStaId1 = OS_REG_READ(ah, AR_STA_ID1) &
+               (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);
+
+       /* Save led state from pci config register */
+       saveLedState = OS_REG_READ(ah, AR_MAC_LED) &
+               (AR_MAC_LED_ASSOC | AR_MAC_LED_MODE |
+                AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW);
+       softLedCfg = OS_REG_READ(ah, AR_GPIO_INTR_OUT);
+
+       /*
+        * Adjust gain parameters before reset if
+        * there's an outstanding gain updated.
+        */
+       (void) ar5416GetRfgain(ah);
+
+       if (!ar5416ChipReset(ah, chan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Restore bmiss rssi & count thresholds */
+       OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg);
+
+       /* Setup the indices for the next set of register array writes */
+       /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+                modesIndex = 1;
+                freqIndex  = 1;
+               break;
+       case CHANNEL_T:
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+                modesIndex = 2;
+                freqIndex  = 1;
+               break;
+       case CHANNEL_PUREG:
+       case CHANNEL_G_HT20:
+       case CHANNEL_B: /* treat as channel G , no  B mode suport in owl */
+               modesIndex = 4;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               modesIndex = 3;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_108G:
+               modesIndex = 5;
+               freqIndex  = 2;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       /* Set correct Baseband to analog shift setting to access analog chips. */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+        /*
+        * Write addac shifts
+        */
+       OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+#if 0
+       /* NB: only required for Sowl */
+       ar5416EepromSetAddac(ah, ichan);
+#endif
+       regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1,
+           regWrites);
+       OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+       /* XXX Merlin ini fixups */
+       /* XXX Merlin 100us delay for shift registers */
+       regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex,
+           regWrites);
+#ifdef AH_SUPPORT_AR9280
+       if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
+               regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain,
+                   modesIndex, regWrites);
+               regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain,
+                   modesIndex, regWrites);
+       }
+#endif
+       /* XXX Merlin 100us delay for shift registers */
+       regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_common, 1, regWrites);
+       /* Setup 11n MAC/Phy mode registers */
+       ar5416Set11nRegs(ah,chan);
+       /* XXX updated regWrites? */
+       ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
+#ifdef AH_SUPPORT_AR9280
+       if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
+               /* 5GHz channels w/ Fast Clock use different modal values */
+               regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes,
+                   modesIndex, regWrites);
+       }
+#endif
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n",
+               __func__, OS_REG_READ(ah,AR_PHY_DAG_CTRLCCK));
+       HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n",
+               __func__, OS_REG_READ(ah,AR_PHY_ADC_CTL));
+
+       /* Set the mute mask to the correct default */
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2)
+               OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
+
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
+               /* Clear reg to alllow RX_CLEAR line debug */
+               OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
+       }
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
+#ifdef notyet
+               /* Enable burst prefetch for the data queues */
+               OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
+               /* Enable double-buffering */
+               OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
+#endif
+       }
+
+       /* Set ADC/DAC select values */
+       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
+
+       if (AH5416(ah)->ah_rx_chainmask == 0x5 ||
+           AH5416(ah)->ah_tx_chainmask == 0x5)
+               OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN);
+       /* Setup Chain Masks */
+       OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, AH5416(ah)->ah_rx_chainmask);
+       OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, AH5416(ah)->ah_rx_chainmask);
+       OS_REG_WRITE(ah, AR_SELFGEN_MASK, AH5416(ah)->ah_tx_chainmask);
+
+       /* Setup the transmit power values. */
+       if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Write the analog registers */
+       if (!ahp->ah_rfHal->setRfRegs(ah, ichan, freqIndex, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: ar5212SetRfRegs failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
+       if (IS_CHAN_OFDM(chan)|| IS_CHAN_HT(chan))
+               ar5416SetDeltaSlope(ah, ichan);
+
+#ifdef AH_SUPPORT_AR9280
+       if (AR_SREV_MERLIN_10_OR_LATER(ah))
+               ar9280SpurMitigate(ah, ichan);
+       else
+#endif
+               ar5416SpurMitigate(ah, ichan);
+
+       /* Setup board specific options for EEPROM version 3 */
+       if (!ar5416SetBoardValues(ah, ichan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error setting board options\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
+       OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
+               | macStaId1
+               | AR_STA_ID1_RTS_USE_DEF
+               | ahp->ah_staId1Defaults
+       );
+       ar5212SetOperatingMode(ah, opmode);
+
+       /* Set Venice BSSID mask according to current state */
+       OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
+       OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
+
+       /* Restore previous led state */
+       OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | saveLedState);
+       /* Restore soft Led state to GPIO */
+       OS_REG_WRITE(ah, AR_GPIO_INTR_OUT, softLedCfg);
+
+       /* Restore previous antenna */
+       OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+
+       /* then our BSSID */
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
+
+       /* Restore bmiss rssi & count thresholds */
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+
+       OS_REG_WRITE(ah, AR_ISR, ~0);           /* cleared on write */
+
+       if (!ar5212SetChannel(ah, ichan))
+               FAIL(HAL_EIO);
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       /* Set 1:1 QCU to DCU mapping for all queues */
+       for (i = 0; i < AR_NUM_DCU; i++)
+               OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+       ahp->ah_intrTxqs = 0;
+       for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
+               ar5212ResetTxQueue(ah, i);
+
+       ar5416InitIMR(ah, opmode);
+       ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
+       ar5416InitQoS(ah);
+       ar5416InitUserSettings(ah);
+
+       /*
+        * disable seq number generation in hw
+        */
+        OS_REG_WRITE(ah, AR_STA_ID1,
+            OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
+
+       ar5416InitDMA(ah);
+
+       /*
+        * program OBS bus to see MAC interrupts
+        */
+       OS_REG_WRITE(ah, AR_OBS, 8);
+
+#ifdef AR5416_INT_MITIGATION
+       OS_REG_WRITE(ah, AR_MIRT, 0);
+       OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
+       OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
+#endif
+
+       ar5416InitBB(ah, chan);
+
+       /* Setup compression registers */
+       ar5212SetCompRegs(ah);          /* XXX not needed? */
+
+       /*
+        * 5416 baseband will check the per rate power table
+        * and select the lower of the two
+        */
+       ackTpcPow = 63;
+       ctsTpcPow = 63;
+       chirpTpcPow = 63;
+       powerVal = SM(ackTpcPow, AR_TPC_ACK) |
+               SM(ctsTpcPow, AR_TPC_CTS) |
+               SM(chirpTpcPow, AR_TPC_CHIRP);
+       OS_REG_WRITE(ah, AR_TPC, powerVal);
+
+       if (!ar5416InitCal(ah, chan))
+               FAIL(HAL_ESELFTEST);
+
+       AH_PRIVATE(ah)->ah_opmode = opmode;     /* record operating mode */
+
+       if (bChannelChange) {
+               if (!(ichan->privFlags & CHANNEL_DFS))
+                       ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+               chan->channelFlags = ichan->channelFlags;
+               chan->privFlags = ichan->privFlags;
+               chan->maxRegTxPower = ichan->maxRegTxPower;
+               chan->maxTxPower = ichan->maxTxPower;
+               chan->minTxPower = ichan->minTxPower;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
+
+       OS_MARK(ah, AH_MARK_RESET_DONE, 0);
+
+       return AH_TRUE;
+bad:
+       OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
+       if (*status)
+               *status = ecode;
+       return AH_FALSE;
+#undef FAIL
+#undef N
+}
+
+#if 0
+/*
+ * This channel change evaluates whether the selected hardware can
+ * perform a synthesizer-only channel change (no reset).  If the
+ * TX is not stopped, or the RFBus cannot be granted in the given
+ * time, the function returns false as a reset is necessary
+ */
+HAL_BOOL
+ar5416ChannelChange(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t       ulCount;
+       uint32_t   data, synthDelay, qnum;
+       uint16_t   rfXpdGain[4];
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+
+       /* TX must be stopped or RF Bus grant will not work */
+       for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) {
+               if (ar5212NumTxPending(ah, qnum)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: frames pending on queue %d\n", __func__, qnum);
+                       return AH_FALSE;
+               }
+       }
+
+       /*
+        * Kill last Baseband Rx Frame - Request analog bus grant
+        */
+       OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST);
+       if (!ath_hal_wait(ah, AR_PHY_RFBUS_GNT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: could not kill baseband rx\n",
+                   __func__);
+               return AH_FALSE;
+       }
+
+       ar5416Set11nRegs(ah, chan);     /* NB: setup 5416-specific regs */
+
+       /* Change the synth */
+       if (!ar5212SetChannel(ah, ichan))
+               return AH_FALSE;
+
+       /* Setup the transmit power values. */
+       if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               return AH_FALSE;
+       }
+
+       /*
+        * Wait for the frequency synth to settle (synth goes on
+        * via PHY_ACTIVE_EN).  Read the phy active delay register.
+        * Value is in 100ns increments.
+        */
+       data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_CCK(ichan)) {
+               synthDelay = (4 * data) / 22;
+       } else {
+               synthDelay = data / 10;
+       }
+
+       OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
+
+       /* Release the RFBus Grant */
+       OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+
+       /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
+       if (IS_CHAN_OFDM(ichan)|| IS_CHAN_HT(chan)) {
+               if (ahp->ah_eeprom.ee_version >= AR_EEPROM_VER5_3 &&
+                   !IS_CHAN_B(chan))
+                       ar5212SetSpurMitigation(ah, ichan);
+               ar5416SetDeltaSlope(ah, ichan);
+       }
+
+       /* XXX spur mitigation for Melin */
+
+       /* Copy over internal channel flags to public hal channel */
+
+       if (!(ichan->privFlags & CHANNEL_DFS))
+               ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+       chan->channelFlags = ichan->channelFlags;
+       chan->privFlags = ichan->privFlags;
+       chan->maxRegTxPower = ichan->maxRegTxPower;
+       chan->maxTxPower = ichan->maxTxPower;
+       chan->minTxPower = ichan->minTxPower;
+       AH_PRIVATE(ah)->ah_curchan->ah_channel_time=0;
+       AH_PRIVATE(ah)->ah_curchan->ah_tsf_last = ar5212GetTsf64(ah);
+       ar5212TxEnable(ah,AH_TRUE);
+       return AH_TRUE;
+}
+#endif
+
+static void
+ar5416InitDMA(struct ath_hal *ah)
+{
+
+       /*
+        * set AHB_MODE not to do cacheline prefetches
+        */
+       OS_REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN);
+
+       /*
+        * let mac dma reads be in 128 byte chunks
+        */
+       OS_REG_WRITE(ah, AR_TXCFG,
+               (OS_REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK) | AR_TXCFG_DMASZ_128B);
+
+       /*
+        * let mac dma writes be in 128 byte chunks
+        */
+       OS_REG_WRITE(ah, AR_RXCFG,
+               (OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK) | AR_RXCFG_DMASZ_128B);
+
+       /* XXX restore TX trigger level */
+
+       /*
+        * Setup receive FIFO threshold to hold off TX activities
+        */
+       OS_REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
+
+       /*
+        * reduce the number of usable entries in PCU TXBUF to avoid
+        * wrap around.
+        */
+       OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+}
+
+static void
+ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t synthDelay;
+
+       /*
+        * Wait for the frequency synth to settle (synth goes on
+        * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
+        * Value is in 100ns increments.
+         */
+       synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_CCK(chan)) {
+               synthDelay = (4 * synthDelay) / 22;
+       } else {
+               synthDelay /= 10;
+       }
+
+       /* Turn on PLL on 5416 */
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s %s channel\n",
+           __func__, IS_CHAN_5GHZ(chan) ? "5GHz" : "2GHz");
+       ar5416InitPLL(ah, chan);
+
+       /* Activate the PHY (includes baseband activate and synthesizer on) */
+       OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+       /*
+        * If the AP starts the calibration before the base band timeout
+        * completes  we could get rx_clear false triggering.  Add an
+        * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
+        * does not happen.
+        */
+       if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+               OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
+       } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+               OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
+       } else {
+               OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
+       }
+}
+
+static void
+ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       /*
+        * Setup interrupt handling.  Note that ar5212ResetTxQueue
+        * manipulates the secondary IMR's as queues are enabled
+        * and disabled.  This is done with RMW ops to insure the
+        * settings we make here are preserved.
+        */
+        ahp->ah_maskReg = AR_IMR_TXERR | AR_IMR_TXURN
+                       | AR_IMR_RXERR | AR_IMR_RXORN
+                        | AR_IMR_BCNMISC;
+
+#ifdef AR5416_INT_MITIGATION
+               ahp->ah_maskReg |= AR_IMR_TXINTM | AR_IMR_RXINTM
+                       |  AR_IMR_TXMINTR | AR_IMR_RXMINTR;
+#else
+        ahp->ah_maskReg |= AR_IMR_TXOK | AR_IMR_RXOK;
+#endif
+       if (opmode == HAL_M_HOSTAP)
+               ahp->ah_maskReg |= AR_IMR_MIB;
+       OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
+       /* Enable bus errors that are OR'd to set the HIUERR bit */
+
+#if 0
+       OS_REG_WRITE(ah, AR_IMR_S2,
+               OS_REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT | AR_IMR_S2_CST);
+#endif
+}
+
+static void
+ar5416InitQoS(struct ath_hal *ah)
+{
+       /* QoS support */
+       OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);      /* XXX magic */
+       OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);        /* XXX magic */
+
+       /* Turn on NOACK Support for QoS packets */
+       OS_REG_WRITE(ah, AR_NOACK,
+               SM(2, AR_NOACK_2BIT_VALUE) |
+               SM(5, AR_NOACK_BIT_OFFSET) |
+               SM(0, AR_NOACK_BYTE_OFFSET));
+
+       /*
+        * initialize TXOP for all TIDs
+        */
+       OS_REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
+       OS_REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
+       OS_REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
+       OS_REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
+       OS_REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
+}
+
+static void
+ar5416InitUserSettings(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       /* Restore user-specified settings */
+       if (ahp->ah_miscMode != 0)
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+       if (ahp->ah_sifstime != (u_int) -1)
+               ar5212SetSifsTime(ah, ahp->ah_sifstime);
+       if (ahp->ah_slottime != (u_int) -1)
+               ar5212SetSlotTime(ah, ahp->ah_slottime);
+       if (ahp->ah_acktimeout != (u_int) -1)
+               ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
+       if (ahp->ah_ctstimeout != (u_int) -1)
+               ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
+       if (AH_PRIVATE(ah)->ah_diagreg != 0)
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+#if 0 /* XXX Todo */
+       if (ahp->ah_globaltxtimeout != (u_int) -1)
+               ar5416SetGlobalTxTimeout(ah, ahp->ah_globaltxtimeout);
+#endif
+}
+
+/*
+ * Places the hardware into reset and then pulls it out of reset
+ */
+HAL_BOOL
+ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t rfMode = 0;
+
+       OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0);
+       /*
+        * Warm reset is optimistic.
+        */
+       if (AR_SREV_MERLIN_20_OR_LATER(ah) &&
+           ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) {
+               if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON))
+                       return AH_FALSE;
+       } else {
+               if (!ar5416SetResetReg(ah, HAL_RESET_WARM))
+                       return AH_FALSE;
+       }
+
+       /* Bring out of sleep mode (AGAIN) */
+       if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+              return AH_FALSE;
+
+       ar5416InitPLL(ah, chan);
+
+       /*
+        * Perform warm reset before the mode/PLL/turbo registers
+        * are changed in order to deactivate the radio.  Mode changes
+        * with an active radio can result in corrupted shifts to the
+        * radio device.
+        */
+       if (chan != AH_NULL) {
+               /* treat channel B as channel G , no  B mode suport in owl */
+               rfMode |= (IS_CHAN_G(chan) || IS_CHAN_B(chan)) ?
+                       AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+               if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
+                       /* phy mode bits for 5GHz channels require Fast Clock */
+                       rfMode |= AR_PHY_MODE_DYNAMIC
+                              |  AR_PHY_MODE_DYN_CCK_DISABLE;
+               } else if (!AR_SREV_MERLIN_10_OR_LATER(ah)) {
+                       rfMode |= (IS_CHAN_5GHZ(chan)) ?
+                               AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
+               }
+               OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Delta slope coefficient computation.
+ * Required for OFDM operation.
+ */
+static void
+ar5416GetDeltaSlopeValues(struct ath_hal *ah, uint32_t coef_scaled,
+                          uint32_t *coef_mantissa, uint32_t *coef_exponent)
+{
+#define COEF_SCALE_S 24
+    uint32_t coef_exp, coef_man;
+    /*
+     * ALGO -> coef_exp = 14-floor(log2(coef));
+     * floor(log2(x)) is the highest set bit position
+     */
+    for (coef_exp = 31; coef_exp > 0; coef_exp--)
+            if ((coef_scaled >> coef_exp) & 0x1)
+                    break;
+    /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */
+    HALASSERT(coef_exp);
+    coef_exp = 14 - (coef_exp - COEF_SCALE_S);
+
+    /*
+     * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5);
+     * The coefficient is already shifted up for scaling
+     */
+    coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
+
+    *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
+    *coef_exponent = coef_exp - 16;
+
+#undef COEF_SCALE_S
+}
+
+void
+ar5416SetDeltaSlope(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+#define INIT_CLOCKMHZSCALED    0x64000000
+       uint32_t coef_scaled, ds_coef_exp, ds_coef_man;
+       uint32_t clockMhzScaled = INIT_CLOCKMHZSCALED;
+
+       CHAN_CENTERS centers;
+
+       if (IS_CHAN_TURBO(chan))
+               clockMhzScaled *= 2;
+       /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */
+       /* scale for selected channel bandwidth */
+       if (IS_CHAN_HALF_RATE(chan)) {
+               clockMhzScaled = clockMhzScaled >> 1;
+       } else if (IS_CHAN_QUARTER_RATE(chan)) {
+               clockMhzScaled = clockMhzScaled >> 2;
+       }
+
+       /*
+        * ALGO -> coef = 1e8/fcarrier*fclock/40;
+        * scaled coef to provide precision for this floating calculation
+        */
+       ar5416GetChannelCenters(ah, chan, &centers);
+       coef_scaled = clockMhzScaled / centers.synth_center;
+
+       ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp);
+
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+               AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+               AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+
+        /*
+         * For Short GI,
+         * scaled coeff is 9/10 that of normal coeff
+         */
+        coef_scaled = (9 * coef_scaled)/10;
+
+        ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp);
+
+        /* for short gi */
+        OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+                AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
+        OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+                AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
+#undef INIT_CLOCKMHZSCALED
+}
+
+/*
+ * Convert to baseband spur frequency given input channel frequency
+ * and compute register settings below.
+ */
+#define SPUR_RSSI_THRESH 40
+
+static void
+ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+    static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+                AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
+    static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+                AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
+    static const int inc[4] = { 0, 100, 0, 0 };
+
+    int bb_spur = AR_NO_SPUR;
+    int bin, cur_bin;
+    int spur_freq_sd;
+    int spur_delta_phase;
+    int denominator;
+    int upper, lower, cur_vit_mask;
+    int tmp, new;
+    int i;
+
+    int8_t mask_m[123];
+    int8_t mask_p[123];
+    int8_t mask_amt;
+    int tmp_mask;
+    int cur_bb_spur;
+    HAL_BOOL is2GHz = IS_CHAN_2GHZ(chan);
+
+    OS_MEMZERO(mask_m, sizeof(mask_m));
+    OS_MEMZERO(mask_p, sizeof(mask_p));
+
+    /*
+     * Need to verify range +/- 9.5 for static ht20, otherwise spur
+     * is out-of-band and can be ignored.
+     */
+    for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+        cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
+        if (AR_NO_SPUR == cur_bb_spur)
+            break;
+        cur_bb_spur = cur_bb_spur - (chan->channel * 10);
+        if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
+            bb_spur = cur_bb_spur;
+            break;
+        }
+    }
+    if (AR_NO_SPUR == bb_spur)
+        return;
+
+    bin = bb_spur * 32;
+
+    tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
+    new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+    OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), new);
+
+    new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+        AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+        AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+        AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+        SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+    OS_REG_WRITE(ah, AR_PHY_SPUR_REG, new);
+    /*
+     * Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz
+     * config, no offset for HT20.
+     * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
+     * /80 for dyn2040.
+     */
+    spur_delta_phase = ((bb_spur * 524288) / 100) &
+        AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+    /*
+     * in 11A mode the denominator of spur_freq_sd should be 40 and
+     * it should be 44 in 11G
+     */
+    denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
+    spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
+
+    new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+        SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+        SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+    OS_REG_WRITE(ah, AR_PHY_TIMING11, new);
+
+
+    /*
+     * ============================================
+     * pilot mask 1 [31:0] = +6..-26, no 0 bin
+     * pilot mask 2 [19:0] = +26..+7
+     *
+     * channel mask 1 [31:0] = +6..-26, no 0 bin
+     * channel mask 2 [19:0] = +26..+7
+     */
+    //cur_bin = -26;
+    cur_bin = -6000;
+    upper = bin + 100;
+    lower = bin - 100;
+
+    for (i = 0; i < 4; i++) {
+        int pilot_mask = 0;
+        int chan_mask  = 0;
+        int bp         = 0;
+        for (bp = 0; bp < 30; bp++) {
+            if ((cur_bin > lower) && (cur_bin < upper)) {
+                pilot_mask = pilot_mask | 0x1 << bp;
+                chan_mask  = chan_mask | 0x1 << bp;
+            }
+            cur_bin += 100;
+        }
+        cur_bin += inc[i];
+        OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+        OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+    }
+
+    /* =================================================
+     * viterbi mask 1 based on channel magnitude
+     * four levels 0-3
+     *  - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
+     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
+     *  - enable_mask_ppm, all bins move with freq
+     *
+     *  - mask_select,    8 bits for rates (reg 67,0x990c)
+     *  - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
+     *      choose which mask to use mask or mask2
+     */
+
+    /*
+     * viterbi mask 2  2nd set for per data rate puncturing
+     * four levels 0-3
+     *  - mask_select, 8 bits for rates (reg 67)
+     *  - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
+     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
+     */
+    cur_vit_mask = 6100;
+    upper        = bin + 120;
+    lower        = bin - 120;
+
+    for (i = 0; i < 123; i++) {
+        if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+            if ((abs(cur_vit_mask - bin)) < 75) {
+                mask_amt = 1;
+            } else {
+                mask_amt = 0;
+            }
+            if (cur_vit_mask < 0) {
+                mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+            } else {
+                mask_p[cur_vit_mask / 100] = mask_amt;
+            }
+        }
+        cur_vit_mask -= 100;
+    }
+
+    tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+          | (mask_m[48] << 26) | (mask_m[49] << 24)
+          | (mask_m[50] << 22) | (mask_m[51] << 20)
+          | (mask_m[52] << 18) | (mask_m[53] << 16)
+          | (mask_m[54] << 14) | (mask_m[55] << 12)
+          | (mask_m[56] << 10) | (mask_m[57] <<  8)
+          | (mask_m[58] <<  6) | (mask_m[59] <<  4)
+          | (mask_m[60] <<  2) | (mask_m[61] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+    tmp_mask =             (mask_m[31] << 28)
+          | (mask_m[32] << 26) | (mask_m[33] << 24)
+          | (mask_m[34] << 22) | (mask_m[35] << 20)
+          | (mask_m[36] << 18) | (mask_m[37] << 16)
+          | (mask_m[48] << 14) | (mask_m[39] << 12)
+          | (mask_m[40] << 10) | (mask_m[41] <<  8)
+          | (mask_m[42] <<  6) | (mask_m[43] <<  4)
+          | (mask_m[44] <<  2) | (mask_m[45] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+    tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+          | (mask_m[18] << 26) | (mask_m[18] << 24)
+          | (mask_m[20] << 22) | (mask_m[20] << 20)
+          | (mask_m[22] << 18) | (mask_m[22] << 16)
+          | (mask_m[24] << 14) | (mask_m[24] << 12)
+          | (mask_m[25] << 10) | (mask_m[26] <<  8)
+          | (mask_m[27] <<  6) | (mask_m[28] <<  4)
+          | (mask_m[29] <<  2) | (mask_m[30] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+    tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
+          | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
+          | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
+          | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
+          | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
+          | (mask_m[10] << 10) | (mask_m[11] <<  8)
+          | (mask_m[12] <<  6) | (mask_m[13] <<  4)
+          | (mask_m[14] <<  2) | (mask_m[15] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+    tmp_mask =             (mask_p[15] << 28)
+          | (mask_p[14] << 26) | (mask_p[13] << 24)
+          | (mask_p[12] << 22) | (mask_p[11] << 20)
+          | (mask_p[10] << 18) | (mask_p[ 9] << 16)
+          | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
+          | (mask_p[ 6] << 10) | (mask_p[ 5] <<  8)
+          | (mask_p[ 4] <<  6) | (mask_p[ 3] <<  4)
+          | (mask_p[ 2] <<  2) | (mask_p[ 1] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+    tmp_mask =             (mask_p[30] << 28)
+          | (mask_p[29] << 26) | (mask_p[28] << 24)
+          | (mask_p[27] << 22) | (mask_p[26] << 20)
+          | (mask_p[25] << 18) | (mask_p[24] << 16)
+          | (mask_p[23] << 14) | (mask_p[22] << 12)
+          | (mask_p[21] << 10) | (mask_p[20] <<  8)
+          | (mask_p[19] <<  6) | (mask_p[18] <<  4)
+          | (mask_p[17] <<  2) | (mask_p[16] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+    tmp_mask =             (mask_p[45] << 28)
+          | (mask_p[44] << 26) | (mask_p[43] << 24)
+          | (mask_p[42] << 22) | (mask_p[41] << 20)
+          | (mask_p[40] << 18) | (mask_p[39] << 16)
+          | (mask_p[38] << 14) | (mask_p[37] << 12)
+          | (mask_p[36] << 10) | (mask_p[35] <<  8)
+          | (mask_p[34] <<  6) | (mask_p[33] <<  4)
+          | (mask_p[32] <<  2) | (mask_p[31] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+    tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+          | (mask_p[59] << 26) | (mask_p[58] << 24)
+          | (mask_p[57] << 22) | (mask_p[56] << 20)
+          | (mask_p[55] << 18) | (mask_p[54] << 16)
+          | (mask_p[53] << 14) | (mask_p[52] << 12)
+          | (mask_p[51] << 10) | (mask_p[50] <<  8)
+          | (mask_p[49] <<  6) | (mask_p[48] <<  4)
+          | (mask_p[47] <<  2) | (mask_p[46] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+#ifdef AH_SUPPORT_AR9280
+#define        AR_BASE_FREQ_2GHZ       2300
+#define        AR_BASE_FREQ_5GHZ       4900
+#define        AR_SPUR_FEEQ_BOUND_HT40 19
+#define        AR_SPUR_FEEQ_BOUND_HT20 10
+
+static void
+ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
+{
+    static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+                AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
+    static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+                AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
+    static int inc[4] = { 0, 100, 0, 0 };
+
+    int bb_spur = AR_NO_SPUR;
+    int freq;
+    int bin, cur_bin;
+    int bb_spur_off, spur_subchannel_sd;
+    int spur_freq_sd;
+    int spur_delta_phase;
+    int denominator;
+    int upper, lower, cur_vit_mask;
+    int tmp, newVal;
+    int i;
+    CHAN_CENTERS centers;
+
+    int8_t mask_m[123];
+    int8_t mask_p[123];
+    int8_t mask_amt;
+    int tmp_mask;
+    int cur_bb_spur;
+    HAL_BOOL is2GHz = IS_CHAN_2GHZ(ichan);
+
+    OS_MEMZERO(&mask_m, sizeof(int8_t) * 123);
+    OS_MEMZERO(&mask_p, sizeof(int8_t) * 123);
+
+    ar5416GetChannelCenters(ah, ichan, &centers);
+    freq = centers.synth_center;
+
+    /*
+     * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40,
+     * otherwise spur is out-of-band and can be ignored.
+     */
+    for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+        cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
+        /* Get actual spur freq in MHz from EEPROM read value */
+        if (is2GHz) {
+            cur_bb_spur =  (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
+        } else {
+            cur_bb_spur =  (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
+        }
+
+        if (AR_NO_SPUR == cur_bb_spur)
+            break;
+        cur_bb_spur = cur_bb_spur - freq;
+
+        if (IS_CHAN_HT40(ichan)) {
+            if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
+                (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
+                bb_spur = cur_bb_spur;
+                break;
+            }
+        } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
+                   (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
+            bb_spur = cur_bb_spur;
+            break;
+        }
+    }
+
+    if (AR_NO_SPUR == bb_spur) {
+#if 1
+        /*
+         * MRC CCK can interfere with beacon detection and cause deaf/mute.
+         * Disable MRC CCK for now.
+         */
+        OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+#else
+        /* Enable MRC CCK if no spur is found in this channel. */
+        OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+#endif
+        return;
+    } else {
+        /*
+         * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur
+         * is found in this channel.
+         */
+        OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+    }
+
+    bin = bb_spur * 320;
+
+    tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
+
+    newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+    OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal);
+
+    newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+        AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+        AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+        AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+        SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+    OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
+
+    /* Pick control or extn channel to cancel the spur */
+    if (IS_CHAN_HT40(ichan)) {
+        if (bb_spur < 0) {
+            spur_subchannel_sd = 1;
+            bb_spur_off = bb_spur + 10;
+        } else {
+            spur_subchannel_sd = 0;
+            bb_spur_off = bb_spur - 10;
+        }
+    } else {
+        spur_subchannel_sd = 0;
+        bb_spur_off = bb_spur;
+    }
+
+    /*
+     * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
+     * /80 for dyn2040.
+     */
+    if (IS_CHAN_HT40(ichan))
+        spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+    else
+        spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+    /*
+     * in 11A mode the denominator of spur_freq_sd should be 40 and
+     * it should be 44 in 11G
+     */
+    denominator = IS_CHAN_2GHZ(ichan) ? 44 : 40;
+    spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
+
+    newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+        SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+        SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+    OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal);
+
+    /* Choose to cancel between control and extension channels */
+    newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
+    OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
+
+    /*
+     * ============================================
+     * Set Pilot and Channel Masks
+     *
+     * pilot mask 1 [31:0] = +6..-26, no 0 bin
+     * pilot mask 2 [19:0] = +26..+7
+     *
+     * channel mask 1 [31:0] = +6..-26, no 0 bin
+     * channel mask 2 [19:0] = +26..+7
+     */
+    cur_bin = -6000;
+    upper = bin + 100;
+    lower = bin - 100;
+
+    for (i = 0; i < 4; i++) {
+        int pilot_mask = 0;
+        int chan_mask  = 0;
+        int bp         = 0;
+        for (bp = 0; bp < 30; bp++) {
+            if ((cur_bin > lower) && (cur_bin < upper)) {
+                pilot_mask = pilot_mask | 0x1 << bp;
+                chan_mask  = chan_mask | 0x1 << bp;
+            }
+            cur_bin += 100;
+        }
+        cur_bin += inc[i];
+        OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+        OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+    }
+
+    /* =================================================
+     * viterbi mask 1 based on channel magnitude
+     * four levels 0-3
+     *  - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
+     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
+     *  - enable_mask_ppm, all bins move with freq
+     *
+     *  - mask_select,    8 bits for rates (reg 67,0x990c)
+     *  - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
+     *      choose which mask to use mask or mask2
+     */
+
+    /*
+     * viterbi mask 2  2nd set for per data rate puncturing
+     * four levels 0-3
+     *  - mask_select, 8 bits for rates (reg 67)
+     *  - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
+     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
+     */
+    cur_vit_mask = 6100;
+    upper        = bin + 120;
+    lower        = bin - 120;
+
+    for (i = 0; i < 123; i++) {
+        if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+            if ((abs(cur_vit_mask - bin)) < 75) {
+                mask_amt = 1;
+            } else {
+                mask_amt = 0;
+            }
+            if (cur_vit_mask < 0) {
+                mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+            } else {
+                mask_p[cur_vit_mask / 100] = mask_amt;
+            }
+        }
+        cur_vit_mask -= 100;
+    }
+
+    tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+          | (mask_m[48] << 26) | (mask_m[49] << 24)
+          | (mask_m[50] << 22) | (mask_m[51] << 20)
+          | (mask_m[52] << 18) | (mask_m[53] << 16)
+          | (mask_m[54] << 14) | (mask_m[55] << 12)
+          | (mask_m[56] << 10) | (mask_m[57] <<  8)
+          | (mask_m[58] <<  6) | (mask_m[59] <<  4)
+          | (mask_m[60] <<  2) | (mask_m[61] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+    tmp_mask =             (mask_m[31] << 28)
+          | (mask_m[32] << 26) | (mask_m[33] << 24)
+          | (mask_m[34] << 22) | (mask_m[35] << 20)
+          | (mask_m[36] << 18) | (mask_m[37] << 16)
+          | (mask_m[48] << 14) | (mask_m[39] << 12)
+          | (mask_m[40] << 10) | (mask_m[41] <<  8)
+          | (mask_m[42] <<  6) | (mask_m[43] <<  4)
+          | (mask_m[44] <<  2) | (mask_m[45] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+    tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+          | (mask_m[18] << 26) | (mask_m[18] << 24)
+          | (mask_m[20] << 22) | (mask_m[20] << 20)
+          | (mask_m[22] << 18) | (mask_m[22] << 16)
+          | (mask_m[24] << 14) | (mask_m[24] << 12)
+          | (mask_m[25] << 10) | (mask_m[26] <<  8)
+          | (mask_m[27] <<  6) | (mask_m[28] <<  4)
+          | (mask_m[29] <<  2) | (mask_m[30] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+    tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
+          | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
+          | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
+          | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
+          | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
+          | (mask_m[10] << 10) | (mask_m[11] <<  8)
+          | (mask_m[12] <<  6) | (mask_m[13] <<  4)
+          | (mask_m[14] <<  2) | (mask_m[15] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+    tmp_mask =             (mask_p[15] << 28)
+          | (mask_p[14] << 26) | (mask_p[13] << 24)
+          | (mask_p[12] << 22) | (mask_p[11] << 20)
+          | (mask_p[10] << 18) | (mask_p[ 9] << 16)
+          | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
+          | (mask_p[ 6] << 10) | (mask_p[ 5] <<  8)
+          | (mask_p[ 4] <<  6) | (mask_p[ 3] <<  4)
+          | (mask_p[ 2] <<  2) | (mask_p[ 1] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+    tmp_mask =             (mask_p[30] << 28)
+          | (mask_p[29] << 26) | (mask_p[28] << 24)
+          | (mask_p[27] << 22) | (mask_p[26] << 20)
+          | (mask_p[25] << 18) | (mask_p[24] << 16)
+          | (mask_p[23] << 14) | (mask_p[22] << 12)
+          | (mask_p[21] << 10) | (mask_p[20] <<  8)
+          | (mask_p[19] <<  6) | (mask_p[18] <<  4)
+          | (mask_p[17] <<  2) | (mask_p[16] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+    tmp_mask =             (mask_p[45] << 28)
+          | (mask_p[44] << 26) | (mask_p[43] << 24)
+          | (mask_p[42] << 22) | (mask_p[41] << 20)
+          | (mask_p[40] << 18) | (mask_p[39] << 16)
+          | (mask_p[38] << 14) | (mask_p[37] << 12)
+          | (mask_p[36] << 10) | (mask_p[35] <<  8)
+          | (mask_p[34] <<  6) | (mask_p[33] <<  4)
+          | (mask_p[32] <<  2) | (mask_p[31] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+    tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+          | (mask_p[59] << 26) | (mask_p[58] << 24)
+          | (mask_p[57] << 22) | (mask_p[56] << 20)
+          | (mask_p[55] << 18) | (mask_p[54] << 16)
+          | (mask_p[53] << 14) | (mask_p[52] << 12)
+          | (mask_p[51] << 10) | (mask_p[50] <<  8)
+          | (mask_p[49] <<  6) | (mask_p[48] <<  4)
+          | (mask_p[47] <<  2) | (mask_p[46] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+#endif /* AH_SUPPORT_AR9280 */
+
+/*
+ * Set a limit on the overall output power.  Used for dynamic
+ * transmit power control and the like.
+ *
+ * NB: limit is in units of 0.5 dbM.
+ */
+HAL_BOOL
+ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
+{
+       uint16_t dummyXpdGains[2];
+
+       AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
+       return ar5416SetTransmitPower(ah, AH_PRIVATE(ah)->ah_curchan,
+                       dummyXpdGains);
+}
+
+HAL_BOOL
+ar5416GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       int16_t minPower, maxPower;
+       HAL_CHANNEL *chan;
+       int i;
+
+       /*
+        * Get Pier table max and min powers.
+        */
+       for (i = 0; i < nchans; i++) {
+               chan = &chans[i];
+               if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) {
+                       /* NB: rf code returns 1/4 dBm units, convert */
+                       chan->maxTxPower = maxPower / 2;
+                       chan->minTxPower = minPower / 2;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: no min/max power for %u/0x%x\n",
+                           __func__, chan->channel, chan->channelFlags);
+                       chan->maxTxPower = AR5416_MAX_RATE_POWER;
+                       chan->minTxPower = 0;
+               }
+       }
+#ifdef AH_DEBUG
+       for (i=0; i<nchans; i++) {
+               HALDEBUG(ah, HAL_DEBUG_RESET,
+                   "Chan %d: MaxPow = %d MinPow = %d\n",
+                   chans[i].channel,chans[i].maxTxPower, chans[i].minTxPower);
+       }
+#endif
+       return AH_TRUE;
+}
+
+/* XXX gag, this is sick */
+typedef enum Ar5416_Rates {
+       rate6mb,  rate9mb,  rate12mb, rate18mb,
+       rate24mb, rate36mb, rate48mb, rate54mb,
+       rate1l,   rate2l,   rate2s,   rate5_5l,
+       rate5_5s, rate11l,  rate11s,  rateXr,
+       rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
+       rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
+       rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
+       rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
+       rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
+       Ar5416RateSize
+} AR5416_RATES;
+
+/**************************************************************
+ * ar5416SetTransmitPower
+ *
+ * Set the transmit power in the baseband for the given
+ * operating channel and mode.
+ */
+static HAL_BOOL
+ar5416SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain)
+{
+#define POW_SM(_r, _s)     (((_r) & 0x3f) << (_s))
+#define N(a)            (sizeof (a) / sizeof (a[0]))
+
+    MODAL_EEP_HEADER   *pModal;
+    struct ath_hal_5212 *ahp = AH5212(ah);
+    int16_t            ratesArray[Ar5416RateSize];
+    int16_t            txPowerIndexOffset = 0;
+    uint8_t            ht40PowerIncForPdadc = 2;
+    int                        i;
+
+    uint16_t           cfgCtl;
+    uint16_t           powerLimit;
+    uint16_t           twiceAntennaReduction;
+    uint16_t           twiceMaxRegulatoryPower;
+    int16_t            maxPower;
+    HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+    struct ar5416eeprom        *pEepData = &ee->ee_base;
+
+    HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
+
+    /* Setup info for the actual eeprom */
+    ath_hal_memzero(ratesArray, sizeof(ratesArray));
+    cfgCtl = ath_hal_getctl(ah, (HAL_CHANNEL *)chan);
+    powerLimit = chan->maxRegTxPower * 2;
+    twiceAntennaReduction = chan->antennaMax;
+    twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit);
+    pModal = &pEepData->modalHeader[IS_CHAN_2GHZ(chan)];
+    HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n",
+       __func__,chan->channel, cfgCtl );
+
+    if (IS_EEP_MINOR_V2(ah)) {
+        ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+    }
+
+    if (!ar5416SetPowerPerRateTable(ah, pEepData,  chan,
+                                    &ratesArray[0],cfgCtl,
+                                    twiceAntennaReduction,
+                                   twiceMaxRegulatoryPower, powerLimit)) {
+        HALDEBUG(ah, HAL_DEBUG_ANY,
+           "%s: unable to set tx power per rate table\n", __func__);
+        return AH_FALSE;
+    }
+
+    if (!ar5416SetPowerCalTable(ah,  pEepData, chan, &txPowerIndexOffset)) {
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n",
+           __func__);
+        return AH_FALSE;
+    }
+
+    maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
+
+    if (IS_CHAN_2GHZ(chan)) {
+        maxPower = AH_MAX(maxPower, ratesArray[rate1l]);
+    }
+
+    if (IS_CHAN_HT40(chan)) {
+        maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]);
+    }
+
+    ahp->ah_tx6PowerInHalfDbm = maxPower;
+    AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower;
+    ahp->ah_txPowerIndexOffset = txPowerIndexOffset;
+
+    /*
+     * txPowerIndexOffset is set by the SetPowerTable() call -
+     *  adjust the rate table (0 offset if rates EEPROM not loaded)
+     */
+    for (i = 0; i < N(ratesArray); i++) {
+        ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+        if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+            ratesArray[i] = AR5416_MAX_RATE_POWER;
+    }
+
+#ifdef AH_EEPROM_DUMP
+    ar5416PrintPowerPerRate(ah, ratesArray);
+#endif
+
+    /* Write the OFDM power per rate set */
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+        POW_SM(ratesArray[rate18mb], 24)
+          | POW_SM(ratesArray[rate12mb], 16)
+          | POW_SM(ratesArray[rate9mb], 8)
+          | POW_SM(ratesArray[rate6mb], 0)
+    );
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+        POW_SM(ratesArray[rate54mb], 24)
+          | POW_SM(ratesArray[rate48mb], 16)
+          | POW_SM(ratesArray[rate36mb], 8)
+          | POW_SM(ratesArray[rate24mb], 0)
+    );
+
+    if (IS_CHAN_2GHZ(chan)) {
+        /* Write the CCK power per rate set */
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+            POW_SM(ratesArray[rate2s], 24)
+              | POW_SM(ratesArray[rate2l],  16)
+              | POW_SM(ratesArray[rateXr],  8) /* XR target power */
+              | POW_SM(ratesArray[rate1l],   0)
+        );
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+            POW_SM(ratesArray[rate11s], 24)
+              | POW_SM(ratesArray[rate11l], 16)
+              | POW_SM(ratesArray[rate5_5s], 8)
+              | POW_SM(ratesArray[rate5_5l], 0)
+        );
+    HALDEBUG(ah, HAL_DEBUG_RESET,
+       "%s AR_PHY_POWER_TX_RATE3=0x%x AR_PHY_POWER_TX_RATE4=0x%x\n",
+           __func__, OS_REG_READ(ah,AR_PHY_POWER_TX_RATE3),
+           OS_REG_READ(ah,AR_PHY_POWER_TX_RATE4));
+    }
+
+    /* Write the HT20 power per rate set */
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+        POW_SM(ratesArray[rateHt20_3], 24)
+          | POW_SM(ratesArray[rateHt20_2], 16)
+          | POW_SM(ratesArray[rateHt20_1], 8)
+          | POW_SM(ratesArray[rateHt20_0], 0)
+    );
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+        POW_SM(ratesArray[rateHt20_7], 24)
+          | POW_SM(ratesArray[rateHt20_6], 16)
+          | POW_SM(ratesArray[rateHt20_5], 8)
+          | POW_SM(ratesArray[rateHt20_4], 0)
+    );
+
+    if (IS_CHAN_HT40(chan)) {
+        /* Write the HT40 power per rate set */
+       /* Correct PAR difference between HT40 and HT20/LEGACY */
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+            POW_SM(ratesArray[rateHt40_3] + ht40PowerIncForPdadc, 24)
+              | POW_SM(ratesArray[rateHt40_2] + ht40PowerIncForPdadc, 16)
+              | POW_SM(ratesArray[rateHt40_1] + ht40PowerIncForPdadc, 8)
+              | POW_SM(ratesArray[rateHt40_0] + ht40PowerIncForPdadc, 0)
+        );
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+            POW_SM(ratesArray[rateHt40_7] + ht40PowerIncForPdadc, 24)
+              | POW_SM(ratesArray[rateHt40_6] + ht40PowerIncForPdadc, 16)
+              | POW_SM(ratesArray[rateHt40_5] + ht40PowerIncForPdadc, 8)
+              | POW_SM(ratesArray[rateHt40_4] + ht40PowerIncForPdadc, 0)
+        );
+        /* Write the Dup/Ext 40 power per rate set */
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+            POW_SM(ratesArray[rateExtOfdm], 24)
+              | POW_SM(ratesArray[rateExtCck], 16)
+              | POW_SM(ratesArray[rateDupOfdm], 8)
+              | POW_SM(ratesArray[rateDupCck], 0)
+        );
+    }
+
+    /* Write the Power subtraction for dynamic chain changing, for per-packet powertx */
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+        POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+          | POW_SM(pModal->pwrDecreaseFor2Chain, 0)
+    );
+    return AH_TRUE;
+#undef POW_SM
+#undef N
+}
+
+/*
+ * Exported call to check for a recent gain reading and return
+ * the current state of the thermal calibration gain engine.
+ */
+HAL_RFGAIN
+ar5416GetRfgain(struct ath_hal *ah)
+{
+       return HAL_RFGAIN_INACTIVE;
+}
+
+/*
+ * Places all of hardware into reset
+ */
+HAL_BOOL
+ar5416Disable(struct ath_hal *ah)
+{
+       if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+       return ar5416SetResetReg(ah, HAL_RESET_COLD);
+}
+
+/*
+ * Places the PHY and Radio chips into reset.  A full reset
+ * must be called to leave this state.  The PCI/MAC/PCU are
+ * not placed into reset as we must receive interrupt to
+ * re-enable the hardware.
+ */
+HAL_BOOL
+ar5416PhyDisable(struct ath_hal *ah)
+{
+       return ar5416SetResetReg(ah, HAL_RESET_WARM);
+}
+
+/*
+ * Write the given reset bit mask into the reset register
+ */
+HAL_BOOL
+ar5416SetResetReg(struct ath_hal *ah, uint32_t type)
+{
+       /*
+        * Set force wake
+        */
+       OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+            AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+       switch (type) {
+       case HAL_RESET_POWER_ON:
+               return ar5416SetResetPowerOn(ah);
+               break;
+       case HAL_RESET_WARM:
+       case HAL_RESET_COLD:
+               return ar5416SetReset(ah, type);
+               break;
+       default:
+               return AH_FALSE;
+       }
+}
+
+static HAL_BOOL
+ar5416SetResetPowerOn(struct ath_hal *ah)
+{
+    /* Power On Reset (Hard Reset) */
+
+    /*
+     * Set force wake
+     *
+     * If the MAC was running, previously calling
+     * reset will wake up the MAC but it may go back to sleep
+     * before we can start polling.
+     * Set force wake  stops that
+     * This must be called before initiating a hard reset.
+     */
+    OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+            AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+    /*
+     * RTC reset and clear
+     */
+    OS_REG_WRITE(ah, AR_RTC_RESET, 0);
+    OS_DELAY(20);
+    OS_REG_WRITE(ah, AR_RTC_RESET, 1);
+
+    /*
+     * Poll till RTC is ON
+     */
+    if (!ath_hal_wait(ah, AR_RTC_STATUS, AR_RTC_PM_STATUS_M, AR_RTC_STATUS_ON)) {
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC not waking up\n", __func__);
+        return AH_FALSE;
+    }
+
+    return ar5416SetReset(ah, HAL_RESET_COLD);
+}
+
+static HAL_BOOL
+ar5416SetReset(struct ath_hal *ah, int type)
+{
+    uint32_t tmpReg;
+
+    /*
+     * Force wake
+     */
+    OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+       AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+    /*
+     * Reset AHB
+     */
+    tmpReg = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
+    if (tmpReg & (AR_INTR_SYNC_LOCAL_TIMEOUT|AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+       OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+       OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF);
+    } else {
+       OS_REG_WRITE(ah, AR_RC, AR_RC_AHB);
+    }
+
+    /*
+     * Set Mac(BB,Phy) Warm Reset
+     */
+    switch (type) {
+    case HAL_RESET_WARM:
+            OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM);
+            break;
+        case HAL_RESET_COLD:
+            OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM|AR_RTC_RC_MAC_COLD);
+            break;
+        default:
+            HALASSERT(0);
+            break;
+    }
+
+    /*
+     * Clear resets and force wakeup
+     */
+    OS_REG_WRITE(ah, AR_RTC_RC, 0);
+    if (!ath_hal_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) {
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC stuck in MAC reset\n", __func__);
+        return AH_FALSE;
+    }
+
+    /* Clear AHB reset */
+    OS_REG_WRITE(ah, AR_RC, 0);
+
+   /* Set register and descriptor swapping on
+    * Bigendian platforms on cold reset
+    */
+#ifdef __BIG_ENDIAN__
+    if (type == HAL_RESET_COLD) {
+               uint32_t        mask;
+
+               HALDEBUG(ah, HAL_DEBUG_RESET,
+                   "%s Applying descriptor swap\n", __func__);
+
+               mask = INIT_CONFIG_STATUS | AR_CFG_SWRD | AR_CFG_SWRG;
+#ifndef AH_NEED_DESC_SWAP
+               mask |= AR_CFG_SWTD;
+#endif
+               OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));
+       }
+#endif
+
+    ar5416InitPLL(ah, AH_NULL);
+
+    return AH_TRUE;
+}
+
+#ifndef IS_5GHZ_FAST_CLOCK_EN
+#define        IS_5GHZ_FAST_CLOCK_EN(ah, chan) AH_FALSE
+#endif
+
+static void
+ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t pll;
+
+       if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+               pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
+
+               if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
+                       pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
+               } else if (chan && IS_CHAN_QUARTER_RATE(chan)) {
+                       pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
+               }
+               if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
+                       pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
+
+                       /*
+                        * PLL WAR for Merlin 2.0/2.1
+                        * When doing fast clock, set PLL to 0x142c
+                        * Else, set PLL to 0x2850 to prevent reset-to-reset variation
+                        */
+                       if (AR_SREV_MERLIN_20(ah)) {
+                               if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
+                                       pll = 0x142c;
+                               } else {
+                                       pll = 0x2850;
+                               }
+                       }
+               } else {
+                       pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
+               }
+       } else if (AR_SREV_SOWL_10_OR_LATER(ah)) {
+               pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
+
+               if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
+                       pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
+               } else if (chan && IS_CHAN_QUARTER_RATE(chan)) {
+                       pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
+               }
+               if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
+                       pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV);
+               } else {
+                       pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);
+               }
+       } else {
+               pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+
+               if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
+                       pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+               } else if (chan != AH_NULL && IS_CHAN_QUARTER_RATE(chan)) {
+                       pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
+               }
+               if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
+                       pll |= SM(0xa, AR_RTC_PLL_DIV);
+               } else {
+                       pll |= SM(0xb, AR_RTC_PLL_DIV);
+               }
+       }
+       OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
+
+       /* TODO:
+       * For multi-band owl, switch between bands by reiniting the PLL.
+       */
+
+       OS_DELAY(RTC_PLL_SETTLE_DELAY);
+
+       OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
+}
+
+/*
+ * Read EEPROM header info and program the device for correct operation
+ * given the channel value.
+ */
+static HAL_BOOL
+ar5416SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+    const HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+    const struct ar5416eeprom *eep = &ee->ee_base;
+    const MODAL_EEP_HEADER *pModal;
+    int                        i, regChainOffset;
+    uint8_t            txRxAttenLocal;    /* workaround for eeprom versions <= 14.2 */
+
+    HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
+    pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+    txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;    /* workaround for eeprom versions <= 14.2 */
+
+    OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
+    for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+          if (AR_SREV_MERLIN(ah)) {
+               if (i >= 2) break;
+          }
+                  if (AR_SREV_OWL_20_OR_LATER(ah) &&
+            (AH5416(ah)->ah_rx_chainmask == 0x5 ||
+            AH5416(ah)->ah_tx_chainmask == 0x5) && i != 0) {
+            /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
+             * only chains 0 and 2 populated
+             */
+            regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+        } else {
+            regChainOffset = i * 0x1000;
+        }
+
+        OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]);
+        OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset,
+               (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) &
+               ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+               SM(pModal->iqCalICh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+               SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+        /*
+         * Large signal upgrade.
+        * XXX update
+         */
+
+        if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) {
+            OS_REG_WRITE(ah, AR_PHY_RXGAIN + regChainOffset,
+               (OS_REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & ~AR_PHY_RXGAIN_TXRX_ATTEN) |
+                       SM(IS_EEP_MINOR_V3(ah)  ? pModal->txRxAttenCh[i] : txRxAttenLocal,
+                               AR_PHY_RXGAIN_TXRX_ATTEN));
+
+            OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+               (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+                       SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+        }
+    }
+
+    OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
+    OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
+    OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize);
+    OS_REG_WRITE(ah, AR_PHY_RF_CTL4,
+        SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+        | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+        | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+        | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+    OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
+
+    if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+       OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+           pModal->thresh62);
+       OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+           pModal->thresh62);
+    } else {
+       OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+           pModal->thresh62);
+       OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA_THRESH62,
+           pModal->thresh62);
+    }
+
+    /* Minor Version Specific application */
+    if (IS_EEP_MINOR_V2(ah)) {
+        OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,  AR_PHY_TX_FRAME_TO_DATA_START, pModal->txFrameToDataStart);
+        OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,  AR_PHY_TX_FRAME_TO_PA_ON, pModal->txFrameToPaOn);
+    }
+
+    if (IS_EEP_MINOR_V3(ah)) {
+       if (IS_CHAN_HT40(chan)) {
+               /* Overwrite switch settling with HT40 value */
+               OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
+       }
+
+        if ((AR_SREV_OWL_20_OR_LATER(ah)) &&
+            (  AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5)){
+            /* Reg Offsets are swapped for logical mapping */
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
+                       SM(pModal->bswMargin[2], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
+                       SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
+                       SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
+                       SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+        } else {
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
+                       SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
+                       SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
+                       SM(pModal->bswMargin[2],AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
+                       SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+        }
+        OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_MARGIN, pModal->bswMargin[0]);
+        OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_ATTEN, pModal->bswAtten[0]);
+    }
+    return AH_TRUE;
+}
+
+/*
+ * Helper functions common for AP/CB/XB
+ */
+
+/*
+ * ar5416SetPowerPerRateTable
+ *
+ * Sets the transmit power in the baseband for the given
+ * operating channel and mode.
+ */
+static HAL_BOOL
+ar5416SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom *pEepData,
+                           HAL_CHANNEL_INTERNAL *chan,
+                           int16_t *ratesArray, uint16_t cfgCtl,
+                           uint16_t AntennaReduction,
+                           uint16_t twiceMaxRegulatoryPower,
+                           uint16_t powerLimit)
+{
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+/* Local defines to distinguish between extension and control CTL's */
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+
+       uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+       int i;
+       int16_t  twiceLargestAntenna;
+       CAL_CTL_DATA *rep;
+       CAL_TARGET_POWER_LEG targetPowerOfdm, targetPowerCck = {0, {0, 0, 0, 0}};
+       CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}, targetPowerCckExt = {0, {0, 0, 0, 0}};
+       CAL_TARGET_POWER_HT  targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0}};
+       int16_t scaledPower, minCtlPower;
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2   /* excluding HT40, EXT-OFDM */
+#define SUB_NUM_CTL_MODES_AT_2G_40 3   /* excluding HT40, EXT-OFDM, EXT-CCK */
+       static const uint16_t ctlModesFor11a[] = {
+          CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+       };
+       static const uint16_t ctlModesFor11g[] = {
+          CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+       };
+       const uint16_t *pCtlMode;
+       uint16_t numCtlModes, ctlMode, freq;
+       CHAN_CENTERS centers;
+
+       ar5416GetChannelCenters(ah,  chan, &centers);
+
+       /* Compute TxPower reduction due to Antenna Gain */
+
+       twiceLargestAntenna = AH_MAX(AH_MAX(pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+                                       pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[1]),
+                                       pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+#if 0
+       /* Turn it back on if we need to calculate per chain antenna gain reduction */
+       /* Use only if the expected gain > 6dbi */
+       /* Chain 0 is always used */
+       twiceLargestAntenna = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[0];
+
+       /* Look at antenna gains of Chains 1 and 2 if the TX mask is set */
+       if (ahp->ah_tx_chainmask & 0x2)
+               twiceLargestAntenna = AH_MAX(twiceLargestAntenna,
+                       pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+
+       if (ahp->ah_tx_chainmask & 0x4)
+               twiceLargestAntenna = AH_MAX(twiceLargestAntenna,
+                       pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+#endif
+       twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0);
+
+       /* XXX setup for 5212 use (really used?) */
+       ath_hal_eepromSet(ah,
+           IS_CHAN_2GHZ(chan) ? AR_EEP_ANTGAINMAX_2 : AR_EEP_ANTGAINMAX_5,
+           twiceLargestAntenna);
+
+       /*
+        * scaledPower is the minimum of the user input power level and
+        * the regulatory allowed power level
+        */
+       scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna);
+
+       /* Reduce scaled Power by number of chains active to get to per chain tx power level */
+       /* TODO: better value than these? */
+       switch (owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask)) {
+       case 1:
+               break;
+       case 2:
+               scaledPower -= pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor2Chain;
+               break;
+       case 3:
+               scaledPower -= pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor3Chain;
+               break;
+       default:
+               return AH_FALSE; /* Unsupported number of chains */
+       }
+
+       scaledPower = AH_MAX(0, scaledPower);
+
+       /* Get target powers from EEPROM - our baseline for TX Power */
+       if (IS_CHAN_2GHZ(chan)) {
+               /* Setup for CTL modes */
+               numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */
+               pCtlMode = ctlModesFor11g;
+
+               ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPowerCck,
+                               AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE);
+               ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPower2G,
+                               AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE);
+               ar5416GetTargetPowers(ah,  chan, pEepData->calTargetPower2GHT20,
+                               AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE);
+
+               if (IS_CHAN_HT40(chan)) {
+                       numCtlModes = N(ctlModesFor11g);    /* All 2G CTL's */
+
+                       ar5416GetTargetPowers(ah,  chan, pEepData->calTargetPower2GHT40,
+                               AR5416_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE);
+                       /* Get target powers for extension channels */
+                       ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPowerCck,
+                               AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE);
+                       ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPower2G,
+                               AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE);
+               }
+       } else {
+               /* Setup for CTL modes */
+               numCtlModes = N(ctlModesFor11a) - SUB_NUM_CTL_MODES_AT_5G_40; /* CTL_11A, CTL_5GHT20 */
+               pCtlMode = ctlModesFor11a;
+
+               ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPower5G,
+                               AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE);
+               ar5416GetTargetPowers(ah,  chan, pEepData->calTargetPower5GHT20,
+                               AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE);
+
+               if (IS_CHAN_HT40(chan)) {
+                       numCtlModes = N(ctlModesFor11a); /* All 5G CTL's */
+
+                       ar5416GetTargetPowers(ah,  chan, pEepData->calTargetPower5GHT40,
+                               AR5416_NUM_5G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE);
+                       ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPower5G,
+                               AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE);
+               }
+       }
+
+       /*
+        * For MIMO, need to apply regulatory caps individually across dynamically
+        * running modes: CCK, OFDM, HT20, HT40
+        *
+        * The outer loop walks through each possible applicable runtime mode.
+        * The inner loop walks through each ctlIndex entry in EEPROM.
+        * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
+        *
+        */
+       for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+
+               HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+                                                                (pCtlMode[ctlMode] == CTL_2GHT40);
+               if (isHt40CtlMode) {
+                       freq = centers.ctl_center;
+               } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) {
+                       freq = centers.ext_center;
+               } else {
+                       freq = centers.ctl_center;
+               }
+
+               /* walk through each CTL index stored in EEPROM */
+               for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+                       uint16_t twiceMinEdgePower;
+
+                       /* compare test group from regulatory channel list with test mode from pCtlMode list */
+                       if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) ||
+                               (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+                                ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
+                               rep = &(pEepData->ctlData[i]);
+                               twiceMinEdgePower = ar5416GetMaxEdgePower(freq,
+                                                       rep->ctlEdges[owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1],
+                                                       IS_CHAN_2GHZ(chan));
+                               if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+                                       /* Find the minimum of all CTL edge powers that apply to this channel */
+                                       twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower);
+                               } else {
+                                       /* specific */
+                                       twiceMaxEdgePower = twiceMinEdgePower;
+                                       break;
+                               }
+                       }
+               }
+               minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower);
+               /* Apply ctl mode to correct target power set */
+               switch(pCtlMode[ctlMode]) {
+               case CTL_11B:
+                       for (i = 0; i < N(targetPowerCck.tPow2x); i++) {
+                               targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower);
+                       }
+                       break;
+               case CTL_11A:
+               case CTL_11G:
+                       for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) {
+                               targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower);
+                       }
+                       break;
+               case CTL_5GHT20:
+               case CTL_2GHT20:
+                       for (i = 0; i < N(targetPowerHt20.tPow2x); i++) {
+                               targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower);
+                       }
+                       break;
+               case CTL_11B_EXT:
+                       targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower);
+                       break;
+               case CTL_11A_EXT:
+               case CTL_11G_EXT:
+                       targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower);
+                       break;
+               case CTL_5GHT40:
+               case CTL_2GHT40:
+                       for (i = 0; i < N(targetPowerHt40.tPow2x); i++) {
+                               targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower);
+                       }
+                       break;
+               default:
+                       return AH_FALSE;
+                       break;
+               }
+       } /* end ctl mode checking */
+
+       /* Set rates Array from collected data */
+       ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = ratesArray[rate18mb] = ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0];
+       ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+       ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+       ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+       ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+       for (i = 0; i < N(targetPowerHt20.tPow2x); i++) {
+               ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+       }
+
+       if (IS_CHAN_2GHZ(chan)) {
+               ratesArray[rate1l]  = targetPowerCck.tPow2x[0];
+               ratesArray[rate2s] = ratesArray[rate2l]  = targetPowerCck.tPow2x[1];
+               ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+               ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+       }
+       if (IS_CHAN_HT40(chan)) {
+               for (i = 0; i < N(targetPowerHt40.tPow2x); i++) {
+                       ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
+               }
+               ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+               ratesArray[rateDupCck]  = targetPowerHt40.tPow2x[0];
+               ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+               if (IS_CHAN_2GHZ(chan)) {
+                       ratesArray[rateExtCck]  = targetPowerCckExt.tPow2x[0];
+               }
+       }
+       return AH_TRUE;
+#undef EXT_ADDITIVE
+#undef CTL_11A_EXT
+#undef CTL_11G_EXT
+#undef CTL_11B_EXT
+#undef SUB_NUM_CTL_MODES_AT_5G_40
+#undef SUB_NUM_CTL_MODES_AT_2G_40
+#undef N
+}
+
+/**************************************************************************
+ * fbin2freq
+ *
+ * Get channel value from binary representation held in eeprom
+ * RETURNS: the frequency in MHz
+ */
+static uint16_t
+fbin2freq(uint8_t fbin, HAL_BOOL is2GHz)
+{
+    /*
+     * Reserved value 0xFF provides an empty definition both as
+     * an fbin and as a frequency - do not convert
+     */
+    if (fbin == AR5416_BCHAN_UNUSED) {
+        return fbin;
+    }
+
+    return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+/*
+ * ar5416GetMaxEdgePower
+ *
+ * Find the maximum conformance test limit for the given channel and CTL info
+ */
+static uint16_t
+ar5416GetMaxEdgePower(uint16_t freq, CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz)
+{
+    uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+    int      i;
+
+    /* Get the edge power */
+    for (i = 0; (i < AR5416_NUM_BAND_EDGES) && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED) ; i++) {
+        /*
+         * If there's an exact channel match or an inband flag set
+         * on the lower channel use the given rdEdgePower
+         */
+        if (freq == fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
+            twiceMaxEdgePower = MS(pRdEdgesPower[i].tPowerFlag, CAL_CTL_EDGES_POWER);
+            break;
+        } else if ((i > 0) && (freq < fbin2freq(pRdEdgesPower[i].bChannel, is2GHz))) {
+            if (fbin2freq(pRdEdgesPower[i - 1].bChannel, is2GHz) < freq && (pRdEdgesPower[i - 1].tPowerFlag & CAL_CTL_EDGES_FLAG) != 0) {
+                twiceMaxEdgePower = MS(pRdEdgesPower[i - 1].tPowerFlag, CAL_CTL_EDGES_POWER);
+            }
+            /* Leave loop - no more affecting edges possible in this monotonic increasing list */
+            break;
+        }
+    }
+    HALASSERT(twiceMaxEdgePower > 0);
+    return twiceMaxEdgePower;
+}
+
+/**************************************************************
+ * ar5416GetTargetPowers
+ *
+ * Return the rates of target power for the given target power table
+ * channel, and number of channels
+ */
+static void
+ar5416GetTargetPowers(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan,
+                      CAL_TARGET_POWER_HT *powInfo, uint16_t numChannels,
+                      CAL_TARGET_POWER_HT *pNewPower, uint16_t numRates,
+                      HAL_BOOL isHt40Target)
+{
+    uint16_t clo, chi;
+    int i;
+    int matchIndex = -1, lowIndex = -1;
+    uint16_t freq;
+    CHAN_CENTERS centers;
+
+    ar5416GetChannelCenters(ah,  chan, &centers);
+    freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+
+    /* Copy the target powers into the temp channel list */
+    if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+        matchIndex = 0;
+    } else {
+        for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+            if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) {
+                matchIndex = i;
+                break;
+            } else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) &&
+                       (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))))
+            {
+                lowIndex = i - 1;
+                break;
+            }
+        }
+        if ((matchIndex == -1) && (lowIndex == -1)) {
+            HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)));
+            matchIndex = i - 1;
+        }
+    }
+
+    if (matchIndex != -1) {
+        OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower));
+    } else {
+        HALASSERT(lowIndex != -1);
+        /*
+         * Get the lower and upper channels, target powers,
+         * and interpolate between them.
+         */
+        clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan));
+        chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan));
+
+        for (i = 0; i < numRates; i++) {
+            pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi,
+                                   powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
+        }
+    }
+}
+/**************************************************************
+ * ar5416GetTargetPowersLeg
+ *
+ * Return the four rates of target power for the given target power table
+ * channel, and number of channels
+ */
+static void
+ar5416GetTargetPowersLeg(struct ath_hal *ah,
+                         HAL_CHANNEL_INTERNAL *chan,
+                         CAL_TARGET_POWER_LEG *powInfo, uint16_t numChannels,
+                         CAL_TARGET_POWER_LEG *pNewPower, uint16_t numRates,
+                        HAL_BOOL isExtTarget)
+{
+    uint16_t clo, chi;
+    int i;
+    int matchIndex = -1, lowIndex = -1;
+    uint16_t freq;
+    CHAN_CENTERS centers;
+
+    ar5416GetChannelCenters(ah,  chan, &centers);
+    freq = (isExtTarget) ? centers.ext_center :centers.ctl_center;
+
+    /* Copy the target powers into the temp channel list */
+    if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+        matchIndex = 0;
+    } else {
+        for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+            if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) {
+                matchIndex = i;
+                break;
+            } else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) &&
+                       (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))))
+            {
+                lowIndex = i - 1;
+                break;
+            }
+        }
+        if ((matchIndex == -1) && (lowIndex == -1)) {
+            HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)));
+            matchIndex = i - 1;
+        }
+    }
+
+    if (matchIndex != -1) {
+        OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower));
+    } else {
+        HALASSERT(lowIndex != -1);
+        /*
+         * Get the lower and upper channels, target powers,
+         * and interpolate between them.
+         */
+        clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan));
+        chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan));
+
+        for (i = 0; i < numRates; i++) {
+            pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi,
+                                   powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
+        }
+    }
+}
+
+/**************************************************************
+ * ar5416SetPowerCalTable
+ *
+ * Pull the PDADC piers from cal data and interpolate them across the given
+ * points as well as from the nearest pier(s) to get a power detector
+ * linear voltage to power level table.
+ */
+static HAL_BOOL
+ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, HAL_CHANNEL_INTERNAL *chan, int16_t *pTxPowerIndexOffset)
+{
+    CAL_DATA_PER_FREQ *pRawDataset;
+    uint8_t  *pCalBChans = AH_NULL;
+    uint16_t pdGainOverlap_t2;
+    static uint8_t  pdadcValues[AR5416_NUM_PDADC_VALUES];
+    uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+    uint16_t numPiers, i, j;
+    int16_t  tMinCalPower;
+    uint16_t numXpdGain, xpdMask;
+    uint16_t xpdGainValues[AR5416_NUM_PD_GAINS];
+    uint32_t reg32, regOffset, regChainOffset;
+
+    ath_hal_memzero(xpdGainValues, sizeof(xpdGainValues));
+
+    xpdMask = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].xpdGain;
+
+    if (IS_EEP_MINOR_V2(ah)) {
+        pdGainOverlap_t2 = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pdGainOverlap;
+    } else {
+       pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+    }
+
+    if (IS_CHAN_2GHZ(chan)) {
+        pCalBChans = pEepData->calFreqPier2G;
+        numPiers = AR5416_NUM_2G_CAL_PIERS;
+    } else {
+        pCalBChans = pEepData->calFreqPier5G;
+        numPiers = AR5416_NUM_5G_CAL_PIERS;
+    }
+
+    numXpdGain = 0;
+    /* Calculate the value of xpdgains from the xpdGain Mask */
+    for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+        if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+            if (numXpdGain >= AR5416_NUM_PD_GAINS) {
+                HALASSERT(0);
+                break;
+            }
+            xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
+            numXpdGain++;
+        }
+    }
+
+    /* Write the detector gain biases and their number */
+    OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) &
+       ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) |
+       SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) |
+       SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | SM(xpdGainValues[2],  AR_PHY_TPCRG1_PD_GAIN_3));
+
+    for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+
+            if (AR_SREV_OWL_20_OR_LATER(ah) &&
+            ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) {
+            /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
+             * only chains 0 and 2 populated
+             */
+            regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+        } else {
+            regChainOffset = i * 0x1000;
+        }
+
+        if (pEepData->baseEepHeader.txMask & (1 << i)) {
+            if (IS_CHAN_2GHZ(chan)) {
+                pRawDataset = pEepData->calPierData2G[i];
+            } else {
+                pRawDataset = pEepData->calPierData5G[i];
+            }
+
+            ar5416GetGainBoundariesAndPdadcs(ah,  chan, pRawDataset,
+                                             pCalBChans, numPiers,
+                                             pdGainOverlap_t2,
+                                             &tMinCalPower, gainBoundaries,
+                                             pdadcValues, numXpdGain);
+
+            if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) {
+                /*
+                 * Note the pdadc table may not start at 0 dBm power, could be
+                 * negative or greater than 0.  Need to offset the power
+                 * values by the amount of minPower for griffin
+                 */
+
+                OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+                     SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                     SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)  |
+                     SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)  |
+                     SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)  |
+                     SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+            }
+
+            /* Write the power values into the baseband power table */
+            regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+
+            for (j = 0; j < 32; j++) {
+                reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0)  |
+                    ((pdadcValues[4*j + 1] & 0xFF) << 8)  |
+                    ((pdadcValues[4*j + 2] & 0xFF) << 16) |
+                    ((pdadcValues[4*j + 3] & 0xFF) << 24) ;
+                OS_REG_WRITE(ah, regOffset, reg32);
+
+#ifdef PDADC_DUMP
+               ath_hal_printf(ah, "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",
+                              i,
+                              4*j, pdadcValues[4*j],
+                              4*j+1, pdadcValues[4*j + 1],
+                              4*j+2, pdadcValues[4*j + 2],
+                              4*j+3, pdadcValues[4*j + 3]);
+#endif
+                regOffset += 4;
+            }
+        }
+    }
+    *pTxPowerIndexOffset = 0;
+
+    return AH_TRUE;
+}
+
+/**************************************************************
+ * ar5416GetGainBoundariesAndPdadcs
+ *
+ * Uses the data points read from EEPROM to reconstruct the pdadc power table
+ * Called by ar5416SetPowerCalTable only.
+ */
+static void
+ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
+                                 HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet,
+                                 uint8_t * bChans,  uint16_t availPiers,
+                                 uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries,
+                                 uint8_t * pPDADCValues, uint16_t numXpdGains)
+{
+
+    int       i, j, k;
+    int16_t   ss;         /* potentially -ve index for taking care of pdGainOverlap */
+    uint16_t  idxL = 0, idxR = 0, numPiers; /* Pier indexes */
+
+    /* filled out Vpd table for all pdGains (chanL) */
+    static uint8_t   vpdTableL[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+    /* filled out Vpd table for all pdGains (chanR) */
+    static uint8_t   vpdTableR[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+    /* filled out Vpd table for all pdGains (interpolated) */
+    static uint8_t   vpdTableI[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+    uint8_t   *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+    uint8_t   minPwrT4[AR5416_NUM_PD_GAINS];
+    uint8_t   maxPwrT4[AR5416_NUM_PD_GAINS];
+    int16_t   vpdStep;
+    int16_t   tmpVal;
+    uint16_t  sizeCurrVpdTable, maxIndex, tgtIndex;
+    HAL_BOOL    match;
+    int16_t  minDelta = 0;
+    CHAN_CENTERS centers;
+
+    ar5416GetChannelCenters(ah, chan, &centers);
+
+    /* Trim numPiers for the number of populated channel Piers */
+    for (numPiers = 0; numPiers < availPiers; numPiers++) {
+        if (bChans[numPiers] == AR5416_BCHAN_UNUSED) {
+            break;
+        }
+    }
+
+    /* Find pier indexes around the current channel */
+    match = getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+                       bChans, numPiers, &idxL, &idxR);
+
+    if (match) {
+        /* Directly fill both vpd tables from the matching index */
+        for (i = 0; i < numXpdGains; i++) {
+            minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+            maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+            ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pRawDataSet[idxL].pwrPdg[i],
+                               pRawDataSet[idxL].vpdPdg[i], AR5416_PD_GAIN_ICEPTS, vpdTableI[i]);
+        }
+    } else {
+        for (i = 0; i < numXpdGains; i++) {
+            pVpdL = pRawDataSet[idxL].vpdPdg[i];
+            pPwrL = pRawDataSet[idxL].pwrPdg[i];
+            pVpdR = pRawDataSet[idxR].vpdPdg[i];
+            pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+            /* Start Vpd interpolation from the max of the minimum powers */
+            minPwrT4[i] = AH_MAX(pPwrL[0], pPwrR[0]);
+
+            /* End Vpd interpolation from the min of the max powers */
+            maxPwrT4[i] = AH_MIN(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
+            HALASSERT(maxPwrT4[i] > minPwrT4[i]);
+
+            /* Fill pier Vpds */
+            ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, AR5416_PD_GAIN_ICEPTS, vpdTableL[i]);
+            ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, AR5416_PD_GAIN_ICEPTS, vpdTableR[i]);
+
+            /* Interpolate the final vpd */
+            for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+                vpdTableI[i][j] = (uint8_t)(interpolate((uint16_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+                    bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j]));
+            }
+        }
+    }
+    *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+    k = 0; /* index for the final table */
+    for (i = 0; i < numXpdGains; i++) {
+        if (i == (numXpdGains - 1)) {
+            pPdGainBoundaries[i] = (uint16_t)(maxPwrT4[i] / 2);
+        } else {
+            pPdGainBoundaries[i] = (uint16_t)((maxPwrT4[i] + minPwrT4[i+1]) / 4);
+        }
+
+        pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+       /* NB: only applies to owl 1.0 */
+        if ((i == 0) && !AR_SREV_OWL_20_OR_LATER(ah) ) {
+           /*
+             * fix the gain delta, but get a delta that can be applied to min to
+             * keep the upper power values accurate, don't think max needs to
+             * be adjusted because should not be at that area of the table?
+            */
+            minDelta = pPdGainBoundaries[0] - 23;
+            pPdGainBoundaries[0] = 23;
+        }
+        else {
+            minDelta = 0;
+        }
+
+        /* Find starting index for this pdGain */
+        if (i == 0) {
+            ss = 0; /* for the first pdGain, start from index 0 */
+        } else {
+           /* need overlap entries extrapolated below. */
+            ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta);
+        }
+        vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+        vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+        /*
+         *-ve ss indicates need to extrapolate data below for this pdGain
+         */
+        while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+            tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+            pPDADCValues[k++] = (uint8_t)((tmpVal < 0) ? 0 : tmpVal);
+            ss++;
+        }
+
+        sizeCurrVpdTable = (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 +1);
+        tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2));
+        maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
+
+        while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+            pPDADCValues[k++] = vpdTableI[i][ss++];
+        }
+
+        vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]);
+        vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+        /*
+         * for last gain, pdGainBoundary == Pmax_t2, so will
+         * have to extrapolate
+         */
+        if (tgtIndex > maxIndex) {  /* need to extrapolate above */
+            while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+                tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+                          (ss - maxIndex +1) * vpdStep));
+                pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ? 255 : tmpVal);
+                ss++;
+            }
+        }               /* extrapolated above */
+    }                   /* for all pdGainUsed */
+
+    /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */
+    while (i < AR5416_PD_GAINS_IN_MASK) {
+        pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
+        i++;
+    }
+
+    while (k < AR5416_NUM_PDADC_VALUES) {
+        pPDADCValues[k] = pPDADCValues[k-1];
+        k++;
+    }
+    return;
+}
+
+/**************************************************************
+ * getLowerUppderIndex
+ *
+ * Return indices surrounding the value in sorted integer lists.
+ * Requirement: the input list must be monotonically increasing
+ *     and populated up to the list size
+ * Returns: match is set if an index in the array matches exactly
+ *     or a the target is before or after the range of the array.
+ */
+HAL_BOOL
+getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
+                   uint16_t *indexL, uint16_t *indexR)
+{
+    uint16_t i;
+
+    /*
+     * Check first and last elements for beyond ordered array cases.
+     */
+    if (target <= pList[0]) {
+        *indexL = *indexR = 0;
+        return AH_TRUE;
+    }
+    if (target >= pList[listSize-1]) {
+        *indexL = *indexR = (uint16_t)(listSize - 1);
+        return AH_TRUE;
+    }
+
+    /* look for value being near or between 2 values in list */
+    for (i = 0; i < listSize - 1; i++) {
+        /*
+         * If value is close to the current value of the list
+         * then target is not between values, it is one of the values
+         */
+        if (pList[i] == target) {
+            *indexL = *indexR = i;
+            return AH_TRUE;
+        }
+        /*
+         * Look for value being between current value and next value
+         * if so return these 2 values
+         */
+        if (target < pList[i + 1]) {
+            *indexL = i;
+            *indexR = (uint16_t)(i + 1);
+            return AH_FALSE;
+        }
+    }
+    HALASSERT(0);
+    return AH_FALSE;
+}
+
+/**************************************************************
+ * ar5416FillVpdTable
+ *
+ * Fill the Vpdlist for indices Pmax-Pmin
+ * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
+ */
+static HAL_BOOL
+ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
+                   uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
+{
+    uint16_t  i, k;
+    uint8_t   currPwr = pwrMin;
+    uint16_t  idxL = 0, idxR = 0;
+
+    HALASSERT(pwrMax > pwrMin);
+    for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
+        getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
+                           &(idxL), &(idxR));
+        if (idxR < 1)
+            idxR = 1;           /* extrapolate below */
+        if (idxL == numIntercepts - 1)
+            idxL = (uint16_t)(numIntercepts - 2);   /* extrapolate above */
+        if (pPwrList[idxL] == pPwrList[idxR])
+            k = pVpdList[idxL];
+        else
+            k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
+                  (pPwrList[idxR] - pPwrList[idxL]) );
+        HALASSERT(k < 256);
+        pRetVpdList[i] = (uint8_t)k;
+        currPwr += 2;               /* half dB steps */
+    }
+
+    return AH_TRUE;
+}
+
+/**************************************************************************
+ * interpolate
+ *
+ * Returns signed interpolated or the scaled up interpolated value
+ */
+static int16_t
+interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+            int16_t targetLeft, int16_t targetRight)
+{
+    int16_t rv;
+
+    if (srcRight == srcLeft) {
+        rv = targetLeft;
+    } else {
+        rv = (int16_t)( ((target - srcLeft) * targetRight +
+              (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
+    }
+    return rv;
+}
+
+static void
+ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t phymode;
+       HAL_HT_MACMODE macmode;         /* MAC - 20/40 mode */
+
+       if (!IS_CHAN_HT(chan))
+               return;
+
+       /* Enable 11n HT, 20 MHz */
+       phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
+               | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
+
+       /* Configure baseband for dynamic 20/40 operation */
+       if (IS_CHAN_HT40(chan)) {
+               phymode |= AR_PHY_FC_DYN2040_EN | AR_PHY_FC_SHORT_GI_40;
+
+               /* Configure control (primary) channel at +-10MHz */
+               if ((chan->channelFlags & CHANNEL_HT40PLUS))
+                       phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+#if 0
+               /* Configure 20/25 spacing */
+               if (ht->ht_extprotspacing == HAL_HT_EXTPROTSPACING_25)
+                       phymode |= AR_PHY_FC_DYN2040_EXT_CH;
+#endif
+               macmode = HAL_HT_MACMODE_2040;
+       } else
+               macmode = HAL_HT_MACMODE_20;
+       OS_REG_WRITE(ah, AR_PHY_TURBO, phymode);
+
+       /* Configure MAC for 20/40 operation */
+       ar5416Set11nMac2040(ah, macmode);
+
+       /* global transmit timeout (25 TUs default)*/
+       /* XXX - put this elsewhere??? */
+       OS_REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S) ;
+
+       /* carrier sense timeout */
+       OS_REG_SET_BIT(ah, AR_GTTM, AR_GTTM_CST_USEC);
+       OS_REG_WRITE(ah, AR_CST, 1 << AR_CST_TIMEOUT_LIMIT_S);
+}
+
+void
+ar5416GetChannelCenters(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, CHAN_CENTERS *centers)
+{
+       centers->ctl_center = chan->channel;
+       centers->synth_center = chan->channel;
+       /*
+        * In 20/40 phy mode, the center frequency is
+        * "between" the control and extension channels.
+        */
+       if (chan->channelFlags & CHANNEL_HT40PLUS) {
+               centers->synth_center += HT40_CHANNEL_CENTER_SHIFT;
+               centers->ext_center =
+                   centers->synth_center + HT40_CHANNEL_CENTER_SHIFT;
+       } else if (chan->channelFlags & CHANNEL_HT40MINUS) {
+               centers->synth_center -= HT40_CHANNEL_CENTER_SHIFT;
+               centers->ext_center =
+                   centers->synth_center - HT40_CHANNEL_CENTER_SHIFT;
+       } else {
+               centers->ext_center = chan->channel;
+       }
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416_xmit.c      2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,698 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_xmit.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_desc.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+#include "ar5416/ar5416desc.h"
+
+/*
+ * Stop transmit on the specified queue
+ */
+HAL_BOOL
+ar5416StopTxDma(struct ath_hal *ah, u_int q)
+{
+#define        STOP_DMA_TIMEOUT        4000    /* us */
+#define        STOP_DMA_ITER           100     /* us */
+       u_int i;
+
+       HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
+
+       HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       OS_REG_WRITE(ah, AR_Q_TXD, 1 << q);
+       for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) {
+               if (ar5212NumTxPending(ah, q) == 0)
+                       break;
+               OS_DELAY(STOP_DMA_ITER);
+       }
+#ifdef AH_DEBUG
+       if (i == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: queue %u DMA did not stop in 400 msec\n", __func__, q);
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__,
+                   OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE),
+                   OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q)));
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n",
+                   __func__, OS_REG_READ(ah, AR_QMISC(q)),
+                   OS_REG_READ(ah, AR_QRDYTIMECFG(q)),
+                   OS_REG_READ(ah, AR_Q_RDYTIMESHDN));
+       }
+#endif /* AH_DEBUG */
+
+       /* ar5416 and up can kill packets at the PCU level */
+       if (ar5212NumTxPending(ah, q)) {
+               uint32_t j;
+
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
+                   "%s: Num of pending TX Frames %d on Q %d\n",
+                   __func__, ar5212NumTxPending(ah, q), q);
+
+               /* Kill last PCU Tx Frame */
+               /* TODO - save off and restore current values of Q1/Q2? */
+               for (j = 0; j < 2; j++) {
+                       uint32_t tsfLow = OS_REG_READ(ah, AR_TSF_L32);
+                       OS_REG_WRITE(ah, AR_QUIET2,
+                           SM(10, AR_QUIET2_QUIET_DUR));
+                       OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100);
+                       OS_REG_WRITE(ah, AR_NEXT_QUIET, tsfLow >> 10);
+                       OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
+
+                       if ((OS_REG_READ(ah, AR_TSF_L32)>>10) == (tsfLow>>10))
+                               break;
+
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: TSF moved while trying to set quiet time "
+                           "TSF: 0x%08x\n", __func__, tsfLow);
+                       HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */
+               }
+
+               OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);
+
+               /* Allow the quiet mechanism to do its work */
+               OS_DELAY(200);
+               OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
+
+               /* Verify the transmit q is empty */
+               for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) {
+                       if (ar5212NumTxPending(ah, q) == 0)
+                               break;
+                       OS_DELAY(STOP_DMA_ITER);
+               }
+               if (i == 0) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: Failed to stop Tx DMA in %d msec after killing"
+                           " last frame\n", __func__, STOP_DMA_TIMEOUT / 1000);
+               }
+               OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);
+       }
+
+       OS_REG_WRITE(ah, AR_Q_TXD, 0);
+       return (i != 0);
+#undef STOP_DMA_ITER
+#undef STOP_DMA_TIMEOUT
+}
+
+#define VALID_KEY_TYPES \
+        ((1 << HAL_KEY_TYPE_CLEAR) | (1 << HAL_KEY_TYPE_WEP)|\
+         (1 << HAL_KEY_TYPE_AES)   | (1 << HAL_KEY_TYPE_TKIP))
+#define isValidKeyType(_t)      ((1 << (_t)) & VALID_KEY_TYPES)
+
+#define set11nTries(_series, _index) \
+        (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
+
+#define set11nRate(_series, _index) \
+        (SM((_series)[_index].Rate, AR_XmitRate##_index))
+
+#define set11nPktDurRTSCTS(_series, _index) \
+        (SM((_series)[_index].PktDuration, AR_PacketDur##_index) |\
+         ((_series)[_index].RateFlags & HAL_RATESERIES_RTS_CTS   ?\
+         AR_RTSCTSQual##_index : 0))
+
+#define set11nRateFlags(_series, _index) \
+        ((_series)[_index].RateFlags & HAL_RATESERIES_2040 ? AR_2040_##_index : 0) \
+        |((_series)[_index].RateFlags & HAL_RATESERIES_HALFGI ? AR_GI##_index : 0) \
+        |SM((_series)[_index].ChSel, AR_ChainSel##_index)
+
+/*
+ * Descriptor Access Functions
+ */
+
+#define VALID_PKT_TYPES \
+        ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\
+         (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\
+         (1<<HAL_PKT_TYPE_BEACON)|(1<<HAL_PKT_TYPE_AMPDU))
+#define isValidPktType(_t)      ((1<<(_t)) & VALID_PKT_TYPES)
+#define VALID_TX_RATES \
+        ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\
+         (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\
+         (1<<0x1d)|(1<<0x18)|(1<<0x1c))
+#define isValidTxRate(_r)       ((1<<(_r)) & VALID_TX_RATES)
+
+HAL_BOOL
+ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int pktLen,
+       u_int hdrLen,
+       HAL_PKT_TYPE type,
+       u_int txPower,
+       u_int txRate0, u_int txTries0,
+       u_int keyIx,
+       u_int antMode,
+       u_int flags,
+       u_int rtsctsRate,
+       u_int rtsctsDuration,
+       u_int compicvLen,
+       u_int compivLen,
+       u_int comp)
+{
+#define        RTSCTS  (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       struct ath_hal_5416 *ahp = AH5416(ah);
+
+       (void) hdrLen;
+
+       HALASSERT(txTries0 != 0);
+       HALASSERT(isValidPktType(type));
+       HALASSERT(isValidTxRate(txRate0));
+       HALASSERT((flags & RTSCTS) != RTSCTS);
+       /* XXX validate antMode */
+
+        txPower = (txPower + AH5212(ah)->ah_txPowerIndexOffset);
+        if (txPower > 63)
+               txPower = 63;
+
+       ads->ds_ctl0 = (pktLen & AR_FrameLen)
+                    | (txPower << AR_XmitPower_S)
+                    | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
+                    | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+                    | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+                    ;
+       ads->ds_ctl1 = (type << AR_FrameType_S)
+                    | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0)
+                     ;
+       ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0)
+                    | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEn : 0)
+                    ;
+       ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S)
+                    ;
+       ads->ds_ctl4 = 0;
+       ads->ds_ctl5 = 0;
+       ads->ds_ctl6 = 0;
+       ads->ds_ctl7 = SM(ahp->ah_tx_chainmask, AR_ChainSel0)
+                    | SM(ahp->ah_tx_chainmask, AR_ChainSel1)
+                    | SM(ahp->ah_tx_chainmask, AR_ChainSel2)
+                    | SM(ahp->ah_tx_chainmask, AR_ChainSel3)
+                    ;
+       ads->ds_ctl8 = 0;
+       ads->ds_ctl9 = (txPower << 24);         /* XXX? */
+       ads->ds_ctl10 = (txPower << 24);        /* XXX? */
+       ads->ds_ctl11 = (txPower << 24);        /* XXX? */
+       if (keyIx != HAL_TXKEYIX_INVALID) {
+               /* XXX validate key index */
+               ads->ds_ctl1 |= SM(keyIx, AR_DestIdx);
+               ads->ds_ctl0 |= AR_DestIdxValid;
+               ads->ds_ctl6 |= SM(ahp->ah_keytype[keyIx], AR_EncrType);
+       }
+       if (flags & RTSCTS) {
+               if (!isValidTxRate(rtsctsRate)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid rts/cts rate 0x%x\n",
+                           __func__, rtsctsRate);
+                       return AH_FALSE;
+               }
+               /* XXX validate rtsctsDuration */
+               ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0)
+                            | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0)
+                            ;
+               ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur);
+               ads->ds_ctl7 |= (rtsctsRate << AR_RTSCTSRate_S);
+       }
+       return AH_TRUE;
+#undef RTSCTS
+}
+
+HAL_BOOL
+ar5416SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int txRate1, u_int txTries1,
+       u_int txRate2, u_int txTries2,
+       u_int txRate3, u_int txTries3)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       if (txTries1) {
+               HALASSERT(isValidTxRate(txRate1));
+               ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1);
+               ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S);
+       }
+       if (txTries2) {
+               HALASSERT(isValidTxRate(txRate2));
+               ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2);
+               ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S);
+       }
+       if (txTries3) {
+               HALASSERT(isValidTxRate(txRate3));
+               ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3);
+               ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S);
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+       const struct ath_desc *ds0)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       HALASSERT((segLen &~ AR_BufLen) == 0);
+
+       if (firstSeg) {
+               /*
+                * First descriptor, don't clobber xmit control data
+                * setup by ar5212SetupTxDesc.
+                */
+               ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
+       } else if (lastSeg) {           /* !firstSeg && lastSeg */
+               /*
+                * Last descriptor in a multi-descriptor frame,
+                * copy the multi-rate transmit parameters from
+                * the first frame for processing on completion.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 = segLen;
+#ifdef AH_NEED_DESC_SWAP
+               ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2);
+               ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3);
+#else
+               ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+               ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+#endif
+       } else {                        /* !firstSeg && !lastSeg */
+               /*
+                * Intermediate descriptor in a multi-descriptor frame.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 = segLen | AR_TxMore;
+               ads->ds_ctl2 = 0;
+               ads->ds_ctl3 = 0;
+       }
+       /* XXX only on last descriptor? */
+       OS_MEMZERO(ads->u.tx.status, sizeof(ads->u.tx.status));
+       return AH_TRUE;
+}
+
+#if 0
+
+HAL_BOOL
+ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int pktLen,
+       u_int hdrLen,
+       HAL_PKT_TYPE type,
+       u_int keyIx,
+       HAL_CIPHER cipher,
+       uint8_t delims,
+       u_int segLen,
+       HAL_BOOL firstSeg,
+       HAL_BOOL lastSeg)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
+
+       int isaggr = 0;
+
+       (void) hdrLen;
+       (void) ah;
+
+       HALASSERT((segLen &~ AR_BufLen) == 0);
+
+       HALASSERT(isValidPktType(type));
+       if (type == HAL_PKT_TYPE_AMPDU) {
+               type = HAL_PKT_TYPE_NORMAL;
+               isaggr = 1;
+       }
+
+       if (!firstSeg) {
+               ath_hal_memzero(ds->ds_hw, AR5416_DESC_TX_CTL_SZ);
+       }
+
+       ads->ds_ctl0 = (pktLen & AR_FrameLen);
+       ads->ds_ctl1 = (type << AR_FrameType_S)
+                       | (isaggr ? (AR_IsAggr | AR_MoreAggr) : 0);
+       ads->ds_ctl2 = 0;
+       ads->ds_ctl3 = 0;
+       if (keyIx != HAL_TXKEYIX_INVALID) {
+               /* XXX validate key index */
+               ads->ds_ctl1 |= SM(keyIx, AR_DestIdx);
+               ads->ds_ctl0 |= AR_DestIdxValid;
+       }
+
+       ads->ds_ctl6 = SM(keyType[cipher], AR_EncrType);
+       if (isaggr) {
+               ads->ds_ctl6 |= SM(delims, AR_PadDelim);
+       }
+
+       if (firstSeg) {
+               ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
+       } else if (lastSeg) {           /* !firstSeg && lastSeg */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 |= segLen;
+       } else {                        /* !firstSeg && !lastSeg */
+               /*
+                * Intermediate descriptor in a multi-descriptor frame.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 |= segLen | AR_TxMore;
+       }
+       ds_txstatus[0] = ds_txstatus[1] = 0;
+       ds_txstatus[9] &= ~AR_TxDone;
+
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int aggrLen, u_int flags, u_int txPower,
+       u_int txRate0, u_int txTries0, u_int antMode,
+       u_int rtsctsRate, u_int rtsctsDuration)
+{
+#define RTSCTS  (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(txTries0 != 0);
+       HALASSERT(isValidTxRate(txRate0));
+       HALASSERT((flags & RTSCTS) != RTSCTS);
+       /* XXX validate antMode */
+
+       txPower = (txPower + ahp->ah_txPowerIndexOffset );
+       if(txPower > 63)  txPower=63;
+
+       ads->ds_ctl0 |= (txPower << AR_XmitPower_S)
+               | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
+               | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+               | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0);
+       ads->ds_ctl1 |= (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0);
+       ads->ds_ctl2 |= SM(txTries0, AR_XmitDataTries0);
+       ads->ds_ctl3 |= (txRate0 << AR_XmitRate0_S);
+       ads->ds_ctl7 = SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel0)
+               | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel1)
+               | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel2)
+               | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel3);
+
+       /* NB: no V1 WAR */
+       ads->ds_ctl8 = 0;
+       ads->ds_ctl9 = (txPower << 24);
+       ads->ds_ctl10 = (txPower << 24);
+       ads->ds_ctl11 = (txPower << 24);
+
+       ads->ds_ctl6 &= ~(0xffff);
+       ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
+
+       if (flags & RTSCTS) {
+               /* XXX validate rtsctsDuration */
+               ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0)
+                       | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0);
+               ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur);
+       }
+
+       return AH_TRUE;
+#undef RTSCTS
+}
+
+HAL_BOOL
+ar5416SetupLastTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+               const struct ath_desc *ds0)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       ads->ds_ctl1 &= ~AR_MoreAggr;
+       ads->ds_ctl6 &= ~AR_PadDelim;
+
+       /* hack to copy rate info to last desc for later processing */
+#ifdef AH_NEED_DESC_SWAP
+       ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2);
+       ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3);
+#else
+       ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+       ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+#endif
+
+       return AH_TRUE;
+}
+#endif /* 0 */
+
+#ifdef AH_NEED_DESC_SWAP
+/* Swap transmit descriptor */
+static __inline void
+ar5416SwapTxDesc(struct ath_desc *ds)
+{
+       ds->ds_data = __bswap32(ds->ds_data);
+       ds->ds_ctl0 = __bswap32(ds->ds_ctl0);
+       ds->ds_ctl1 = __bswap32(ds->ds_ctl1);
+       ds->ds_hw[0] = __bswap32(ds->ds_hw[0]);
+       ds->ds_hw[1] = __bswap32(ds->ds_hw[1]);
+       ds->ds_hw[2] = __bswap32(ds->ds_hw[2]);
+       ds->ds_hw[3] = __bswap32(ds->ds_hw[3]);
+}
+#endif
+
+/*
+ * Processing of HW TX descriptor.
+ */
+HAL_STATUS
+ar5416ProcTxDesc(struct ath_hal *ah,
+       struct ath_desc *ds, struct ath_tx_status *ts)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
+
+#ifdef AH_NEED_DESC_SWAP
+       if ((ds_txstatus[9] & __bswap32(AR_TxDone)) == 0)
+               return HAL_EINPROGRESS;
+       ar5416SwapTxDesc(ds);
+#else
+       if ((ds_txstatus[9] & AR_TxDone) == 0)
+               return HAL_EINPROGRESS;
+#endif
+
+       /* Update software copies of the HW status */
+       ts->ts_seqnum = MS(ds_txstatus[9], AR_SeqNum);
+       ts->ts_tstamp = AR_SendTimestamp(ds_txstatus);
+
+       ts->ts_status = 0;
+       if (ds_txstatus[1] & AR_ExcessiveRetries)
+               ts->ts_status |= HAL_TXERR_XRETRY;
+       if (ds_txstatus[1] & AR_Filtered)
+               ts->ts_status |= HAL_TXERR_FILT;
+       if (ds_txstatus[1] & AR_FIFOUnderrun)
+               ts->ts_status |= HAL_TXERR_FIFO;
+       if (ds_txstatus[9] & AR_TxOpExceeded)
+               ts->ts_status |= HAL_TXERR_XTXOP;
+       if (ds_txstatus[1] & AR_TxTimerExpired)
+               ts->ts_status |= HAL_TXERR_TIMER_EXPIRED;
+
+       ts->ts_flags  = 0;
+       if (ds_txstatus[0] & AR_TxBaStatus) {
+               ts->ts_flags |= HAL_TX_BA;
+               ts->ts_ba_low = AR_BaBitmapLow(ds_txstatus);
+               ts->ts_ba_high = AR_BaBitmapHigh(ds_txstatus);
+       }
+       if (ds->ds_ctl1 & AR_IsAggr)
+               ts->ts_flags |= HAL_TX_AGGR;
+       if (ds_txstatus[1] & AR_DescCfgErr)
+               ts->ts_flags |= HAL_TX_DESC_CFG_ERR;
+       if (ds_txstatus[1] & AR_TxDataUnderrun)
+               ts->ts_flags |= HAL_TX_DATA_UNDERRUN;
+       if (ds_txstatus[1] & AR_TxDelimUnderrun)
+               ts->ts_flags |= HAL_TX_DELIM_UNDERRUN;
+
+       /*
+        * Extract the transmit rate used and mark the rate as
+        * ``alternate'' if it wasn't the series 0 rate.
+        */
+       ts->ts_finaltsi =  MS(ds_txstatus[9], AR_FinalTxIdx);
+       switch (ts->ts_finaltsi) {
+       case 0:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0);
+               break;
+       case 1:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       case 2:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       case 3:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       }
+
+       ts->ts_rssi = MS(ds_txstatus[5], AR_TxRSSICombined);
+       ts->ts_rssi_ctl[0] = MS(ds_txstatus[0], AR_TxRSSIAnt00);
+       ts->ts_rssi_ctl[1] = MS(ds_txstatus[0], AR_TxRSSIAnt01);
+       ts->ts_rssi_ctl[2] = MS(ds_txstatus[0], AR_TxRSSIAnt02);
+       ts->ts_rssi_ext[0] = MS(ds_txstatus[5], AR_TxRSSIAnt10);
+       ts->ts_rssi_ext[1] = MS(ds_txstatus[5], AR_TxRSSIAnt11);
+       ts->ts_rssi_ext[2] = MS(ds_txstatus[5], AR_TxRSSIAnt12);
+       ts->ts_evm0 = AR_TxEVM0(ds_txstatus);
+       ts->ts_evm1 = AR_TxEVM1(ds_txstatus);
+       ts->ts_evm2 = AR_TxEVM2(ds_txstatus);
+
+       ts->ts_shortretry = MS(ds_txstatus[1], AR_RTSFailCnt);
+       ts->ts_longretry = MS(ds_txstatus[1], AR_DataFailCnt);
+       /*
+        * The retry count has the number of un-acked tries for the
+        * final series used.  When doing multi-rate retry we must
+        * fixup the retry count by adding in the try counts for
+        * each series that was fully-processed.  Beware that this
+        * takes values from the try counts in the final descriptor.
+        * These are not required by the hardware.  We assume they
+        * are placed there by the driver as otherwise we have no
+        * access and the driver can't do the calculation because it
+        * doesn't know the descriptor format.
+        */
+       switch (ts->ts_finaltsi) {
+       case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2);
+       case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1);
+       case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0);
+       }
+
+       /*
+        * These fields are not used. Zero these to preserve compatability
+        * with existing drivers.
+        */
+       ts->ts_virtcol = MS(ads->ds_ctl1, AR_VirtRetryCnt);
+       ts->ts_antenna = 0; /* We don't switch antennas on Owl*/
+
+       /* handle tx trigger level changes internally */
+       if ((ts->ts_status & HAL_TXERR_FIFO) ||
+           (ts->ts_flags & (HAL_TX_DATA_UNDERRUN | HAL_TX_DELIM_UNDERRUN)))
+               ar5212UpdateTxTrigLevel(ah, AH_TRUE);
+
+       return HAL_OK;
+}
+
+#if 0
+HAL_BOOL
+ar5416SetGlobalTxTimeout(struct ath_hal *ah, u_int tu)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+
+       if (tu > 0xFFFF) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad global tx timeout %u\n",
+                   __func__, tu);
+               /* restore default handling */
+               ahp->ah_globaltxtimeout = (u_int) -1;
+               return AH_FALSE;
+       }
+       OS_REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
+       ahp->ah_globaltxtimeout = tu;
+       return AH_TRUE;
+}
+
+u_int
+ar5416GetGlobalTxTimeout(struct ath_hal *ah)
+{
+       return MS(OS_REG_READ(ah, AR_GTXTO), AR_GTXTO_TIMEOUT_LIMIT);
+}
+
+void
+ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds,
+        u_int durUpdateEn, u_int rtsctsRate,
+       HAL_11N_RATE_SERIES series[], u_int nseries)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       HALASSERT(nseries == 4);
+       (void)nseries;
+
+
+       ads->ds_ctl2 = set11nTries(series, 0)
+                    | set11nTries(series, 1)
+                    | set11nTries(series, 2)
+                    | set11nTries(series, 3)
+                    | (durUpdateEn ? AR_DurUpdateEn : 0);
+
+       ads->ds_ctl3 = set11nRate(series, 0)
+                    | set11nRate(series, 1)
+                    | set11nRate(series, 2)
+                    | set11nRate(series, 3);
+
+       ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
+                    | set11nPktDurRTSCTS(series, 1);
+
+       ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
+                    | set11nPktDurRTSCTS(series, 3);
+
+       ads->ds_ctl7 = set11nRateFlags(series, 0)
+                    | set11nRateFlags(series, 1)
+                    | set11nRateFlags(series, 2)
+                    | set11nRateFlags(series, 3)
+                    | SM(rtsctsRate, AR_RTSCTSRate);
+
+       /*
+        * Enable RTSCTS if any of the series is flagged for RTSCTS,
+        * but only if CTS is not enabled.
+        */
+       /*
+        * FIXME : the entire RTS/CTS handling should be moved to this
+        * function (by passing the global RTS/CTS flags to this function).
+        * currently it is split between this function and the
+        * setupFiirstDescriptor. with this current implementation there
+        * is an implicit assumption that setupFirstDescriptor is called
+        * before this function.
+        */
+       if (((series[0].RateFlags & HAL_RATESERIES_RTS_CTS) ||
+            (series[1].RateFlags & HAL_RATESERIES_RTS_CTS) ||
+            (series[2].RateFlags & HAL_RATESERIES_RTS_CTS) ||
+            (series[3].RateFlags & HAL_RATESERIES_RTS_CTS) )  &&
+           (ads->ds_ctl0 & AR_CTSEnable) == 0) {
+               ads->ds_ctl0 |= AR_RTSEnable;
+               ads->ds_ctl0 &= ~AR_CTSEnable;
+       }
+}
+
+void
+ar5416Set11nAggrMiddle(struct ath_hal *ah, struct ath_desc *ds, u_int numDelims)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
+
+       ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+
+       ads->ds_ctl6 &= ~AR_PadDelim;
+       ads->ds_ctl6 |= SM(numDelims, AR_PadDelim);
+       ads->ds_ctl6 &= ~AR_AggrLen;
+
+       /*
+        * Clear the TxDone status here, may need to change
+        * func name to reflect this
+        */
+       ds_txstatus[9] &= ~AR_TxDone;
+}
+
+void
+ar5416Clr11nAggr(struct ath_hal *ah, struct ath_desc *ds)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+       ads->ds_ctl6 &= ~AR_PadDelim;
+       ads->ds_ctl6 &= ~AR_AggrLen;
+}
+
+void
+ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds,
+                                                  u_int burstDuration)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       ads->ds_ctl2 &= ~AR_BurstDur;
+       ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
+}
+#endif
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416desc.h       2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416desc.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _ATH_AR5416_DESC_H_
+#define _ATH_AR5416_DESC_H
+
+/*
+ * Hardware-specific descriptor structures.
+ */
+#include "ah_desc.h"
+
+/* XXX Need to replace this with a dynamic
+ * method of determining Owl2 if possible
+ */
+#define _get_index(_ah) ( IS_5416V1(_ah)  ? -4 : 0 )
+#define AR5416_DS_TXSTATUS(_ah, _ads) \
+       ((uint32_t*)(&(_ads)->u.tx.status[_get_index(_ah)]))
+#define AR5416_DS_TXSTATUS_CONST(_ah, _ads) \
+       ((const uint32_t*)(&(_ads)->u.tx.status[_get_index(_ah)]))
+
+#define AR5416_NUM_TX_STATUS   10 /* Number of TX status words */
+/* Clear the whole descriptor */
+#define AR5416_DESC_TX_CTL_SZ  sizeof(struct ar5416_tx_desc)
+
+struct ar5416_tx_desc { /* tx desc has 12 control words + 10 status words */
+       uint32_t        ctl2;
+       uint32_t        ctl3;
+       uint32_t        ctl4;
+       uint32_t        ctl5;
+       uint32_t        ctl6;
+       uint32_t        ctl7;
+       uint32_t        ctl8;
+       uint32_t        ctl9;
+       uint32_t        ctl10;
+       uint32_t        ctl11;
+       uint32_t        status[AR5416_NUM_TX_STATUS];
+};
+
+struct ar5416_rx_desc { /* rx desc has 2 control words + 9 status words */
+       uint32_t        status0;
+       uint32_t        status1;
+       uint32_t        status2;
+       uint32_t        status3;
+       uint32_t        status4;
+       uint32_t        status5;
+       uint32_t        status6;
+       uint32_t        status7;
+       uint32_t        status8;
+};
+
+
+struct ar5416_desc {
+       uint32_t   ds_link;    /* link pointer */
+       uint32_t   ds_data;    /* data buffer pointer */
+       uint32_t   ds_ctl0;    /* DMA control 0 */
+       uint32_t   ds_ctl1;    /* DMA control 1 */
+       union {
+               struct ar5416_tx_desc tx;
+               struct ar5416_rx_desc rx;
+       } u;
+} __packed;
+#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds))
+#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds))
+
+#define ds_ctl2     u.tx.ctl2
+#define ds_ctl3     u.tx.ctl3
+#define ds_ctl4     u.tx.ctl4
+#define ds_ctl5     u.tx.ctl5
+#define ds_ctl6     u.tx.ctl6
+#define ds_ctl7     u.tx.ctl7
+#define ds_ctl8     u.tx.ctl8
+#define ds_ctl9     u.tx.ctl9
+#define ds_ctl10    u.tx.ctl10
+#define ds_ctl11    u.tx.ctl11
+
+#define ds_rxstatus0    u.rx.status0
+#define ds_rxstatus1    u.rx.status1
+#define ds_rxstatus2    u.rx.status2
+#define ds_rxstatus3    u.rx.status3
+#define ds_rxstatus4    u.rx.status4
+#define ds_rxstatus5    u.rx.status5
+#define ds_rxstatus6    u.rx.status6
+#define ds_rxstatus7    u.rx.status7
+#define ds_rxstatus8    u.rx.status8
+
+/***********
+ * TX Desc *
+ ***********/
+
+/* ds_ctl0 */
+#define AR_FrameLen         0x00000fff
+#define AR_VirtMoreFrag     0x00001000
+#define AR_TxCtlRsvd00      0x0000e000
+#define AR_XmitPower        0x003f0000
+#define AR_XmitPower_S      16
+#define AR_RTSEnable        0x00400000
+#define AR_VEOL             0x00800000
+#define AR_ClrDestMask      0x01000000
+#define AR_TxCtlRsvd01      0x1e000000
+#define AR_TxIntrReq        0x20000000
+#define AR_DestIdxValid     0x40000000
+#define AR_CTSEnable        0x80000000
+
+/* ds_ctl1 */
+#define AR_BufLen           0x00000fff
+#define AR_TxMore           0x00001000
+#define AR_DestIdx          0x000fe000
+#define AR_DestIdx_S        13
+#define AR_FrameType        0x00f00000
+#define AR_FrameType_S      20
+#define AR_NoAck            0x01000000
+#define AR_InsertTS         0x02000000
+#define AR_CorruptFCS       0x04000000
+#define AR_ExtOnly          0x08000000
+#define AR_ExtAndCtl        0x10000000
+#define AR_MoreAggr         0x20000000
+#define AR_IsAggr           0x40000000
+#define AR_MoreRifs        0x80000000
+
+/* ds_ctl2 */
+#define AR_BurstDur         0x00007fff
+#define AR_BurstDur_S       0
+#define AR_DurUpdateEn      0x00008000
+#define AR_XmitDataTries0   0x000f0000
+#define AR_XmitDataTries0_S 16
+#define AR_XmitDataTries1   0x00f00000
+#define AR_XmitDataTries1_S 20
+#define AR_XmitDataTries2   0x0f000000
+#define AR_XmitDataTries2_S 24
+#define AR_XmitDataTries3   0xf0000000
+#define AR_XmitDataTries3_S 28
+
+/* ds_ctl3 */
+#define AR_XmitRate0        0x000000ff
+#define AR_XmitRate0_S      0
+#define AR_XmitRate1        0x0000ff00
+#define AR_XmitRate1_S      8
+#define AR_XmitRate2        0x00ff0000
+#define AR_XmitRate2_S      16
+#define AR_XmitRate3        0xff000000
+#define AR_XmitRate3_S      24
+
+/* ds_ctl4 */
+#define AR_PacketDur0       0x00007fff
+#define AR_PacketDur0_S     0
+#define AR_RTSCTSQual0      0x00008000
+#define AR_PacketDur1       0x7fff0000
+#define AR_PacketDur1_S     16
+#define AR_RTSCTSQual1      0x80000000
+
+/* ds_ctl5 */
+#define AR_PacketDur2       0x00007fff
+#define AR_PacketDur2_S     0
+#define AR_RTSCTSQual2      0x00008000
+#define AR_PacketDur3       0x7fff0000
+#define AR_PacketDur3_S     16
+#define AR_RTSCTSQual3      0x80000000
+
+/* ds_ctl6 */
+#define AR_AggrLen          0x0000ffff
+#define AR_AggrLen_S        0
+#define AR_TxCtlRsvd60      0x00030000
+#define AR_PadDelim         0x03fc0000
+#define AR_PadDelim_S       18
+#define AR_EncrType         0x0c000000
+#define AR_EncrType_S       26
+#define AR_TxCtlRsvd61      0xf0000000
+
+/* ds_ctl7 */
+#define AR_2040_0           0x00000001
+#define AR_GI0              0x00000002
+#define AR_ChainSel0        0x0000001c
+#define AR_ChainSel0_S      2
+#define AR_2040_1           0x00000020
+#define AR_GI1              0x00000040
+#define AR_ChainSel1        0x00000380
+#define AR_ChainSel1_S      7
+#define AR_2040_2           0x00000400
+#define AR_GI2              0x00000800
+#define AR_ChainSel2        0x00007000
+#define AR_ChainSel2_S      12
+#define AR_2040_3           0x00008000
+#define AR_GI3              0x00010000
+#define AR_ChainSel3        0x000e0000
+#define AR_ChainSel3_S      17
+#define AR_RTSCTSRate       0x0ff00000
+#define AR_RTSCTSRate_S     20
+#define        AR_STBC0            0x10000000
+#define        AR_STBC1            0x20000000
+#define        AR_STBC2            0x40000000
+#define        AR_STBC3            0x80000000
+
+/*************
+ * TX Status *
+ *************/
+
+/* ds_status0 */
+#define AR_TxRSSIAnt00      0x000000ff
+#define AR_TxRSSIAnt00_S    0
+#define AR_TxRSSIAnt01      0x0000ff00
+#define AR_TxRSSIAnt01_S    8
+#define AR_TxRSSIAnt02      0x00ff0000
+#define AR_TxRSSIAnt02_S    16
+#define AR_TxStatusRsvd00   0x3f000000
+#define AR_TxBaStatus       0x40000000
+#define AR_TxStatusRsvd01   0x80000000
+
+/* ds_status1 */
+#define AR_FrmXmitOK            0x00000001
+#define AR_ExcessiveRetries     0x00000002
+#define AR_FIFOUnderrun         0x00000004
+#define AR_Filtered             0x00000008
+#define AR_RTSFailCnt           0x000000f0
+#define AR_RTSFailCnt_S         4
+#define AR_DataFailCnt          0x00000f00
+#define AR_DataFailCnt_S        8
+#define AR_VirtRetryCnt         0x0000f000
+#define AR_VirtRetryCnt_S       12
+#define AR_TxDelimUnderrun      0x00010000
+#define AR_TxDelimUnderrun_S    13
+#define AR_TxDataUnderrun       0x00020000
+#define AR_TxDataUnderrun_S     14
+#define AR_DescCfgErr           0x00040000
+#define AR_DescCfgErr_S         15
+#define        AR_TxTimerExpired       0x00080000
+#define AR_TxStatusRsvd10       0xfff00000
+
+/* ds_status2 */
+#define AR_SendTimestamp(_ptr)   (_ptr)[2]
+
+/* ds_status3 */
+#define AR_BaBitmapLow(_ptr)     (_ptr)[3]
+
+/* ds_status4 */
+#define AR_BaBitmapHigh(_ptr)    (_ptr)[4]
+
+/* ds_status5 */
+#define AR_TxRSSIAnt10      0x000000ff
+#define AR_TxRSSIAnt10_S    0
+#define AR_TxRSSIAnt11      0x0000ff00
+#define AR_TxRSSIAnt11_S    8
+#define AR_TxRSSIAnt12      0x00ff0000
+#define AR_TxRSSIAnt12_S    16
+#define AR_TxRSSICombined   0xff000000
+#define AR_TxRSSICombined_S 24
+
+/* ds_status6 */
+#define AR_TxEVM0(_ptr)     (_ptr)[6]
+
+/* ds_status7 */
+#define AR_TxEVM1(_ptr)    (_ptr)[7]
+
+/* ds_status8 */
+#define AR_TxEVM2(_ptr)   (_ptr)[8]
+
+/* ds_status9 */
+#define AR_TxDone           0x00000001
+#define AR_SeqNum           0x00001ffe
+#define AR_SeqNum_S         1
+#define AR_TxStatusRsvd80   0x0001e000
+#define AR_TxOpExceeded     0x00020000
+#define AR_TxStatusRsvd81   0x001c0000
+#define AR_FinalTxIdx       0x00600000
+#define AR_FinalTxIdx_S     21
+#define AR_TxStatusRsvd82   0x01800000
+#define AR_PowerMgmt        0x02000000
+#define AR_TxStatusRsvd83   0xfc000000
+
+/***********
+ * RX Desc *
+ ***********/
+
+/* ds_ctl0 */
+#define AR_RxCTLRsvd00  0xffffffff
+
+/* ds_ctl1 */
+#define AR_BufLen       0x00000fff
+#define AR_RxCtlRsvd00  0x00001000
+#define AR_RxIntrReq    0x00002000
+#define AR_RxCtlRsvd01  0xffffc000
+
+/*************
+ * Rx Status *
+ *************/
+
+/* ds_status0 */
+#define AR_RxRSSIAnt00      0x000000ff
+#define AR_RxRSSIAnt00_S    0
+#define AR_RxRSSIAnt01      0x0000ff00
+#define AR_RxRSSIAnt01_S    8
+#define AR_RxRSSIAnt02      0x00ff0000
+#define AR_RxRSSIAnt02_S    16
+/* Rev specific */
+/* Owl 1.x only */
+#define AR_RxStatusRsvd00   0xff000000
+/* Owl 2.x only */
+#define AR_RxRate           0xff000000
+#define AR_RxRate_S         24
+
+/* ds_status1 */
+#define AR_DataLen          0x00000fff
+#define AR_RxMore           0x00001000
+#define AR_NumDelim         0x003fc000
+#define AR_NumDelim_S       14
+#define AR_RxStatusRsvd10   0xff800000
+
+/* ds_status2 */
+#define AR_RcvTimestamp     ds_rxstatus2
+
+/* ds_status3 */
+#define AR_GI               0x00000001
+#define AR_2040             0x00000002
+/* Rev specific */
+/* Owl 1.x only */
+#define AR_RxRateV1         0x000003fc
+#define AR_RxRateV1_S       2
+#define AR_Parallel40       0x00000400
+#define AR_RxStatusRsvd30   0xfffff800
+/* Owl 2.x only */
+#define AR_DupFrame        0x00000004
+#define AR_RxAntenna        0xffffff00
+#define AR_RxAntenna_S      8
+
+/* ds_status4 */
+#define AR_RxRSSIAnt10            0x000000ff
+#define AR_RxRSSIAnt10_S          0
+#define AR_RxRSSIAnt11            0x0000ff00
+#define AR_RxRSSIAnt11_S          8
+#define AR_RxRSSIAnt12            0x00ff0000
+#define AR_RxRSSIAnt12_S          16
+#define AR_RxRSSICombined         0xff000000
+#define AR_RxRSSICombined_S       24
+
+/* ds_status5 */
+#define AR_RxEVM0           ds_rxstatus5
+
+/* ds_status6 */
+#define AR_RxEVM1           ds_rxstatus6
+
+/* ds_status7 */
+#define AR_RxEVM2           ds_rxstatus7
+
+/* ds_status8 */
+#define AR_RxDone           0x00000001
+#define AR_RxFrameOK        0x00000002
+#define AR_CRCErr           0x00000004
+#define AR_DecryptCRCErr    0x00000008
+#define AR_PHYErr           0x00000010
+#define AR_MichaelErr       0x00000020
+#define AR_PreDelimCRCErr   0x00000040
+#define AR_RxStatusRsvd70   0x00000080
+#define AR_RxKeyIdxValid    0x00000100
+#define AR_KeyIdx           0x0000fe00
+#define AR_KeyIdx_S         9
+#define AR_PHYErrCode       0x0000ff00
+#define AR_PHYErrCode_S     8
+#define AR_RxMoreAggr       0x00010000
+#define AR_RxAggr           0x00020000
+#define AR_PostDelimCRCErr  0x00040000
+#define AR_RxStatusRsvd71   0x2ff80000
+#define        AR_HiRxChain        0x10000000
+#define AR_DecryptBusyErr   0x40000000
+#define AR_KeyMiss          0x80000000
+
+#define TXCTL_OFFSET(ah)       2
+#define TXCTL_NUMWORDS(ah)     (AR_SREV_5416_V20_OR_LATER(ah) ? 12 : 8)
+#define TXSTATUS_OFFSET(ah)    (AR_SREV_5416_V20_OR_LATER(ah) ? 14 : 10)
+#define TXSTATUS_NUMWORDS(ah)  10
+
+#define RXCTL_OFFSET(ah)       3
+#define RXCTL_NUMWORDS(ah)     1
+#define RXSTATUS_OFFSET(ah)    4
+#define RXSTATUS_NUMWORDS(ah)  9
+#define RXSTATUS_RATE(ah, ads) \
+       (AR_SREV_OWL_20_OR_LATER(ah) ? \
+        MS((ads)->ds_rxstatus0, AR_RxRate) : \
+        ((ads)->ds_rxstatus3 >> 2) & 0xFF)
+#define RXSTATUS_DUPLICATE(ah, ads) \
+       (AR_SREV_OWL_20_OR_LATER(ah) ?  \
+        MS((ads)->ds_rxstatus3, AR_Parallel40) : \
+        ((ads)->ds_rxstatus3 >> 10) & 0x1)
+#endif /* _ATH_AR5416_DESC_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416phy.h        2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416phy.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5416PHY_H_
+#define _DEV_ATH_AR5416PHY_H_
+
+#include "ar5212/ar5212phy.h"
+
+#define AR_PHY_CHIP_ID_REV_0    0x80        /* 5416 Rev 0 (owl 1.0) BB */
+#define AR_PHY_CHIP_ID_REV_1    0x81        /* 5416 Rev 1 (owl 2.0) BB */
+
+#define RFSILENT_BB             0x00002000      /* shush bb */
+#define AR_PHY_RESTART         0x9970      /* restart */
+#define AR_PHY_RESTART_DIV_GC   0x001C0000  /* bb_ant_fast_div_gc_limit */
+#define AR_PHY_RESTART_DIV_GC_S 18
+
+/* PLL settling times */
+#define RTC_PLL_SETTLE_DELAY           1000    /* 1 ms     */
+#define HT40_CHANNEL_CENTER_SHIFT      10      /* MHz      */
+
+#define AR_PHY_RFBUS_REQ        0x997C
+#define AR_PHY_RFBUS_REQ_EN     0x00000001
+
+#define AR_2040_MODE                0x8318
+#define AR_2040_JOINED_RX_CLEAR     0x00000001   // use ctl + ext rx_clear for cca
+
+#define AR_PHY_FC_TURBO_SHORT       0x00000002  /* Set short symbols to turbo mode setting */
+#define AR_PHY_FC_DYN2040_EN        0x00000004      /* Enable dyn 20/40 mode */
+#define AR_PHY_FC_DYN2040_PRI_ONLY  0x00000008      /* dyn 20/40 - primary only */
+#define AR_PHY_FC_DYN2040_PRI_CH    0x00000010      /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/
+#define AR_PHY_FC_DYN2040_EXT_CH    0x00000020      /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */
+#define AR_PHY_FC_HT_EN             0x00000040      /* ht enable */
+#define AR_PHY_FC_SHORT_GI_40       0x00000080      /* allow short GI for HT 40 */
+#define AR_PHY_FC_WALSH             0x00000100      /* walsh spatial spreading for 2 chains,2 streams TX */
+#define AR_PHY_FC_SINGLE_HT_LTF1    0x00000200      /* single length (4us) 1st HT long training symbol */
+
+#define AR_PHY_TIMING2      0x9810      /* Timing Control 2 */
+#define AR_PHY_TIMING2_USE_FORCE    0x00001000
+#define AR_PHY_TIMING2_FORCE_VAL    0x00000fff
+
+#define        AR_PHY_TIMING_CTRL4_CHAIN(_i) \
+       (AR_PHY_TIMING_CTRL4 + ((_i) << 12))
+#define        AR_PHY_TIMING_CTRL4_DO_CAL  0x10000         /* perform calibration */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F   /* Mask for kcos_theta-1 for q correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S   0   /* shift for Q_COFF */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0   /* Mask for sin_theta for i correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5   /* Shift for sin_theta for i correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE   0x800   /* enable IQ correction */
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000  /* Mask for max number of samples (logarithmic) */
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S   12  /* Shift for max number of samples */
+
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI   0x80000000
+#define        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER  0x40000000      /* Enable spur filter */
+#define        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK    0x20000000
+#define        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK   0x10000000
+
+#define AR_PHY_ADC_SERIAL_CTL       0x9830
+#define AR_PHY_SEL_INTERNAL_ADDAC   0x00000000
+#define AR_PHY_SEL_EXTERNAL_RADIO   0x00000001
+
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN    0x00003C00
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S  10
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN     0x0000001F
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S   0
+
+#define AR_PHY_EXT_CCA          0x99bc
+#define AR_PHY_EXT_CCA_CYCPWR_THR1      0x0000FE00
+#define AR_PHY_EXT_CCA_CYCPWR_THR1_S    9
+#define AR_PHY_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_EXT_MINCCA_PWR_S 23
+#define AR_PHY_EXT_CCA_THRESH62        0x007F0000
+#define AR_PHY_EXT_CCA_THRESH62_S      16
+#define AR9280_PHY_EXT_MINCCA_PWR       0x01FF0000
+#define AR9280_PHY_EXT_MINCCA_PWR_S     16
+
+#define AR_PHY_HALFGI           0x99D0      /* Timing control 3 */
+#define AR_PHY_HALFGI_DSC_MAN   0x0007FFF0
+#define AR_PHY_HALFGI_DSC_MAN_S 4
+#define AR_PHY_HALFGI_DSC_EXP   0x0000000F
+#define AR_PHY_HALFGI_DSC_EXP_S 0
+
+#define AR_PHY_HEAVY_CLIP_ENABLE    0x99E0
+
+#define AR_PHY_M_SLEEP      0x99f0      /* sleep control registers */
+#define AR_PHY_REFCLKDLY    0x99f4
+#define AR_PHY_REFCLKPD     0x99f8
+
+#define        AR_PHY_CALMODE          0x99f0
+/* Calibration Types */
+#define        AR_PHY_CALMODE_IQ               0x00000000
+#define        AR_PHY_CALMODE_ADC_GAIN         0x00000001
+#define        AR_PHY_CALMODE_ADC_DC_PER       0x00000002
+#define        AR_PHY_CALMODE_ADC_DC_INIT      0x00000003
+/* Calibration results */
+#define        AR_PHY_CAL_MEAS_0(_i)   (0x9c10 + ((_i) << 12))
+#define        AR_PHY_CAL_MEAS_1(_i)   (0x9c14 + ((_i) << 12))
+#define        AR_PHY_CAL_MEAS_2(_i)   (0x9c18 + ((_i) << 12))
+#define        AR_PHY_CAL_MEAS_3(_i)   (0x9c1c + ((_i) << 12))
+
+
+#define AR_PHY_CCA          0x9864
+#define AR_PHY_MINCCA_PWR   0x0FF80000
+#define AR_PHY_MINCCA_PWR_S 19
+#define AR9280_PHY_MINCCA_PWR       0x1FF00000
+#define AR9280_PHY_MINCCA_PWR_S     20
+#define AR9280_PHY_CCA_THRESH62     0x000FF000
+#define AR9280_PHY_CCA_THRESH62_S   12
+
+#define AR_PHY_CH1_CCA          0xa864
+#define AR_PHY_CH1_MINCCA_PWR   0x0FF80000
+#define AR_PHY_CH1_MINCCA_PWR_S 19
+#define AR_PHY_CCA_THRESH62     0x0007F000
+#define AR_PHY_CCA_THRESH62_S   12
+#define AR9280_PHY_CH1_MINCCA_PWR   0x1FF00000
+#define AR9280_PHY_CH1_MINCCA_PWR_S 20
+
+#define AR_PHY_CH2_CCA          0xb864
+#define AR_PHY_CH2_MINCCA_PWR   0x0FF80000
+#define AR_PHY_CH2_MINCCA_PWR_S 19
+
+#define AR_PHY_CH1_EXT_CCA          0xa9bc
+#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
+
+#define AR_PHY_CH2_EXT_CCA          0xb9bc
+#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
+
+#define AR_PHY_RX_CHAINMASK     0x99a4
+
+#define        AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
+#define        AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define        AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE    0x80000000
+#define        AR_PHY_MULTICHAIN_GAIN_CTL      0x99ac
+
+#define        AR_PHY_EXT_CCA0                 0x99b8
+#define        AR_PHY_EXT_CCA0_THRESH62        0x000000FF
+#define        AR_PHY_EXT_CCA0_THRESH62_S      0
+
+#define AR_PHY_CH1_EXT_CCA          0xa9bc
+#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
+
+#define AR_PHY_CH2_EXT_CCA          0xb9bc
+#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
+#define AR_PHY_ANALOG_SWAP      0xa268
+#define AR_PHY_SWAP_ALT_CHAIN   0x00000040
+#define AR_PHY_CAL_CHAINMASK   0xa39c
+
+#define AR_PHY_SWITCH_CHAIN_0     0x9960
+#define AR_PHY_SWITCH_COM         0x9964
+
+#define AR_PHY_RF_CTL2                  0x9824
+#define AR_PHY_TX_FRAME_TO_DATA_START  0x000000FF
+#define AR_PHY_TX_FRAME_TO_DATA_START_S        0
+#define AR_PHY_TX_FRAME_TO_PA_ON       0x0000FF00
+#define AR_PHY_TX_FRAME_TO_PA_ON_S     8
+
+#define AR_PHY_RF_CTL3                  0x9828
+#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S     16
+
+#define AR_PHY_RF_CTL4                    0x9834
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF    0xFF000000
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S  24
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF    0x00FF0000
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S  16
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON      0x0000FF00
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S    8
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON      0x000000FF
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S    0
+
+#define        AR_PHY_SYNTH_CONTROL    0x9874
+
+#define        AR_PHY_FORCE_CLKEN_CCK  0xA22C
+#define        AR_PHY_FORCE_CLKEN_CCK_MRC_MUX  0x00000040
+
+#define AR_PHY_POWER_TX_SUB     0xA3C8
+#define AR_PHY_POWER_TX_RATE5   0xA38C
+#define AR_PHY_POWER_TX_RATE6   0xA390
+#define AR_PHY_POWER_TX_RATE7   0xA3CC
+#define AR_PHY_POWER_TX_RATE8   0xA3D0
+#define AR_PHY_POWER_TX_RATE9   0xA3D4
+
+#define        AR_PHY_TPCRG1_PD_GAIN_1         0x00030000
+#define        AR_PHY_TPCRG1_PD_GAIN_1_S       16
+#define        AR_PHY_TPCRG1_PD_GAIN_2         0x000C0000
+#define        AR_PHY_TPCRG1_PD_GAIN_2_S       18
+#define        AR_PHY_TPCRG1_PD_GAIN_3         0x00300000
+#define        AR_PHY_TPCRG1_PD_GAIN_3_S       20
+
+#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
+#define AR_PHY_MASK2_M_31_45     0xa3a4
+#define AR_PHY_MASK2_M_16_30     0xa3a8
+#define AR_PHY_MASK2_M_00_15     0xa3ac
+#define AR_PHY_MASK2_P_15_01     0xa3b8
+#define AR_PHY_MASK2_P_30_16     0xa3bc
+#define AR_PHY_MASK2_P_45_31     0xa3c0
+#define AR_PHY_MASK2_P_61_45     0xa3c4
+
+#define        AR_PHY_SPUR_REG         0x994c
+#define        AR_PHY_SFCORR_EXT       0x99c0
+#define        AR_PHY_SFCORR_EXT_M1_THRESH     0x0000007F
+#define        AR_PHY_SFCORR_EXT_M1_THRESH_S   0
+#define        AR_PHY_SFCORR_EXT_M2_THRESH     0x00003F80
+#define        AR_PHY_SFCORR_EXT_M2_THRESH_S   7
+#define        AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
+#define        AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S       14
+#define        AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
+#define        AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S       21
+#define        AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
+
+/* enable vit puncture per rate, 8 bits, lsb is low rate */
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL       (0xFF << 18)
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S     18
+
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM      0x20000     /* bins move with freq offset */
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT     (0xFF << 9) /* use mask1 or mask2, one per rate */
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S   9
+#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH     0x7F
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S   0
+
+#define AR_PHY_PILOT_MASK_01_30   0xa3b0
+#define AR_PHY_PILOT_MASK_31_60   0xa3b4
+
+#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
+#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
+
+#define        AR_PHY_CL_CAL_CTL       0xA358          /* carrier leak cal control */
+#define        AR_PHY_CL_CAL_ENABLE    0x00000002
+#endif /* _DEV_ATH_AR5416PHY_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar5416reg.h        2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416reg.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5416REG_H
+#define        _DEV_ATH_AR5416REG_H
+
+#include "ar5212/ar5212reg.h"
+
+/*
+ * Register added starting with the AR5416
+ */
+#define        AR_MIRT                 0x0020  /* interrupt rate threshold */
+#define        AR_TIMT                 0x0028  /* Tx Interrupt mitigation threshold */
+#define        AR_RIMT                 0x002C  /* Rx Interrupt mitigation threshold */
+#define        AR_GTXTO                0x0064  /* global transmit timeout */
+#define        AR_GTTM                 0x0068  /* global transmit timeout mode */
+#define        AR_CST                  0x006C  /* carrier sense timeout */
+#define        AR_MAC_LED              0x1f04  /* LED control */
+#define        AR5416_PCIE_PM_CTRL     0x4014
+#define        AR_AHB_MODE             0x4024  /* AHB mode for dma */
+#define        AR_INTR_SYNC_CAUSE_CLR  0x4028  /* clear interrupt */
+#define        AR_INTR_SYNC_CAUSE      0x4028  /* check pending interrupts */
+#define        AR_INTR_SYNC_ENABLE     0x402c  /* enable interrupts */
+#define        AR_INTR_ASYNC_MASK      0x4030  /* asynchronous interrupt mask */
+#define        AR_INTR_SYNC_MASK       0x4034  /* synchronous interrupt mask */
+#define        AR_INTR_ASYNC_CAUSE     0x4038  /* check pending interrupts */
+#define        AR_INTR_ASYNC_ENABLE    0x403c  /* enable interrupts */
+#define        AR5416_PCIE_SERDES      0x4040
+#define        AR5416_PCIE_SERDES2     0x4044
+#define        AR_GPIO_IN              0x4048  /* GPIO input register */
+#define        AR_GPIO_INTR_OUT        0x404c  /* GPIO output register */
+#define        AR_EEPROM_STATUS_DATA   0x407c
+#define        AR_OBS                  0x4080
+#define        AR_RTC_RC               0x7000  /* reset control */
+#define        AR_RTC_PLL_CONTROL      0x7014
+#define        AR_RTC_RESET            0x7040  /* RTC reset register */
+#define        AR_RTC_STATUS           0x7044  /* system sleep status */
+#define        AR_RTC_SLEEP_CLK        0x7048
+#define        AR_RTC_FORCE_WAKE       0x704c  /* control MAC force wake */
+#define        AR_RTC_INTR_CAUSE       0x7050  /* RTC interrupt cause/clear */
+#define        AR_RTC_INTR_ENABLE      0x7054  /* RTC interrupt enable */
+#define        AR_RTC_INTR_MASK        0x7058  /* RTC interrupt mask */
+/* AR9280: rf long shift registers */
+#define        AR_AN_RF2G1_CH0         0x7810
+#define        AR_AN_RF5G1_CH0         0x7818
+#define        AR_AN_RF2G1_CH1         0x7834
+#define        AR_AN_RF5G1_CH1         0x783C
+#define        AR_AN_TOP2              0x7894
+#define        AR_AN_SYNTH9            0x7868
+#define        AR9285_AN_RF2G3         0x7828
+#define        AR9285_AN_TOP3          0x786c
+#define        AR_RESET_TSF            0x8020
+#define        AR_RXFIFO_CFG           0x8114
+#define        AR_PHY_ERR_1            0x812c
+#define        AR_PHY_ERR_MASK_1       0x8130  /* mask for AR_PHY_ERR_1 */
+#define        AR_PHY_ERR_2            0x8134
+#define        AR_PHY_ERR_MASK_2       0x8138  /* mask for AR_PHY_ERR_2 */
+#define        AR_TSFOOR_THRESHOLD     0x813c
+#define        AR_PHY_ERR_3            0x8168
+#define        AR_PHY_ERR_MASK_3       0x816c  /* mask for AR_PHY_ERR_3 */
+#define        AR_TXOP_X               0x81ec  /* txop for legacy non-qos */
+#define        AR_TXOP_0_3             0x81f0  /* txop for various tid's */
+#define        AR_TXOP_4_7             0x81f4
+#define        AR_TXOP_8_11            0x81f8
+#define        AR_TXOP_12_15           0x81fc
+/* generic timers based on tsf - all uS */
+#define        AR_NEXT_TBTT            0x8200
+#define        AR_NEXT_DBA             0x8204
+#define        AR_NEXT_SWBA            0x8208
+#define        AR_NEXT_CFP             0x8208
+#define        AR_NEXT_HCF             0x820C
+#define        AR_NEXT_TIM             0x8210
+#define        AR_NEXT_DTIM            0x8214
+#define        AR_NEXT_QUIET           0x8218
+#define        AR_NEXT_NDP             0x821C
+#define        AR5416_BEACON_PERIOD    0x8220
+#define        AR_DBA_PERIOD           0x8224
+#define        AR_SWBA_PERIOD          0x8228
+#define        AR_HCF_PERIOD           0x822C
+#define        AR_TIM_PERIOD           0x8230
+#define        AR_DTIM_PERIOD          0x8234
+#define        AR_QUIET_PERIOD         0x8238
+#define        AR_NDP_PERIOD           0x823C
+#define        AR_TIMER_MODE           0x8240
+#define        AR_SLP32_MODE           0x8244
+#define        AR_SLP32_WAKE           0x8248
+#define        AR_SLP32_INC            0x824c
+#define        AR_SLP_CNT              0x8250  /* 32kHz cycles with mac asleep */
+#define        AR_SLP_CYCLE_CNT        0x8254  /* absolute number of 32kHz cycles */
+#define        AR_SLP_MIB_CTRL         0x8258
+#define        AR_2040_MODE            0x8318
+#define        AR_EXTRCCNT             0x8328  /* extension channel rx clear count */
+#define        AR_SELFGEN_MASK         0x832c  /* rx and cal chain masks */
+#define        AR_PCU_TXBUF_CTRL       0x8340
+
+/* DMA & PCI Registers in PCI space (usable during sleep)*/
+#define        AR_RC_AHB               0x00000001      /* AHB reset */
+#define        AR_RC_APB               0x00000002      /* APB reset */
+#define        AR_RC_HOSTIF            0x00000100      /* host interface reset */
+
+#define        AR_MIRT_VAL             0x0000ffff      /* in uS */
+#define        AR_MIRT_VAL_S           16
+
+#define        AR_TIMT_LAST            0x0000ffff      /* Last packet threshold */
+#define        AR_TIMT_LAST_S          0
+#define        AR_TIMT_FIRST           0xffff0000      /* First packet threshold */
+#define        AR_TIMT_FIRST_S         16
+
+#define        AR_RIMT_LAST            0x0000ffff      /* Last packet threshold */
+#define        AR_RIMT_LAST_S          0
+#define        AR_RIMT_FIRST           0xffff0000      /* First packet threshold */
+#define        AR_RIMT_FIRST_S         16
+
+#define        AR_GTXTO_TIMEOUT_COUNTER    0x0000FFFF  // Mask for timeout counter (in TUs)
+#define        AR_GTXTO_TIMEOUT_LIMIT      0xFFFF0000  // Mask for timeout limit (in  TUs)
+#define        AR_GTXTO_TIMEOUT_LIMIT_S    16      // Shift for timeout limit
+
+#define        AR_GTTM_USEC          0x00000001 // usec strobe
+#define        AR_GTTM_IGNORE_IDLE   0x00000002 // ignore channel idle
+#define        AR_GTTM_RESET_IDLE    0x00000004 // reset counter on channel idle low
+#define        AR_GTTM_CST_USEC      0x00000008 // CST usec strobe
+
+#define        AR_CST_TIMEOUT_COUNTER    0x0000FFFF  // Mask for timeout counter (in TUs)
+#define        AR_CST_TIMEOUT_LIMIT      0xFFFF0000  // Mask for timeout limit (in  TUs)
+#define        AR_CST_TIMEOUT_LIMIT_S    16      // Shift for timeout limit
+
+/* MAC tx DMA size config  */
+#define        AR_TXCFG_DMASZ_MASK     0x00000003
+#define        AR_TXCFG_DMASZ_4B       0
+#define        AR_TXCFG_DMASZ_8B       1
+#define        AR_TXCFG_DMASZ_16B      2
+#define        AR_TXCFG_DMASZ_32B      3
+#define        AR_TXCFG_DMASZ_64B      4
+#define        AR_TXCFG_DMASZ_128B     5
+#define        AR_TXCFG_DMASZ_256B     6
+#define        AR_TXCFG_DMASZ_512B     7
+#define        AR_TXCFG_ATIM_TXPOLICY  0x00000800
+
+/* MAC rx DMA size config  */
+#define        AR_RXCFG_DMASZ_MASK     0x00000007
+#define        AR_RXCFG_DMASZ_4B       0
+#define        AR_RXCFG_DMASZ_8B       1
+#define        AR_RXCFG_DMASZ_16B      2
+#define        AR_RXCFG_DMASZ_32B      3
+#define        AR_RXCFG_DMASZ_64B      4
+#define        AR_RXCFG_DMASZ_128B     5
+#define        AR_RXCFG_DMASZ_256B     6
+#define        AR_RXCFG_DMASZ_512B     7
+
+/* MAC Led registers */
+#define        AR_MAC_LED_BLINK_SLOW   0x00000008      /* LED slowest blink rate mode */
+#define        AR_MAC_LED_BLINK_THRESH_SEL 0x00000070  /* LED blink threshold select */
+#define        AR_MAC_LED_MODE         0x00000380      /* LED mode select */
+#define        AR_MAC_LED_MODE_S       7
+#define        AR_MAC_LED_MODE_PROP    0       /* Blink prop to filtered tx/rx */
+#define        AR_MAC_LED_MODE_RPROP   1       /* Blink prop to unfiltered tx/rx */
+#define        AR_MAC_LED_MODE_SPLIT   2       /* Blink power for tx/net for rx */
+#define        AR_MAC_LED_MODE_RAND    3       /* Blink randomly */
+#define        AR_MAC_LED_MODE_POWON   5       /* Power LED on (s/w control) */
+#define        AR_MAC_LED_MODE_NETON   6       /* Network LED on (s/w control) */
+#define        AR_MAC_LED_ASSOC        0x00000c00
+#define        AR_MAC_LED_ASSOC_NONE   0x00000000 /* STA is not associated or trying */
+#define        AR_MAC_LED_ASSOC_ACTIVE 0x00000400 /* STA is associated */
+#define        AR_MAC_LED_ASSOC_PEND   0x00000800 /* STA is trying to associate */
+#define        AR_MAC_LED_ASSOC_S      10
+
+#define        AR_AHB_EXACT_WR_EN      0x00000000      /* write exact bytes */
+#define        AR_AHB_BUF_WR_EN        0x00000001      /* buffer write upto cacheline*/
+#define        AR_AHB_EXACT_RD_EN      0x00000000      /* read exact bytes */
+#define        AR_AHB_CACHELINE_RD_EN  0x00000002      /* read upto end of cacheline */
+#define        AR_AHB_PREFETCH_RD_EN   0x00000004      /* prefetch upto page boundary*/
+#define        AR_AHB_PAGE_SIZE_1K     0x00000000      /* set page-size as 1k */
+#define        AR_AHB_PAGE_SIZE_2K     0x00000008      /* set page-size as 2k */
+#define        AR_AHB_PAGE_SIZE_4K     0x00000010      /* set page-size as 4k */
+
+/* MAC PCU Registers */
+#define        AR_STA_ID1_PRESERVE_SEQNUM      0x20000000 /* Don't replace seq num */
+
+/* Extended PCU DIAG_SW control fields */
+#define        AR_DIAG_DUAL_CHAIN_INFO 0x01000000      /* dual chain channel info */
+#define        AR_DIAG_RX_ABORT        0x02000000      /* abort rx */
+#define        AR_DIAG_SATURATE_CCNT   0x04000000      /* sat. cycle cnts (no shift) */
+#define        AR_DIAG_OBS_PT_SEL2     0x08000000      /* observation point sel */
+#define        AR_DIAG_RXCLEAR_CTL_LOW 0x10000000      /* force rx_clear(ctl) low/busy */
+#define        AR_DIAG_RXCLEAR_EXT_LOW 0x20000000      /* force rx_clear(ext) low/busy */
+
+#define        AR_TXOP_X_VAL   0x000000FF
+
+#define        AR_RESET_TSF_ONCE       0x01000000      /* reset tsf once; self-clears*/
+
+/* Interrupts */
+#define        AR_ISR_TXMINTR          0x00080000      /* Maximum interrupt tx rate */
+#define        AR_ISR_RXMINTR          0x01000000      /* Maximum interrupt rx rate */
+#define        AR_ISR_TXINTM           0x40000000      /* Tx int after mitigation */
+#define        AR_ISR_RXINTM           0x80000000      /* Rx int after mitigation */
+
+#define        AR_ISR_S2_CST           0x00400000      /* Carrier sense timeout */
+#define        AR_ISR_S2_GTT           0x00800000      /* Global transmit timeout */
+#define        AR_ISR_S2_TSFOOR        0x40000000      /* RX TSF out of range */
+
+#define        AR_INTR_SPURIOUS        0xffffffff
+#define        AR_INTR_RTC_IRQ         0x00000001      /* rtc in shutdown state */
+#define        AR_INTR_MAC_IRQ         0x00000002      /* pending mac interrupt */
+#define        AR_INTR_EEP_PROT_ACCESS 0x00000004      /* eeprom protected access */
+#define        AR_INTR_MAC_AWAKE       0x00020000      /* mac is awake */
+#define        AR_INTR_MAC_ASLEEP      0x00040000      /* mac is asleep */
+
+/* Interrupt Mask Registers */
+#define        AR_IMR_TXMINTR          0x00080000      /* Maximum interrupt tx rate */
+#define        AR_IMR_RXMINTR          0x01000000      /* Maximum interrupt rx rate */
+#define        AR_IMR_TXINTM           0x40000000      /* Tx int after mitigation */
+#define        AR_IMR_RXINTM           0x80000000      /* Rx int after mitigation */
+
+#define        AR_IMR_S2_CST           0x00400000      /* Carrier sense timeout */
+#define        AR_IMR_S2_GTT           0x00800000      /* Global transmit timeout */
+
+/* synchronous interrupt signals */
+#define        AR_INTR_SYNC_RTC_IRQ            0x00000001
+#define        AR_INTR_SYNC_MAC_IRQ            0x00000002
+#define        AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS      0x00000004
+#define        AR_INTR_SYNC_APB_TIMEOUT        0x00000008
+#define        AR_INTR_SYNC_PCI_MODE_CONFLICT  0x00000010
+#define        AR_INTR_SYNC_HOST1_FATAL        0x00000020
+#define        AR_INTR_SYNC_HOST1_PERR         0x00000040
+#define        AR_INTR_SYNC_TRCV_FIFO_PERR     0x00000080
+#define        AR_INTR_SYNC_RADM_CPL_EP        0x00000100
+#define        AR_INTR_SYNC_RADM_CPL_DLLP_ABORT        0x00000200
+#define        AR_INTR_SYNC_RADM_CPL_TLP_ABORT 0x00000400
+#define        AR_INTR_SYNC_RADM_CPL_ECRC_ERR  0x00000800
+#define        AR_INTR_SYNC_RADM_CPL_TIMEOUT   0x00001000
+#define        AR_INTR_SYNC_LOCAL_TIMEOUT      0x00002000
+#define        AR_INTR_SYNC_PM_ACCESS          0x00004000
+#define        AR_INTR_SYNC_MAC_AWAKE          0x00008000
+#define        AR_INTR_SYNC_MAC_ASLEEP         0x00010000
+#define        AR_INTR_SYNC_MAC_SLEEP_ACCESS   0x00020000
+#define        AR_INTR_SYNC_ALL                0x0003FFFF
+
+/* default synchronous interrupt signals enabled */
+#define        AR_INTR_SYNC_DEFAULT \
+       (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR | \
+        AR_INTR_SYNC_RADM_CPL_EP | AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | \
+        AR_INTR_SYNC_RADM_CPL_TLP_ABORT | AR_INTR_SYNC_RADM_CPL_ECRC_ERR | \
+        AR_INTR_SYNC_RADM_CPL_TIMEOUT | AR_INTR_SYNC_LOCAL_TIMEOUT | \
+        AR_INTR_SYNC_MAC_SLEEP_ACCESS)
+
+/* RTC registers */
+#define        AR_RTC_RC_M             0x00000003
+#define        AR_RTC_RC_MAC_WARM      0x00000001
+#define        AR_RTC_RC_MAC_COLD      0x00000002
+#define        AR_RTC_PLL_DIV          0x0000001f
+#define        AR_RTC_PLL_DIV_S        0
+#define        AR_RTC_PLL_DIV2         0x00000020
+#define        AR_RTC_PLL_REFDIV_5     0x000000c0
+
+#define        AR_RTC_SOWL_PLL_DIV             0x000003ff
+#define        AR_RTC_SOWL_PLL_DIV_S           0
+#define        AR_RTC_SOWL_PLL_REFDIV          0x00003C00
+#define        AR_RTC_SOWL_PLL_REFDIV_S        10
+#define        AR_RTC_SOWL_PLL_CLKSEL          0x0000C000
+#define        AR_RTC_SOWL_PLL_CLKSEL_S        14
+
+#define        AR_RTC_RESET_EN         0x00000001      /* Reset RTC bit */
+
+#define        AR_RTC_PM_STATUS_M      0x0000000f      /* Pwr Mgmt Status */
+#define        AR_RTC_STATUS_M         0x0000003f      /* RTC Status */
+#define        AR_RTC_STATUS_SHUTDOWN  0x00000001
+#define        AR_RTC_STATUS_ON        0x00000002
+#define        AR_RTC_STATUS_SLEEP     0x00000004
+#define        AR_RTC_STATUS_WAKEUP    0x00000008
+#define        AR_RTC_STATUS_COLDRESET 0x00000010      /* Not currently used */
+#define        AR_RTC_STATUS_PLLCHANGE 0x00000020      /* Not currently used */
+
+#define        AR_RTC_SLEEP_DERIVED_CLK        0x2
+
+#define        AR_RTC_FORCE_WAKE_EN    0x00000001      /* enable force wake */
+#define        AR_RTC_FORCE_WAKE_ON_INT 0x00000002     /* auto-wake on MAC interrupt */
+
+#define        AR_RTC_PLL_CLKSEL       0x00000300
+#define        AR_RTC_PLL_CLKSEL_S     8
+
+/* AR9280: rf long shift registers */
+#define        AR_AN_RF2G1_CH0_OB      0x03800000
+#define        AR_AN_RF2G1_CH0_OB_S    23
+#define        AR_AN_RF2G1_CH0_DB      0x1C000000
+#define        AR_AN_RF2G1_CH0_DB_S    26
+
+#define        AR_AN_RF5G1_CH0_OB5     0x00070000
+#define        AR_AN_RF5G1_CH0_OB5_S   16
+#define        AR_AN_RF5G1_CH0_DB5     0x00380000
+#define        AR_AN_RF5G1_CH0_DB5_S   19
+
+#define        AR_AN_RF2G1_CH1_OB      0x03800000
+#define        AR_AN_RF2G1_CH1_OB_S    23
+#define        AR_AN_RF2G1_CH1_DB      0x1C000000
+#define        AR_AN_RF2G1_CH1_DB_S    26
+
+#define        AR_AN_RF5G1_CH1_OB5     0x00070000
+#define        AR_AN_RF5G1_CH1_OB5_S   16
+#define        AR_AN_RF5G1_CH1_DB5     0x00380000
+#define        AR_AN_RF5G1_CH1_DB5_S   19
+
+#define        AR_AN_TOP2_XPABIAS_LVL      0xC0000000
+#define        AR_AN_TOP2_XPABIAS_LVL_S    30
+#define        AR_AN_TOP2_LOCALBIAS        0x00200000
+#define        AR_AN_TOP2_LOCALBIAS_S      21
+#define        AR_AN_TOP2_PWDCLKIND        0x00400000
+#define        AR_AN_TOP2_PWDCLKIND_S      22
+
+#define        AR_AN_SYNTH9_REFDIVA    0xf8000000
+#define        AR_AN_SYNTH9_REFDIVA_S  27
+
+/* AR9285 Analog registers */
+#define        AR9285_AN_RF2G3_OB_0    0x00E00000
+#define        AR9285_AN_RF2G3_OB_0_S    21
+#define        AR9285_AN_RF2G3_OB_1    0x001C0000
+#define        AR9285_AN_RF2G3_OB_1_S    18
+#define        AR9285_AN_RF2G3_OB_2    0x00038000
+#define        AR9285_AN_RF2G3_OB_2_S    15
+#define        AR9285_AN_RF2G3_OB_3    0x00007000
+#define        AR9285_AN_RF2G3_OB_3_S    12
+#define        AR9285_AN_RF2G3_OB_4    0x00000E00
+#define        AR9285_AN_RF2G3_OB_4_S    9
+
+#define        AR9285_AN_RF2G3_DB1_0    0x000001C0
+#define        AR9285_AN_RF2G3_DB1_0_S    6
+#define        AR9285_AN_RF2G3_DB1_1    0x00000038
+#define        AR9285_AN_RF2G3_DB1_1_S    3
+#define        AR9285_AN_RF2G3_DB1_2    0x00000007
+#define        AR9285_AN_RF2G3_DB1_2_S    0
+#define        AR9285_AN_RF2G4         0x782C
+#define        AR9285_AN_RF2G4_DB1_3    0xE0000000
+#define        AR9285_AN_RF2G4_DB1_3_S    29
+#define        AR9285_AN_RF2G4_DB1_4    0x1C000000
+#define        AR9285_AN_RF2G4_DB1_4_S    26
+
+#define        AR9285_AN_RF2G4_DB2_0    0x03800000
+#define        AR9285_AN_RF2G4_DB2_0_S    23
+#define        AR9285_AN_RF2G4_DB2_1    0x00700000
+#define        AR9285_AN_RF2G4_DB2_1_S    20
+#define        AR9285_AN_RF2G4_DB2_2    0x000E0000
+#define        AR9285_AN_RF2G4_DB2_2_S    17
+#define        AR9285_AN_RF2G4_DB2_3    0x0001C000
+#define        AR9285_AN_RF2G4_DB2_3_S    14
+#define        AR9285_AN_RF2G4_DB2_4    0x00003800
+#define        AR9285_AN_RF2G4_DB2_4_S    11
+
+#define        AR9285_AN_TOP3_XPABIAS_LVL      0x0000000C
+#define        AR9285_AN_TOP3_XPABIAS_LVL_S    2
+
+/* Sleep control */
+#define        AR5416_SLEEP1_CAB_TIMEOUT       0xFFE00000      /* Cab timeout (TU) */
+#define        AR5416_SLEEP1_CAB_TIMEOUT_S     22
+
+#define        AR5416_SLEEP2_BEACON_TIMEOUT    0xFFE00000      /* Beacon timeout (TU)*/
+#define        AR5416_SLEEP2_BEACON_TIMEOUT_S  22
+
+/* Sleep Registers */
+#define        AR_SLP32_HALFCLK_LATENCY      0x000FFFFF        /* rising <-> falling edge */
+#define        AR_SLP32_ENA            0x00100000
+#define        AR_SLP32_TSF_WRITE_STATUS      0x00200000       /* tsf update in progress */
+
+#define        AR_SLP32_WAKE_XTL_TIME  0x0000FFFF      /* time to wake crystal */
+
+#define        AR_SLP32_TST_INC        0x000FFFFF
+
+#define        AR_SLP_MIB_CLEAR        0x00000001      /* clear pending */
+#define        AR_SLP_MIB_PENDING      0x00000002      /* clear counters */
+
+#define        AR_TIMER_MODE_TBTT              0x00000001
+#define        AR_TIMER_MODE_DBA               0x00000002
+#define        AR_TIMER_MODE_SWBA              0x00000004
+#define        AR_TIMER_MODE_HCF               0x00000008
+#define        AR_TIMER_MODE_TIM               0x00000010
+#define        AR_TIMER_MODE_DTIM              0x00000020
+#define        AR_TIMER_MODE_QUIET             0x00000040
+#define        AR_TIMER_MODE_NDP               0x00000080
+#define        AR_TIMER_MODE_OVERFLOW_INDEX    0x00000700
+#define        AR_TIMER_MODE_OVERFLOW_INDEX_S  8
+#define        AR_TIMER_MODE_THRESH            0xFFFFF000
+#define        AR_TIMER_MODE_THRESH_S          12
+
+/* PCU Misc modes */
+#define        AR_PCU_FORCE_BSSID_MATCH        0x00000001 /* force bssid to match */
+#define        AR_PCU_MIC_NEW_LOC_ENA          0x00000004 /* tx/rx mic keys together */
+#define        AR_PCU_TX_ADD_TSF               0x00000008 /* add tx_tsf + int_tsf */
+#define        AR_PCU_CCK_SIFS_MODE            0x00000010 /* assume 11b sifs */
+#define        AR_PCU_RX_ANT_UPDT              0x00000800 /* KC_RX_ANT_UPDATE */
+#define        AR_PCU_TXOP_TBTT_LIMIT_ENA      0x00001000 /* enforce txop / tbtt */
+#define        AR_PCU_MISS_BCN_IN_SLEEP        0x00004000 /* count bmiss's when sleeping */
+#define        AR_PCU_BUG_12306_FIX_ENA        0x00020000 /* use rx_clear to count sifs */
+#define        AR_PCU_FORCE_QUIET_COLL         0x00040000 /* kill xmit for channel change */
+#define        AR_PCU_TBTT_PROTECT             0x00200000 /* no xmit upto tbtt+20 uS */
+#define        AR_PCU_CLEAR_VMF                0x01000000 /* clear vmf mode (fast cc)*/
+#define        AR_PCU_CLEAR_BA_VALID           0x04000000 /* clear ba state */
+
+/* GPIO Interrupt */
+#define        AR_INTR_GPIO            0x3FF00000      /* gpio interrupted */
+#define        AR_INTR_GPIO_S          20
+
+#define        AR_GPIO_OUT_CTRL        0x000003FF      /* 0 = out, 1 = in */
+#define        AR_GPIO_OUT_VAL         0x000FFC00
+#define        AR_GPIO_OUT_VAL_S       10
+#define        AR_GPIO_INTR_CTRL       0x3FF00000
+#define        AR_GPIO_INTR_CTRL_S     20
+
+#define        AR_2040_JOINED_RX_CLEAR 0x00000001      /* use ctl + ext rx_clear for cca */
+
+#define        AR_PCU_TXBUF_CTRL_SIZE_MASK     0x7FF
+#define        AR_PCU_TXBUF_CTRL_USABLE_SIZE   0x700
+
+/* Eeprom defines */
+#define        AR_EEPROM_STATUS_DATA_VAL           0x0000ffff
+#define        AR_EEPROM_STATUS_DATA_VAL_S         0
+#define        AR_EEPROM_STATUS_DATA_BUSY          0x00010000
+#define        AR_EEPROM_STATUS_DATA_BUSY_ACCESS   0x00020000
+#define        AR_EEPROM_STATUS_DATA_PROT_ACCESS   0x00040000
+#define        AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000
+
+#define        AR_SREV_REVISION_OWL_10         0x08
+#define        AR_SREV_REVISION_OWL_20         0x09
+#define        AR_SREV_REVISION_OWL_22         0x0a
+
+#define        AR_RAD5133_SREV_MAJOR           0xc0    /* Fowl: 2+5G/3x3 */
+#define        AR_RAD2133_SREV_MAJOR           0xd0    /* Fowl: 2G/3x3   */
+#define        AR_RAD5122_SREV_MAJOR           0xe0    /* Fowl: 5G/2x2   */
+#define        AR_RAD2122_SREV_MAJOR           0xf0    /* Fowl: 2+5G/2x2 */
+
+/* Test macro for owl 1.0 */
+#define        IS_5416V1(_ah)  ((_ah)->ah_macRev == AR_SREV_REVISION_OWL_10)
+#define        IS_5416V2(_ah)  ((_ah)->ah_macRev >= AR_SREV_REVISION_OWL_20)
+#define        IS_5416V2_2(_ah)        ((_ah)->ah_macRev == AR_SREV_REVISION_OWL_22)
+
+/* Expanded Mac Silicon Rev (16 bits starting with Sowl) */
+#define        AR_XSREV_ID             0xFFFFFFFF      /* Chip ID */
+#define        AR_XSREV_ID_S           0
+#define        AR_XSREV_VERSION        0xFFFC0000      /* Chip version */
+#define        AR_XSREV_VERSION_S      18
+#define        AR_XSREV_TYPE           0x0003F000      /* Chip type */
+#define        AR_XSREV_TYPE_S         12
+#define        AR_XSREV_TYPE_CHAIN     0x00001000      /* Chain Mode (1:3 chains,
+                                                * 0:2 chains) */
+#define        AR_XSREV_TYPE_HOST_MODE 0x00002000      /* Host Mode (1:PCI, 0:PCIe) */
+#define        AR_XSREV_REVISION       0x00000F00
+#define        AR_XSREV_REVISION_S     8
+
+#define        AR_XSREV_VERSION_OWL_PCI        0x0D
+#define        AR_XSREV_VERSION_OWL_PCIE       0x0C
+#define        AR_XSREV_REVISION_OWL_10        0       /* Owl 1.0 */
+#define        AR_XSREV_REVISION_OWL_20        1       /* Owl 2.0/2.1 */
+#define        AR_XSREV_REVISION_OWL_22        2       /* Owl 2.2 */
+#define        AR_XSREV_VERSION_SOWL           0x40
+#define        AR_XSREV_REVISION_SOWL_10       0       /* Sowl 1.0 */
+#define        AR_XSREV_REVISION_SOWL_11       1       /* Sowl 1.1 */
+#define        AR_XSREV_VERSION_MERLIN         0x80    /* Merlin Version */
+#define        AR_XSREV_REVISION_MERLIN_10     0       /* Merlin 1.0 */
+#define        AR_XSREV_REVISION_MERLIN_20     1       /* Merlin 2.0 */
+#define        AR_XSREV_REVISION_MERLIN_21     2       /* Merlin 2.1 */
+#define        AR_XSREV_VERSION_KITE           0xC0    /* Kite Version */
+#define        AR_XSREV_REVISION_KITE_10       0       /* Kite 1.0 */
+
+#define        AR_SREV_OWL_20_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL || \
+        AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_20)
+#define        AR_SREV_OWL_22_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL || \
+        AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_22)
+
+#define        AR_SREV_SOWL(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_SOWL)
+#define        AR_SREV_SOWL_10_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL)
+#define        AR_SREV_SOWL_11(_ah) \
+       (AR_SREV_SOWL(_ah) && \
+        AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_SOWL_11)
+
+#define        AR_SREV_MERLIN(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_MERLIN)
+#define        AR_SREV_MERLIN_10_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_MERLIN)
+#define        AR_SREV_MERLIN_20(_ah) \
+       (AR_SREV_MERLIN(_ah) && \
+        AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_MERLIN_20)
+#define        AR_SREV_MERLIN_20_OR_LATER(_ah) \
+       (AR_SREV_MERLIN_20(_ah) || \
+        AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_MERLIN)
+
+#define        AR_SREV_KITE(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_KITE)
+#define        AR_SREV_KITE_10_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_KITE)
+#endif /* _DEV_ATH_AR5416REG_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar9160.ini 2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,699 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar9160.ini,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+/* Auto Generated PCI Register Writes.  Created: 05/22/08 */
+
+static const uint32_t ar9160Modes[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
+    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 },
+    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
+    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+    { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
+    { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
+    { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce },
+    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 },
+    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
+    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
+    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
+    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
+    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
+    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
+    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
+    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
+    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
+    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
+    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
+    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
+    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
+    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const uint32_t ar9160Common[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+    { 0x00007010, 0x00000020 },
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0x00000000 },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c4, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x00008300, 0x00000000 },
+    { 0x00008304, 0x00000000 },
+    { 0x00008308, 0x00000000 },
+    { 0x0000830c, 0x00000000 },
+    { 0x00008310, 0x00000000 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008318, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00000000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xad848e19 },
+    { 0x00009810, 0x7d14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x00009840, 0x206a01ae },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009854, 0x00000859 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x05100000 },
+    { 0x0000a920, 0x05100000 },
+    { 0x0000b920, 0x05100000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280b212 },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5f3ca3de },
+    { 0x00009958, 0x2108ecff },
+    { 0x00009940, 0x00750604 },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x00009970, 0x190fb515 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x201fff00 },
+    { 0x000099ac, 0x006f0000 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000200 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x0cc80caa },
+    { 0x000099fc, 0x00001042 },
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b28, 0x0000000c },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b38, 0x00000012 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b64, 0x00000021 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b8c, 0x0000002d },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009b9c, 0x00000033 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+    { 0x0000a210, 0x40806333 },
+    { 0x0000a214, 0x00106c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x018830c6 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x001a0bb5 },
+    { 0x0000a22c, 0x00000000 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000001 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000c26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x050701ce },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa33 },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x0c000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+};
+
+static const uint32_t ar9160Bank0[][2] = {
+    { 0x000098b0, 0x1e5795e5 },
+    { 0x000098e0, 0x02008020 },
+};
+
+static const uint32_t ar9160BB_RfGain[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000040, 0x00000040 },
+    { 0x00009a08, 0x00000080, 0x00000080 },
+    { 0x00009a0c, 0x000001a1, 0x00000141 },
+    { 0x00009a10, 0x000001e1, 0x00000181 },
+    { 0x00009a14, 0x00000021, 0x000001c1 },
+    { 0x00009a18, 0x00000061, 0x00000001 },
+    { 0x00009a1c, 0x00000168, 0x00000041 },
+    { 0x00009a20, 0x000001a8, 0x000001a8 },
+    { 0x00009a24, 0x000001e8, 0x000001e8 },
+    { 0x00009a28, 0x00000028, 0x00000028 },
+    { 0x00009a2c, 0x00000068, 0x00000068 },
+    { 0x00009a30, 0x00000189, 0x000000a8 },
+    { 0x00009a34, 0x000001c9, 0x00000169 },
+    { 0x00009a38, 0x00000009, 0x000001a9 },
+    { 0x00009a3c, 0x00000049, 0x000001e9 },
+    { 0x00009a40, 0x00000089, 0x00000029 },
+    { 0x00009a44, 0x00000170, 0x00000069 },
+    { 0x00009a48, 0x000001b0, 0x00000190 },
+    { 0x00009a4c, 0x000001f0, 0x000001d0 },
+    { 0x00009a50, 0x00000030, 0x00000010 },
+    { 0x00009a54, 0x00000070, 0x00000050 },
+    { 0x00009a58, 0x00000191, 0x00000090 },
+    { 0x00009a5c, 0x000001d1, 0x00000151 },
+    { 0x00009a60, 0x00000011, 0x00000191 },
+    { 0x00009a64, 0x00000051, 0x000001d1 },
+    { 0x00009a68, 0x00000091, 0x00000011 },
+    { 0x00009a6c, 0x000001b8, 0x00000051 },
+    { 0x00009a70, 0x000001f8, 0x00000198 },
+    { 0x00009a74, 0x00000038, 0x000001d8 },
+    { 0x00009a78, 0x00000078, 0x00000018 },
+    { 0x00009a7c, 0x00000199, 0x00000058 },
+    { 0x00009a80, 0x000001d9, 0x00000098 },
+    { 0x00009a84, 0x00000019, 0x00000159 },
+    { 0x00009a88, 0x00000059, 0x00000199 },
+    { 0x00009a8c, 0x00000099, 0x000001d9 },
+    { 0x00009a90, 0x000000d9, 0x00000019 },
+    { 0x00009a94, 0x000000f9, 0x00000059 },
+    { 0x00009a98, 0x000000f9, 0x00000099 },
+    { 0x00009a9c, 0x000000f9, 0x000000d9 },
+    { 0x00009aa0, 0x000000f9, 0x000000f9 },
+    { 0x00009aa4, 0x000000f9, 0x000000f9 },
+    { 0x00009aa8, 0x000000f9, 0x000000f9 },
+    { 0x00009aac, 0x000000f9, 0x000000f9 },
+    { 0x00009ab0, 0x000000f9, 0x000000f9 },
+    { 0x00009ab4, 0x000000f9, 0x000000f9 },
+    { 0x00009ab8, 0x000000f9, 0x000000f9 },
+    { 0x00009abc, 0x000000f9, 0x000000f9 },
+    { 0x00009ac0, 0x000000f9, 0x000000f9 },
+    { 0x00009ac4, 0x000000f9, 0x000000f9 },
+    { 0x00009ac8, 0x000000f9, 0x000000f9 },
+    { 0x00009acc, 0x000000f9, 0x000000f9 },
+    { 0x00009ad0, 0x000000f9, 0x000000f9 },
+    { 0x00009ad4, 0x000000f9, 0x000000f9 },
+    { 0x00009ad8, 0x000000f9, 0x000000f9 },
+    { 0x00009adc, 0x000000f9, 0x000000f9 },
+    { 0x00009ae0, 0x000000f9, 0x000000f9 },
+    { 0x00009ae4, 0x000000f9, 0x000000f9 },
+    { 0x00009ae8, 0x000000f9, 0x000000f9 },
+    { 0x00009aec, 0x000000f9, 0x000000f9 },
+    { 0x00009af0, 0x000000f9, 0x000000f9 },
+    { 0x00009af4, 0x000000f9, 0x000000f9 },
+    { 0x00009af8, 0x000000f9, 0x000000f9 },
+    { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const uint32_t ar9160Bank1[][2] = {
+    { 0x000098b0, 0x02108421 },
+    { 0x000098ec, 0x00000008 },
+};
+
+static const uint32_t ar9160Bank2[][2] = {
+    { 0x000098b0, 0x0e73ff17 },
+    { 0x000098e0, 0x00000420 },
+};
+
+static const uint32_t ar9160Bank3[][3] = {
+    { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+static const uint32_t ar9160Bank6[][3] = {
+/*    Reg      A            G            */
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x004210a2, 0x004210a2 },
+    { 0x0000989c, 0x0014008f, 0x0014008f },
+    { 0x0000989c, 0x00c40003, 0x00c40003 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000f1, 0x000000f1 },
+    { 0x0000989c, 0x00002081, 0x00002081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const uint32_t ar9160Bank6TPC[][3] = {
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x00423022, 0x00423022 },
+    { 0x0000989c, 0x2014008f, 0x2014008f },
+    { 0x0000989c, 0x00c40002, 0x00c40002 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000e1, 0x000000e1 },
+    { 0x0000989c, 0x00007080, 0x00007080 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const uint32_t ar9160Bank7[][2] = {
+    { 0x0000989c, 0x00000500 },
+    { 0x0000989c, 0x00000800 },
+    { 0x000098cc, 0x0000000e },
+};
+
+/* Auto generated PCI Register Writes for SOWL1.0 ADDAC Shift Chain */
+static const uint32_t ar9160Addac[][2] = {
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000018 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000019 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000003 },
+    {0x0000989c,  0x00000008 },
+    {0x0000989c,  0x00000000 },
+    {0x000098cc,  0x00000000 },
+};
+
+/* Auto generated PCI Register Writes for SOWL1.1 ADDAC Shift Chain */
+static const uint32_t ar9160Addac_1_1[][2] = {
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000018 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000019 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x000098cc,  0x00000000 },
+};
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5210/ar9160_attach.c    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar9160_attach.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#include "ar5416/ar9160.ini"
+
+static const HAL_PERCAL_DATA ar9160_iq_cal = {         /* multi sample */
+       .calName = "IQ", .calType = IQ_MISMATCH_CAL,
+       .calNumSamples  = MAX_CAL_SAMPLES,
+       .calCountMax    = PER_MIN_LOG_COUNT,
+       .calCollect     = ar5416IQCalCollect,
+       .calPostProc    = ar5416IQCalibration
+};
+static const HAL_PERCAL_DATA ar9160_adc_gain_cal = {   /* multi sample */
+       .calName = "ADC Gain", .calType = ADC_GAIN_CAL,
+       .calNumSamples  = MAX_CAL_SAMPLES,
+       .calCountMax    = PER_MIN_LOG_COUNT,
+       .calCollect     = ar5416AdcGainCalCollect,
+       .calPostProc    = ar5416AdcGainCalibration
+};
+static const HAL_PERCAL_DATA ar9160_adc_dc_cal = {     /* multi sample */
+       .calName = "ADC DC", .calType = ADC_DC_CAL,
+       .calNumSamples  = MAX_CAL_SAMPLES,
+       .calCountMax    = PER_MIN_LOG_COUNT,
+       .calCollect     = ar5416AdcDcCalCollect,
+       .calPostProc    = ar5416AdcDcCalibration
+};
+static const HAL_PERCAL_DATA ar9160_adc_init_dc_cal = {
+       .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
+       .calNumSamples  = MIN_CAL_SAMPLES,
+       .calCountMax    = INIT_LOG_COUNT,
+       .calCollect     = ar5416AdcDcCalCollect,
+       .calPostProc    = ar5416AdcDcCalibration
+};
+
+struct ath_hal *ar9160Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status);
+static void ar9160Detach(struct ath_hal *);
+static HAL_BOOL ar9160FillCapabilityInfo(struct ath_hal *ah);
+
+static void
+ar9160AniSetup(struct ath_hal *ah)
+{
+       static const struct ar5212AniParams aniparams = {
+               .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
+               .totalSizeDesired       = { -55, -55, -55, -55, -62 },
+               .coarseHigh             = { -14, -14, -14, -14, -12 },
+               .coarseLow              = { -64, -64, -64, -64, -70 },
+               .firpwr                 = { -78, -78, -78, -78, -80 },
+               .maxSpurImmunityLevel   = 2,
+               .cycPwrThr1             = { 2, 4, 6 },
+               .maxFirstepLevel        = 2,    /* levels 0..2 */
+               .firstep                = { 0, 4, 8 },
+               .ofdmTrigHigh           = 500,
+               .ofdmTrigLow            = 200,
+               .cckTrigHigh            = 200,
+               .cckTrigLow             = 100,
+               .rssiThrHigh            = 40,
+               .rssiThrLow             = 7,
+               .period                 = 100,
+       };
+       /* NB: ANI is not enabled yet */
+       ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE);
+}
+
+/*
+ * Attach for an AR9160 part.
+ */
+struct ath_hal *
+ar9160Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+       struct ath_hal_5416 *ahp5416;
+       struct ath_hal_5212 *ahp;
+       struct ath_hal *ah;
+       uint32_t val;
+       HAL_STATUS ecode;
+       HAL_BOOL rfStatus;
+
+       HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
+           __func__, sc, (void*) st, (void*) sh);
+
+       /* NB: memory is returned zero'd */
+       ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416));
+       if (ahp5416 == AH_NULL) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                   "%s: cannot allocate memory for state block\n", __func__);
+               *status = HAL_ENOMEM;
+               return AH_NULL;
+       }
+       ar5416InitState(ahp5416, devid, sc, st, sh, status);
+       ahp = &ahp5416->ah_5212;
+       ah = &ahp->ah_priv.h;
+
+       /* XXX override with 9160 specific state */
+       /* override 5416 methods for our needs */
+       ah->ah_detach                   = ar9160Detach;
+
+       AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal;
+       AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal;
+       AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9160_adc_dc_cal;
+       AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9160_adc_init_dc_cal;
+       AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+
+       if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
+               /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
+                   __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
+                   __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+       /* Read Revisions from Chips before taking out of reset */
+       val = OS_REG_READ(ah, AR_SREV);
+       HALDEBUG(ah, HAL_DEBUG_ATTACH,
+           "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
+           __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
+           MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
+       /* NB: include chip type to differentiate from pre-Sowl versions */
+       AH_PRIVATE(ah)->ah_macVersion =
+           (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
+       AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
+       /* XXX extract pcie info */
+
+       /* setup common ini data; rf backends handle remainder */
+       HAL_INI_INIT(&ahp->ah_ini_modes, ar9160Modes, 6);
+       HAL_INI_INIT(&ahp->ah_ini_common, ar9160Common, 2);
+
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar9160BB_RfGain, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar9160Bank0, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar9160Bank1, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar9160Bank2, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar9160Bank3, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar9160Bank6, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar9160Bank7, 2);
+       if (AR_SREV_SOWL_11(ah))
+               HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac_1_1, 2);
+       else
+               HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac, 2);
+
+       if (!ar5416ChipReset(ah, AH_NULL)) {    /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
+
+       if (!ar5212ChipTest(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
+                   __func__);
+               ecode = HAL_ESELFTEST;
+               goto bad;
+       }
+
+       /*
+        * Set correct Baseband to analog shift
+        * setting to access analog chips.
+        */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       /* Read Radio Chip Rev Extract */
+       AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
+       switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
+        case AR_RAD2133_SREV_MAJOR:    /* Sowl: 2G/3x3 */
+       case AR_RAD5133_SREV_MAJOR:     /* Sowl: 2+5G/3x3 */
+               break;
+       default:
+               if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
+                       AH_PRIVATE(ah)->ah_analog5GhzRev =
+                               AR_RAD5133_SREV_MAJOR;
+                       break;
+               }
+#ifdef AH_DEBUG
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: 5G Radio Chip Rev 0x%02X is not supported by "
+                   "this driver\n", __func__,
+                   AH_PRIVATE(ah)->ah_analog5GhzRev);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+#endif
+       }
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: Attaching AR2133 radio\n",
+           __func__);
+       rfStatus = ar2133RfAttach(ah, &ecode);
+       if (!rfStatus) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
+                   __func__, ecode);
+               goto bad;
+       }
+
+       ecode = ath_hal_v14EepromAttach(ah);
+       if (ecode != HAL_OK)
+               goto bad;
+
+       /*
+        * Got everything we need now to setup the capabilities.
+        */
+       if (!ar9160FillCapabilityInfo(ah)) {
+               ecode = HAL_EEREAD;
+               goto bad;
+       }
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error getting mac address from EEPROM\n", __func__);
+               goto bad;
+        }
+       /* XXX How about the serial number ? */
+       /* Read Reg Domain */
+       AH_PRIVATE(ah)->ah_currentRD =
+           ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
+
+       /*
+        * ah_miscMode is populated by ar5416FillCapabilityInfo()
+        * starting from griffin. Set here to make sure that
+        * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
+        * placed into hardware.
+        */
+       if (ahp->ah_miscMode != 0)
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+
+       ar9160AniSetup(ah);                     /* Anti Noise Immunity */
+       ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
+
+       return ah;
+bad:
+       if (ahp)
+               ar9160Detach((struct ath_hal *) ahp);
+       if (status)
+               *status = ecode;
+       return AH_NULL;
+}
+
+void
+ar9160Detach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
+
+       HALASSERT(ah != AH_NULL);
+       HALASSERT(ah->ah_magic == AR5416_MAGIC);
+
+       ar5416Detach(ah);
+}
+
+/*
+ * Fill all software cached or static hardware state information.
+ * Return failure if capabilities are to come from EEPROM and
+ * cannot be read.
+ */
+static HAL_BOOL
+ar9160FillCapabilityInfo(struct ath_hal *ah)
+{
+       HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+
+       if (!ar5416FillCapabilityInfo(ah))
+               return AH_FALSE;
+       pCap->halCSTSupport = AH_TRUE;
+       pCap->halRifsRxSupport = AH_TRUE;
+       pCap->halRifsTxSupport = AH_TRUE;
+       pCap->halRtsAggrLimit = 64*1024;        /* 802.11n max */
+       pCap->halExtChanDfsSupport = AH_TRUE;
+       pCap->halAutoSleepSupport = AH_FALSE;   /* XXX? */
+       return AH_TRUE;
+}
+
+static const char*
+ar9160Probe(uint16_t vendorid, uint16_t devid)
+{
+       if (vendorid == ATHEROS_VENDOR_ID && devid == AR9160_DEVID_PCI)
+               return "Atheros 9160";
+       return AH_NULL;
+}
+AH_CHIP(AR9160, ar9160Probe, ar9160Attach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar2133.c   2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar2133.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#define N(a)    (sizeof(a)/sizeof(a[0]))
+
+struct ar2133State {
+       RF_HAL_FUNCS    base;           /* public state, must be first */
+       uint16_t        pcdacTable[1];
+
+       uint32_t        *Bank0Data;
+       uint32_t        *Bank1Data;
+       uint32_t        *Bank2Data;
+       uint32_t        *Bank3Data;
+       uint32_t        *Bank6Data;
+       uint32_t        *Bank7Data;
+
+       /* NB: Bank*Data storage follows */
+};
+#define        AR2133(ah)      ((struct ar2133State *) AH5212(ah)->ah_rfHal)
+
+#define        ar5416ModifyRfBuffer    ar5212ModifyRfBuffer    /*XXX*/
+
+extern  void ar5416ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
+       uint32_t numBits, uint32_t firstBit, uint32_t column);
+HAL_BOOL ar2133GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL
+       *chans, uint32_t nchans);
+
+static HAL_BOOL ar2133GetChannelMaxMinPower(struct ath_hal *, HAL_CHANNEL *,
+               int16_t *maxPow,int16_t *minPow);
+int16_t ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c);
+
+static void
+ar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+       int writes)
+{
+       (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain,
+               freqIndex, writes);
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ */
+static HAL_BOOL
+ar2133SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
+{
+       uint32_t channelSel  = 0;
+       uint32_t bModeSynth  = 0;
+       uint32_t aModeRefSel = 0;
+       uint32_t reg32       = 0;
+       uint16_t freq;
+       CHAN_CENTERS centers;
+
+       OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
+
+       ar5416GetChannelCenters(ah,  chan, &centers);
+       freq = centers.synth_center;
+
+       if (freq < 4800) {
+               uint32_t txctl;
+
+               if (((freq - 2192) % 5) == 0) {
+                       channelSel = ((freq - 672) * 2 - 3040)/10;
+                       bModeSynth = 0;
+               } else if (((freq - 2224) % 5) == 0) {
+                       channelSel = ((freq - 704) * 2 - 3040) / 10;
+                       bModeSynth = 1;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid channel %u MHz\n", __func__, freq);
+                       return AH_FALSE;
+               }
+
+               channelSel = (channelSel << 2) & 0xff;
+               channelSel = ath_hal_reverseBits(channelSel, 8);
+
+               txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+               if (freq == 2484) {
+                       /* Enable channel spreading for channel 14 */
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                               txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+               } else {
+                       OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+                       txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+               }
+       } else if ((freq % 20) == 0 && freq >= 5120) {
+               channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8);
+               if (AR_SREV_SOWL_10_OR_LATER(ah))
+                       aModeRefSel = ath_hal_reverseBits(3, 2);
+               else
+                       aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else if ((freq % 10) == 0) {
+               channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8);
+               if (AR_SREV_SOWL_10_OR_LATER(ah))
+                       aModeRefSel = ath_hal_reverseBits(2, 2);
+               else
+                       aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else if ((freq % 5) == 0) {
+               channelSel = ath_hal_reverseBits((freq - 4800) / 5, 8);
+               aModeRefSel = ath_hal_reverseBits(1, 2);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
+                   __func__, freq);
+               return AH_FALSE;
+       }
+
+       reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
+               (1 << 5) | 0x1;
+
+       OS_REG_WRITE(ah, AR_PHY(0x37), reg32);
+
+       AH_PRIVATE(ah)->ah_curchan = chan;
+       return AH_TRUE;
+
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar2133GetRfBank(struct ath_hal *ah, int bank)
+{
+       struct ar2133State *priv = AR2133(ah);
+
+       HALASSERT(priv != AH_NULL);
+       switch (bank) {
+       case 1: return priv->Bank1Data;
+       case 2: return priv->Bank2Data;
+       case 3: return priv->Bank3Data;
+       case 6: return priv->Bank6Data;
+       case 7: return priv->Bank7Data;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+           __func__, bank);
+       return AH_NULL;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ *
+ * REQUIRES: Access to the analog rf device
+ */
+static HAL_BOOL
+ar2133SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
+                uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+       struct ar2133State *priv = AR2133(ah);
+       int writes;
+
+       HALASSERT(priv);
+
+       /* Setup Bank 0 Write */
+       ath_hal_ini_bank_setup(priv->Bank0Data, &AH5416(ah)->ah_ini_bank0, 1);
+
+       /* Setup Bank 1 Write */
+       ath_hal_ini_bank_setup(priv->Bank1Data, &AH5416(ah)->ah_ini_bank1, 1);
+
+       /* Setup Bank 2 Write */
+       ath_hal_ini_bank_setup(priv->Bank2Data, &AH5416(ah)->ah_ini_bank2, 1);
+
+       /* Setup Bank 3 Write */
+       ath_hal_ini_bank_setup(priv->Bank3Data, &AH5416(ah)->ah_ini_bank3, modesIndex);
+
+       /* Setup Bank 6 Write */
+       ath_hal_ini_bank_setup(priv->Bank6Data, &AH5416(ah)->ah_ini_bank6, modesIndex);
+
+       /* Only the 5 or 2 GHz OB/DB need to be set for a mode */
+       if (IS_CHAN_2GHZ(chan)) {
+               ar5416ModifyRfBuffer(priv->Bank6Data,
+                   ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 3, 197, 0);
+               ar5416ModifyRfBuffer(priv->Bank6Data,
+                   ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL), 3, 194, 0);
+       } else {
+               ar5416ModifyRfBuffer(priv->Bank6Data,
+                   ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 3, 203, 0);
+               ar5416ModifyRfBuffer(priv->Bank6Data,
+                   ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL), 3, 200, 0);
+       }
+       /* Setup Bank 7 Setup */
+       ath_hal_ini_bank_setup(priv->Bank7Data, &AH5416(ah)->ah_ini_bank7, 1);
+
+       /* Write Analog registers */
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank0,
+           priv->Bank0Data, 0);
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank1,
+           priv->Bank1Data, writes);
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank2,
+           priv->Bank2Data, writes);
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank3,
+           priv->Bank3Data, writes);
+       writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6,
+           priv->Bank6Data, writes);
+       (void) ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank7,
+           priv->Bank7Data, writes);
+
+       return AH_TRUE;
+#undef  RF_BANK_SETUP
+}
+
+/*
+ * Read the transmit power levels from the structures taken from EEPROM
+ * Interpolate read transmit power values for this channel
+ * Organize the transmit power values into a table for writing into the hardware
+ */
+
+static HAL_BOOL
+ar2133SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax,
+       HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain)
+{
+       return AH_TRUE;
+}
+
+#if 0
+static int16_t
+ar2133GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data)
+{
+    int i, minIndex;
+    int16_t minGain,minPwr,minPcdac,retVal;
+
+    /* Assume NUM_POINTS_XPD0 > 0 */
+    minGain = data->pDataPerXPD[0].xpd_gain;
+    for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) {
+        if (data->pDataPerXPD[i].xpd_gain < minGain) {
+            minIndex = i;
+            minGain = data->pDataPerXPD[i].xpd_gain;
+        }
+    }
+    minPwr = data->pDataPerXPD[minIndex].pwr_t4[0];
+    minPcdac = data->pDataPerXPD[minIndex].pcdac[0];
+    for (i=1; i<NUM_POINTS_XPD0; i++) {
+        if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) {
+            minPwr = data->pDataPerXPD[minIndex].pwr_t4[i];
+            minPcdac = data->pDataPerXPD[minIndex].pcdac[i];
+        }
+    }
+    retVal = minPwr - (minPcdac*2);
+    return(retVal);
+}
+#endif
+
+static HAL_BOOL
+ar2133GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow,
+                int16_t *minPow)
+{
+#if 0
+    struct ath_hal_5212 *ahp = AH5212(ah);
+    int numChannels=0,i,last;
+    int totalD, totalF,totalMin;
+    EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL;
+    EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL;
+
+    *maxPow = 0;
+    if (IS_CHAN_A(chan)) {
+        powerArray = ahp->ah_modePowerArray5112;
+        data = powerArray[headerInfo11A].pDataPerChannel;
+        numChannels = powerArray[headerInfo11A].numChannels;
+    } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) {
+        /* XXX - is this correct? Should we also use the same power for turbo G? */
+        powerArray = ahp->ah_modePowerArray5112;
+        data = powerArray[headerInfo11G].pDataPerChannel;
+        numChannels = powerArray[headerInfo11G].numChannels;
+    } else if (IS_CHAN_B(chan)) {
+        powerArray = ahp->ah_modePowerArray5112;
+        data = powerArray[headerInfo11B].pDataPerChannel;
+        numChannels = powerArray[headerInfo11B].numChannels;
+    } else {
+        return (AH_TRUE);
+    }
+    /* Make sure the channel is in the range of the TP values
+     *  (freq piers)
+     */
+    if ((numChannels < 1) ||
+        (chan->channel < data[0].channelValue) ||
+        (chan->channel > data[numChannels-1].channelValue))
+        return(AH_FALSE);
+
+    /* Linearly interpolate the power value now */
+    for (last=0,i=0;
+         (i<numChannels) && (chan->channel > data[i].channelValue);
+         last=i++);
+    totalD = data[i].channelValue - data[last].channelValue;
+    if (totalD > 0) {
+        totalF = data[i].maxPower_t4 - data[last].maxPower_t4;
+        *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD);
+
+        totalMin = ar2133GetMinPower(ah,&data[i]) - ar2133GetMinPower(ah, &data[last]);
+        *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2133GetMinPower(ah, &data[last])*totalD)/totalD);
+        return (AH_TRUE);
+    } else {
+        if (chan->channel == data[i].channelValue) {
+            *maxPow = data[i].maxPower_t4;
+            *minPow = ar2133GetMinPower(ah, &data[i]);
+            return(AH_TRUE);
+        } else
+            return(AH_FALSE);
+    }
+#else
+    *maxPow = *minPow = 0;
+       return AH_FALSE;
+#endif
+}
+
+static void
+ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[])
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       int16_t nf;
+
+       switch (ahp->ah_rx_chainmask) {
+        case 0x7:
+               nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ctl] [chain 2] is %d\n", nf);
+               nfarray[4] = nf;
+
+               nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ext] [chain 2] is %d\n", nf);
+               nfarray[5] = nf;
+               /* fall thru... */
+        case 0x3:
+        case 0x5:
+               nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ctl] [chain 1] is %d\n", nf);
+               nfarray[2] = nf;
+
+
+               nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ext] [chain 1] is %d\n", nf);
+               nfarray[3] = nf;
+               /* fall thru... */
+        case 0x1:
+               nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ctl] [chain 0] is %d\n", nf);
+               nfarray[0] = nf;
+
+               nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
+               if (nf & 0x100)
+                       nf = 0 - ((nf ^ 0x1ff) + 1);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "NF calibrated [ext] [chain 0] is %d\n", nf);
+               nfarray[1] = nf;
+
+               break;
+       }
+}
+
+/*
+ * Adjust NF based on statistical values for 5GHz frequencies.
+ * Stubbed:Not used by Fowl
+ */
+int16_t
+ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
+{
+       return 0;
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar2133RfDetach(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(ahp->ah_rfHal != AH_NULL);
+       ath_hal_free(ahp->ah_rfHal);
+       ahp->ah_rfHal = AH_NULL;
+}
+
+/*
+ * Allocate memory for analog bank scratch buffers
+ * Scratch Buffer will be reinitialized every reset so no need to zero now
+ */
+HAL_BOOL
+ar2133RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar2133State *priv;
+       uint32_t *bankData;
+
+       HALASSERT(ahp->ah_rfHal == AH_NULL);
+       priv = ath_hal_malloc(sizeof(struct ar2133State)
+           + AH5416(ah)->ah_ini_bank0.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank1.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank2.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank3.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank6.rows * sizeof(uint32_t)
+           + AH5416(ah)->ah_ini_bank7.rows * sizeof(uint32_t)
+       );
+       if (priv == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot allocate private state\n", __func__);
+               *status = HAL_ENOMEM;           /* XXX */
+               return AH_FALSE;
+       }
+       priv->base.rfDetach             = ar2133RfDetach;
+       priv->base.writeRegs            = ar2133WriteRegs;
+       priv->base.getRfBank            = ar2133GetRfBank;
+       priv->base.setChannel           = ar2133SetChannel;
+       priv->base.setRfRegs            = ar2133SetRfRegs;
+       priv->base.setPowerTable        = ar2133SetPowerTable;
+       priv->base.getChannelMaxMinPower = ar2133GetChannelMaxMinPower;
+       priv->base.getNfAdjust          = ar2133GetNfAdjust;
+
+       bankData = (uint32_t *) &priv[1];
+       priv->Bank0Data = bankData, bankData += AH5416(ah)->ah_ini_bank0.rows;
+       priv->Bank1Data = bankData, bankData += AH5416(ah)->ah_ini_bank1.rows;
+       priv->Bank2Data = bankData, bankData += AH5416(ah)->ah_ini_bank2.rows;
+       priv->Bank3Data = bankData, bankData += AH5416(ah)->ah_ini_bank3.rows;
+       priv->Bank6Data = bankData, bankData += AH5416(ah)->ah_ini_bank6.rows;
+       priv->Bank7Data = bankData, bankData += AH5416(ah)->ah_ini_bank7.rows;
+
+       ahp->ah_pcdacTable = priv->pcdacTable;
+       ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+       ahp->ah_rfHal = &priv->base;
+       /*
+        * Set noise floor adjust method; we arrange a
+        * direct call instead of thunking.
+        */
+       AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust;
+       AH_PRIVATE(ah)->ah_getNoiseFloor = ar2133GetNoiseFloor;
+
+       return AH_TRUE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416.h   2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _ATH_AR5416_H_
+#define _ATH_AR5416_H_
+
+#include "ar5212/ar5212.h"
+#include "ar5416_cal.h"
+
+#define        AR5416_MAGIC    0x20065416
+
+enum {
+       HAL_RESET_POWER_ON,
+       HAL_RESET_WARM,
+       HAL_RESET_COLD,
+};
+
+typedef struct {
+       uint16_t        synth_center;
+       uint16_t        ctl_center;
+       uint16_t        ext_center;
+} CHAN_CENTERS;
+
+#define        AR5416_DEFAULT_RXCHAINMASK      7
+#define        AR5416_DEFAULT_TXCHAINMASK      1
+#define        AR5416_MAX_RATE_POWER           63
+#define        AR5416_KEYTABLE_SIZE            128
+
+#define        AR5416_CCA_MAX_GOOD_VALUE       -85
+#define        AR5416_CCA_MAX_HIGH_VALUE       -62
+#define        AR5416_CCA_MIN_BAD_VALUE        -140
+
+struct ath_hal_5416 {
+       struct ath_hal_5212 ah_5212;
+
+       /* NB: RF data setup at attach */
+       HAL_INI_ARRAY   ah_ini_bb_rfgain;
+       HAL_INI_ARRAY   ah_ini_bank0;
+       HAL_INI_ARRAY   ah_ini_bank1;
+       HAL_INI_ARRAY   ah_ini_bank2;
+       HAL_INI_ARRAY   ah_ini_bank3;
+       HAL_INI_ARRAY   ah_ini_bank6;
+       HAL_INI_ARRAY   ah_ini_bank7;
+       HAL_INI_ARRAY   ah_ini_addac;
+
+       u_int           ah_globaltxtimeout;     /* global tx timeout */
+       int             ah_hangs;               /* h/w hangs state */
+       uint8_t         ah_keytype[AR5416_KEYTABLE_SIZE];
+       /*
+        * Extension Channel Rx Clear State
+        */
+       uint32_t        ah_cycleCount;
+       uint32_t        ah_ctlBusy;
+       uint32_t        ah_extBusy;
+       uint32_t        ah_rx_chainmask;
+       uint32_t        ah_tx_chainmask;
+
+       struct ar5416PerCal ah_cal;             /* periodic calibration state */
+};
+#define        AH5416(_ah)     ((struct ath_hal_5416 *)(_ah))
+
+#define IS_5416_PCI(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCI)
+#define IS_5416_PCIE(ah) ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_VERSION_OWL_PCIE)
+#undef IS_PCIE
+#define IS_PCIE(ah) (IS_5416_PCIE(ah))
+
+extern HAL_BOOL ar2133RfAttach(struct ath_hal *, HAL_STATUS *);
+
+struct ath_hal;
+
+extern struct ath_hal * ar5416Attach(uint16_t devid, HAL_SOFTC sc,
+               HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status);
+extern void ar5416InitState(struct ath_hal_5416 *, uint16_t devid,
+               HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh,
+               HAL_STATUS *status);
+extern void ar5416Detach(struct ath_hal *ah);
+extern HAL_BOOL ar5416FillCapabilityInfo(struct ath_hal *ah);
+
+#define        IS_5GHZ_FAST_CLOCK_EN(_ah, _c) \
+       (IS_CHAN_5GHZ(_c) && ath_hal_eepromGetFlag(ah, AR_EEP_FSTCLK_5G))
+
+extern void ar5416AniAttach(struct ath_hal *, const struct ar5212AniParams *,
+               const struct ar5212AniParams *, HAL_BOOL ena);
+extern void ar5416AniDetach(struct ath_hal *);
+extern HAL_BOOL ar5416AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param);
+extern HAL_BOOL ar5416AniSetParams(struct ath_hal *,
+               const struct ar5212AniParams *, const struct ar5212AniParams *);
+extern void ar5416ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *);
+extern void ar5416AniPoll(struct ath_hal *, const HAL_NODE_STATS *,
+                            HAL_CHANNEL *);
+extern void ar5416AniReset(struct ath_hal *, HAL_CHANNEL_INTERNAL *,
+               HAL_OPMODE, int);
+
+extern void ar5416SetBeaconTimers(struct ath_hal *, const HAL_BEACON_TIMERS *);
+extern void ar5416BeaconInit(struct ath_hal *ah,
+               uint32_t next_beacon, uint32_t beacon_period);
+extern void ar5416ResetStaBeaconTimers(struct ath_hal *ah);
+extern void ar5416SetStaBeaconTimers(struct ath_hal *ah,
+               const HAL_BEACON_STATE *);
+
+extern HAL_BOOL ar5416EepromRead(struct ath_hal *, u_int off, uint16_t *data);
+extern HAL_BOOL ar5416EepromWrite(struct ath_hal *, u_int off, uint16_t data);
+
+extern HAL_BOOL ar5416IsInterruptPending(struct ath_hal *ah);
+extern HAL_BOOL ar5416GetPendingInterrupts(struct ath_hal *, HAL_INT *masked);
+extern HAL_INT ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints);
+
+extern HAL_BOOL ar5416GpioCfgOutput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5416GpioCfgInput(struct ath_hal *, uint32_t gpio);
+extern HAL_BOOL ar5416GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val);
+extern uint32_t ar5416GpioGet(struct ath_hal *ah, uint32_t gpio);
+extern void ar5416GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel);
+
+extern u_int ar5416GetWirelessModes(struct ath_hal *ah);
+extern void ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state);
+extern void ar5416ResetTsf(struct ath_hal *ah);
+extern HAL_BOOL ar5416SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
+extern HAL_BOOL ar5416SetDecompMask(struct ath_hal *, uint16_t, int);
+extern void ar5416SetCoverageClass(struct ath_hal *, uint8_t, int);
+extern uint32_t ar5416Get11nExtBusy(struct ath_hal *ah);
+extern void ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode);
+extern HAL_HT_RXCLEAR ar5416Get11nRxClear(struct ath_hal *ah);
+extern void ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear);
+extern HAL_STATUS ar5416GetCapability(struct ath_hal *ah,
+           HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result);
+extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request,
+           const void *args, uint32_t argsize,
+           void **result, uint32_t *resultsize);
+
+extern HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
+               int setChip);
+extern HAL_POWER_MODE ar5416GetPowerMode(struct ath_hal *ah);
+extern HAL_BOOL ar5416GetPowerStatus(struct ath_hal *ah);
+
+extern HAL_BOOL ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry);
+extern HAL_BOOL ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
+              const HAL_KEYVAL *k, const uint8_t *mac, int xorKey);
+
+extern void ar5416StartPcuReceive(struct ath_hal *ah);
+extern void ar5416StopPcuReceive(struct ath_hal *ah);
+extern HAL_BOOL ar5416SetupRxDesc(struct ath_hal *,
+               struct ath_desc *, uint32_t size, u_int flags);
+extern HAL_STATUS ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *,
+               uint32_t, struct ath_desc *, uint64_t,
+               struct ath_rx_status *);
+
+extern HAL_BOOL ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+               HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status);
+extern HAL_BOOL ar5416PhyDisable(struct ath_hal *ah);
+extern HAL_RFGAIN ar5416GetRfgain(struct ath_hal *ah);
+extern HAL_BOOL ar5416Disable(struct ath_hal *ah);
+extern HAL_BOOL ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *);
+extern HAL_BOOL ar5416SetResetReg(struct ath_hal *, uint32_t type);
+extern HAL_BOOL ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit);
+extern HAL_BOOL ar5416GetChipPowerLimits(struct ath_hal *ah,
+               HAL_CHANNEL *chans, uint32_t nchans);
+extern void ar5416GetChannelCenters(struct ath_hal *,
+               HAL_CHANNEL_INTERNAL *chan, CHAN_CENTERS *centers);
+
+extern HAL_BOOL ar5416StopTxDma(struct ath_hal *ah, u_int q);
+extern HAL_BOOL ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+               u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower,
+               u_int txRate0, u_int txTries0,
+               u_int keyIx, u_int antMode, u_int flags,
+               u_int rtsctsRate, u_int rtsctsDuration,
+               u_int compicvLen, u_int compivLen, u_int comp);
+extern HAL_BOOL ar5416SetupXTxDesc(struct ath_hal *, struct ath_desc *,
+               u_int txRate1, u_int txRetries1,
+               u_int txRate2, u_int txRetries2,
+               u_int txRate3, u_int txRetries3);
+extern HAL_BOOL ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+               u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+               const struct ath_desc *ds0);
+extern HAL_STATUS ar5416ProcTxDesc(struct ath_hal *ah,
+               struct ath_desc *, struct ath_tx_status *);
+
+extern const HAL_RATE_TABLE *ar5416GetRateTable(struct ath_hal *, u_int mode);
+#endif /* _ATH_AR5416_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416.ini 2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416.ini,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+/* Auto Generated PCI Register Writes.  Created: 09/20/06 */
+
+static const uint32_t ar5416Modes[][6] = {
+   /* Register    A           A-20/40     G-20/40     G           G-Turbo    */
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 },
+    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009844, 0x1372161e, 0x13721c1e, 0x13721c30, 0x137216a4, 0x13721c25 },
+    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x00009850, 0x6c28b4e0, 0x6c28b4e0, 0x6d68b0de, 0x6d68b0de, 0x6c28b0de },
+    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
+    { 0x0000985c, 0x313a5d5e, 0x313a5d5e, 0x313a605e, 0x313a605e, 0x313a5d5e },
+    { 0x00009860, 0x00049d10, 0x00049d10, 0x00049d20, 0x00049d20, 0x00049d10 },
+    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000370 },
+    { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a19, 0xd0058a13, 0xd0058a0b },
+    { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
+#ifdef TB243
+    { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 },
+#else
+    { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+    { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+    { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+#ifdef __LINUX_ARM_ARCH__
+    { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
+#else
+    { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
+#endif
+#endif
+    { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 },
+    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, 0x00000440 },
+    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
+    { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
+    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
+    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
+    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
+    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
+    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
+    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
+    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
+    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
+    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
+    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
+    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const uint32_t ar5416Common[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+#ifdef AR9100
+    { 0x00020010, 0x00000000 },
+#else
+    { 0x00007010, 0x00000000 },
+#endif
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0x00000000 },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c4, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x00008300, 0x00000000 },
+    { 0x00008304, 0x00000000 },
+    { 0x00008308, 0x00000000 },
+    { 0x0000830c, 0x00000000 },
+    { 0x00008310, 0x00000000 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008318, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00000000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xad848e19 },
+    { 0x00009810, 0x7d14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x00009840, 0x206a016e },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009854, 0x00000859 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x05100000 },
+    { 0x0000a920, 0x05100000 },
+    { 0x0000b920, 0x05100000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280b212 },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5d50e188 },
+    { 0x00009958, 0x00081fff },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x0000c968, 0x000003ce },
+    { 0x00009970, 0x190c0514 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x001fff00 },
+    { 0x000099ac, 0x000000c4 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000200 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x000000aa },
+    { 0x000099fc, 0x00001042 },
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b28, 0x0000000c },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b38, 0x00000012 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b64, 0x00000021 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b8c, 0x0000002d },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009b9c, 0x00000033 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+    { 0x0000a210, 0x40806333 },
+    { 0x0000a214, 0x00106c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x018830c6 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x00000bb5 },
+    { 0x0000a22c, 0x00000011 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000c26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x051701ce },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa1f },
+    { 0x0000d35c, 0x066c420f },
+    { 0x0000d360, 0x0f282207 },
+    { 0x0000d364, 0x17601685 },
+    { 0x0000d368, 0x1f801104 },
+    { 0x0000d36c, 0x37a00c03 },
+    { 0x0000d370, 0x3fc40883 },
+    { 0x0000d374, 0x57c00803 },
+    { 0x0000d378, 0x5fd80682 },
+    { 0x0000d37c, 0x7fe00482 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x08000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+};
+
+static const uint32_t ar5416Bank0[][2] = {
+    { 0x000098b0, 0x1e5795e5 },
+    { 0x000098e0, 0x02008020 },
+};
+
+static const uint32_t ar5416BB_RfGain[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000040, 0x00000040 },
+    { 0x00009a08, 0x00000080, 0x00000080 },
+    { 0x00009a0c, 0x000001a1, 0x00000141 },
+    { 0x00009a10, 0x000001e1, 0x00000181 },
+    { 0x00009a14, 0x00000021, 0x000001c1 },
+    { 0x00009a18, 0x00000061, 0x00000001 },
+    { 0x00009a1c, 0x00000168, 0x00000041 },
+    { 0x00009a20, 0x000001a8, 0x000001a8 },
+    { 0x00009a24, 0x000001e8, 0x000001e8 },
+    { 0x00009a28, 0x00000028, 0x00000028 },
+    { 0x00009a2c, 0x00000068, 0x00000068 },
+    { 0x00009a30, 0x00000189, 0x000000a8 },
+    { 0x00009a34, 0x000001c9, 0x00000169 },
+    { 0x00009a38, 0x00000009, 0x000001a9 },
+    { 0x00009a3c, 0x00000049, 0x000001e9 },
+    { 0x00009a40, 0x00000089, 0x00000029 },
+    { 0x00009a44, 0x00000170, 0x00000069 },
+    { 0x00009a48, 0x000001b0, 0x00000190 },
+    { 0x00009a4c, 0x000001f0, 0x000001d0 },
+    { 0x00009a50, 0x00000030, 0x00000010 },
+    { 0x00009a54, 0x00000070, 0x00000050 },
+    { 0x00009a58, 0x00000191, 0x00000090 },
+    { 0x00009a5c, 0x000001d1, 0x00000151 },
+    { 0x00009a60, 0x00000011, 0x00000191 },
+    { 0x00009a64, 0x00000051, 0x000001d1 },
+    { 0x00009a68, 0x00000091, 0x00000011 },
+    { 0x00009a6c, 0x000001b8, 0x00000051 },
+    { 0x00009a70, 0x000001f8, 0x00000198 },
+    { 0x00009a74, 0x00000038, 0x000001d8 },
+    { 0x00009a78, 0x00000078, 0x00000018 },
+    { 0x00009a7c, 0x00000199, 0x00000058 },
+    { 0x00009a80, 0x000001d9, 0x00000098 },
+    { 0x00009a84, 0x00000019, 0x00000159 },
+    { 0x00009a88, 0x00000059, 0x00000199 },
+    { 0x00009a8c, 0x00000099, 0x000001d9 },
+    { 0x00009a90, 0x000000d9, 0x00000019 },
+    { 0x00009a94, 0x000000f9, 0x00000059 },
+    { 0x00009a98, 0x000000f9, 0x00000099 },
+    { 0x00009a9c, 0x000000f9, 0x000000d9 },
+    { 0x00009aa0, 0x000000f9, 0x000000f9 },
+    { 0x00009aa4, 0x000000f9, 0x000000f9 },
+    { 0x00009aa8, 0x000000f9, 0x000000f9 },
+    { 0x00009aac, 0x000000f9, 0x000000f9 },
+    { 0x00009ab0, 0x000000f9, 0x000000f9 },
+    { 0x00009ab4, 0x000000f9, 0x000000f9 },
+    { 0x00009ab8, 0x000000f9, 0x000000f9 },
+    { 0x00009abc, 0x000000f9, 0x000000f9 },
+    { 0x00009ac0, 0x000000f9, 0x000000f9 },
+    { 0x00009ac4, 0x000000f9, 0x000000f9 },
+    { 0x00009ac8, 0x000000f9, 0x000000f9 },
+    { 0x00009acc, 0x000000f9, 0x000000f9 },
+    { 0x00009ad0, 0x000000f9, 0x000000f9 },
+    { 0x00009ad4, 0x000000f9, 0x000000f9 },
+    { 0x00009ad8, 0x000000f9, 0x000000f9 },
+    { 0x00009adc, 0x000000f9, 0x000000f9 },
+    { 0x00009ae0, 0x000000f9, 0x000000f9 },
+    { 0x00009ae4, 0x000000f9, 0x000000f9 },
+    { 0x00009ae8, 0x000000f9, 0x000000f9 },
+    { 0x00009aec, 0x000000f9, 0x000000f9 },
+    { 0x00009af0, 0x000000f9, 0x000000f9 },
+    { 0x00009af4, 0x000000f9, 0x000000f9 },
+    { 0x00009af8, 0x000000f9, 0x000000f9 },
+    { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const uint32_t ar5416Bank1[][2] = {
+    { 0x000098b0, 0x02108421 },
+    { 0x000098ec, 0x00000008 },
+};
+
+static const uint32_t ar5416Bank2[][2] = {
+    { 0x000098b0, 0x0e73ff17 },
+    { 0x000098e0, 0x00000420 },
+};
+
+static const uint32_t ar5416Bank3[][3] = {
+    { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+#ifdef USE_NONTPC_BANK
+static const uint32_t ar5416Bank6[][3] = {
+/*    Reg      A            G            */
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x004210a2, 0x004210a2 },
+    { 0x0000989c, 0x0014008f, 0x0014008f },
+    { 0x0000989c, 0x00c40003, 0x00c40003 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000f1, 0x000000f1 },
+    { 0x0000989c, 0x00002081, 0x00002081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+#else
+/* TPC bank */
+static const uint32_t ar5416Bank6[][3] = {
+/*    Reg      A            G            */
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x00421022, 0x00421022 },
+    { 0x0000989c, 0x001400df, 0x001400df },
+    { 0x0000989c, 0x00c40002, 0x00c40002 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000e1, 0x000000e1 },
+    { 0x0000989c, 0x00002081, 0x00002081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+#endif
+
+static const uint32_t ar5416Bank7[][2] = {
+    { 0x0000989c, 0x00000500 },
+    { 0x0000989c, 0x00000800 },
+    { 0x000098cc, 0x0000000e },
+};
+
+static const uint32_t ar5416Addac[][2] = {
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000003 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x0000000c },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000030 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000060 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000058 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x0989c,  0x00000000 },
+    {0x098c4,  0x00000000 },
+};
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_ani.c       2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,886 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_ani.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+/*
+ * XXX this is virtually the same code as for 5212; we reuse
+ * storage in the 5212 state block; need to refactor.
+ */
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/*
+ * Anti noise immunity support.  We track phy errors and react
+ * to excessive errors by adjusting the noise immunity parameters.
+ */
+
+#define HAL_EP_RND(x, mul) \
+       ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+#define        BEACON_RSSI(ahp) \
+       HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \
+               HAL_RSSI_EP_MULTIPLIER)
+
+/*
+ * ANI processing tunes radio parameters according to PHY errors
+ * and related information.  This is done for for noise and spur
+ * immunity in all operating modes if the device indicates it's
+ * capable at attach time.  In addition, when there is a reference
+ * rssi value (e.g. beacon frames from an ap in station mode)
+ * further tuning is done.
+ *
+ * ANI_ENA indicates whether any ANI processing should be done;
+ * this is specified at attach time.
+ *
+ * ANI_ENA_RSSI indicates whether rssi-based processing should
+ * done, this is enabled based on operating mode and is meaningful
+ * only if ANI_ENA is true.
+ *
+ * ANI parameters are typically controlled only by the hal.  The
+ * AniControl interface however permits manual tuning through the
+ * diagnostic api.
+ */
+#define ANI_ENA(ah) \
+       (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA)
+#define ANI_ENA_RSSI(ah) \
+       (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA)
+
+#define        ah_mibStats     ah_stats.ast_mibstats
+
+static void
+enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: "
+           "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n",
+           __func__, params->ofdmPhyErrBase, params->cckPhyErrBase);
+
+       OS_REG_WRITE(ah, AR_FILTOFDM, 0);
+       OS_REG_WRITE(ah, AR_FILTCCK, 0);
+
+       OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/
+       ar5212EnableMibCounters(ah);                    /* enable everything */
+}
+
+static void
+disableAniMIBCounters(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n");
+
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */
+       ar5212DisableMibCounters(ah);                   /* disable everything */
+
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, 0);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, 0);
+}
+
+/*
+ * This routine returns the index into the aniState array that
+ * corresponds to the channel in *chan.  If no match is found and the
+ * array is still not fully utilized, a new entry is created for the
+ * channel.  We assume the attach function has already initialized the
+ * ah_ani values and only the channel field needs to be set.
+ */
+static int
+ar5416GetAniChannelIndex(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+#define N(a)     (sizeof(a) / sizeof(a[0]))
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       int i;
+
+       for (i = 0; i < N(ahp->ah_ani); i++) {
+               struct ar5212AniState *asp = &ahp->ah_ani[i];
+               if (asp->c.channel == chan->channel)
+                       return i;
+               if (asp->c.channel == 0) {
+                       asp->c.channel = chan->channel;
+                       asp->c.channelFlags = chan->channelFlags;
+                       asp->c.privFlags = chan->privFlags;
+                       asp->isSetup = AH_FALSE;
+                       if (IS_CHAN_2GHZ(chan))
+                               asp->params = &ahp->ah_aniParams24;
+                       else
+                               asp->params = &ahp->ah_aniParams5;
+                       return i;
+               }
+       }
+       /* XXX statistic */
+       HALDEBUG(ah, HAL_DEBUG_ANY,
+           "No more channel states left. Using channel 0\n");
+       return 0;               /* XXX gotta return something valid */
+#undef N
+}
+
+static void
+setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params)
+{
+       if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "OFDM Trigger %d is too high for hw counters, using max\n",
+                   params->ofdmTrigHigh);
+               params->ofdmPhyErrBase = 0;
+       } else
+               params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh;
+       if (params->cckTrigHigh >= AR_PHY_COUNTMAX) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "CCK Trigger %d is too high for hw counters, using max\n",
+                   params->cckTrigHigh);
+               params->cckPhyErrBase = 0;
+       } else
+               params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh;
+}
+
+/*
+ * Setup ANI handling.  Sets all thresholds and reset the
+ * channel statistics.  Note that ar5416AniReset should be
+ * called by ar5416Reset before anything else happens and
+ * that's where we force initial settings.
+ */
+void
+ar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24,
+       const struct ar5212AniParams *params5, HAL_BOOL enable)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       if (params24 != AH_NULL) {
+               OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));
+               setPhyErrBase(ah, &ahp->ah_aniParams24);
+       }
+       if (params5 != AH_NULL) {
+               OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));
+               setPhyErrBase(ah, &ahp->ah_aniParams5);
+       }
+
+       OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));
+       /* Enable MIB Counters */
+       enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/);
+
+       if (enable) {           /* Enable ani now */
+               HALASSERT(params24 != AH_NULL && params5 != AH_NULL);
+               ahp->ah_procPhyErr |= HAL_ANI_ENA;
+       } else {
+               ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
+       }
+}
+
+/*
+ * Cleanup any ANI state setup.
+ */
+void
+ar5416AniDetach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n");
+       disableAniMIBCounters(ah);
+}
+
+/*
+ * Control Adaptive Noise Immunity Parameters
+ */
+HAL_BOOL
+ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
+{
+       typedef int TABLE[];
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState = ahp->ah_curani;
+       const struct ar5212AniParams *params = aniState->params;
+
+       OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);
+
+       switch (cmd) {
+       case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxNoiseImmunityLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxNoiseImmunityLevel);
+                       return AH_FALSE;
+               }
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+                   AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+                   AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+                   AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                   AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]);
+
+               if (level > aniState->noiseImmunityLevel)
+                       ahp->ah_stats.ast_ani_niup++;
+               else if (level < aniState->noiseImmunityLevel)
+                       ahp->ah_stats.ast_ani_nidown++;
+               aniState->noiseImmunityLevel = level;
+               break;
+       }
+       case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
+               static const TABLE m1ThreshLow   = { 127,   50 };
+               static const TABLE m2ThreshLow   = { 127,   40 };
+               static const TABLE m1Thresh      = { 127, 0x4d };
+               static const TABLE m2Thresh      = { 127, 0x40 };
+               static const TABLE m2CountThr    = {  31,   16 };
+               static const TABLE m2CountThrLow = {  63,   48 };
+               u_int on = param ? 1 : 0;
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                       AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                       AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]);
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                       AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                       AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                       AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]);
+               OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                       AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]);
+
+               if (on) {
+                       OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+                               AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               } else {
+                       OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+                               AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               }
+               if (on)
+                       ahp->ah_stats.ast_ani_ofdmon++;
+               else
+                       ahp->ah_stats.ast_ani_ofdmoff++;
+               aniState->ofdmWeakSigDetectOff = !on;
+               break;
+       }
+       case HAL_ANI_CCK_WEAK_SIGNAL_THR: {
+               static const TABLE weakSigThrCck = { 8, 6 };
+               u_int high = param ? 1 : 0;
+
+               OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+                   AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]);
+               if (high)
+                       ahp->ah_stats.ast_ani_cckhigh++;
+               else
+                       ahp->ah_stats.ast_ani_ccklow++;
+               aniState->cckWeakSigThreshold = high;
+               break;
+       }
+       case HAL_ANI_FIRSTEP_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxFirstepLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxFirstepLevel);
+                       return AH_FALSE;
+               }
+               OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                   AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]);
+               if (level > aniState->firstepLevel)
+                       ahp->ah_stats.ast_ani_stepup++;
+               else if (level < aniState->firstepLevel)
+                       ahp->ah_stats.ast_ani_stepdown++;
+               aniState->firstepLevel = level;
+               break;
+       }
+       case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
+               u_int level = param;
+
+               if (level >= params->maxSpurImmunityLevel) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: level out of range (%u > %u)\n",
+                           __func__, level, params->maxSpurImmunityLevel);
+                       return AH_FALSE;
+               }
+               OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+                   AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]);
+               if (level > aniState->spurImmunityLevel)
+                       ahp->ah_stats.ast_ani_spurup++;
+               else if (level < aniState->spurImmunityLevel)
+                       ahp->ah_stats.ast_ani_spurdown++;
+               aniState->spurImmunityLevel = level;
+               break;
+       }
+       case HAL_ANI_PRESENT:
+               break;
+       case HAL_ANI_MODE:
+               if (param == 0) {
+                       ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
+                       /* Turn off HW counters if we have them */
+                       ar5416AniDetach(ah);
+                       ar5212SetRxFilter(ah,
+                               ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
+               } else {                        /* normal/auto mode */
+                       /* don't mess with state if already enabled */
+                       if (ahp->ah_procPhyErr & HAL_ANI_ENA)
+                               break;
+                       ar5212SetRxFilter(ah,
+                               ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
+                       /* Enable MIB Counters */
+                       enableAniMIBCounters(ah, ahp->ah_curani != AH_NULL ?
+                           ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/);
+                       ahp->ah_procPhyErr |= HAL_ANI_ENA;
+               }
+               break;
+#ifdef AH_PRIVATE_DIAG
+       case HAL_ANI_PHYERR_RESET:
+               ahp->ah_stats.ast_ani_ofdmerrs = 0;
+               ahp->ah_stats.ast_ani_cckerrs = 0;
+               break;
+#endif /* AH_PRIVATE_DIAG */
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n",
+                   __func__, cmd);
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+static void
+ar5416AniOfdmErrTrigger(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(chan != AH_NULL);
+
+       if (!ANI_ENA(ah))
+               return;
+
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       /* First, raise noise immunity level, up to max */
+       if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel + 1);
+               return;
+       }
+       /* then, raise spur immunity level, up to max */
+       if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) {
+               ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel + 1);
+               return;
+       }
+
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi > params->rssiThrHigh) {
+                       /*
+                        * Beacon rssi is high, can turn off ofdm
+                        * weak sig detect.
+                        */
+                       if (!aniState->ofdmWeakSigDetectOff) {
+                               ar5416AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_FALSE);
+                               ar5416AniControl(ah,
+                                   HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
+                               return;
+                       }
+                       /*
+                        * If weak sig detect is already off, as last resort,
+                        * raise firstep level
+                        */
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel + 1);
+                               return;
+                       }
+               } else if (rssi > params->rssiThrLow) {
+                       /*
+                        * Beacon rssi in mid range, need ofdm weak signal
+                        * detect, but we can raise firststepLevel.
+                        */
+                       if (aniState->ofdmWeakSigDetectOff)
+                               ar5416AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_TRUE);
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel)
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                    aniState->firstepLevel + 1);
+                       return;
+               } else {
+                       /*
+                        * Beacon rssi is low, if in 11b/g mode, turn off ofdm
+                        * weak signal detection and zero firstepLevel to
+                        * maximize CCK sensitivity
+                        */
+                       /* XXX can optimize */
+                       if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) {
+                               if (!aniState->ofdmWeakSigDetectOff)
+                                       ar5416AniControl(ah,
+                                           HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                           AH_FALSE);
+                               if (aniState->firstepLevel > 0)
+                                       ar5416AniControl(ah,
+                                            HAL_ANI_FIRSTEP_LEVEL, 0);
+                               return;
+                       }
+               }
+       }
+}
+
+static void
+ar5416AniCckErrTrigger(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(chan != AH_NULL);
+
+       if (!ANI_ENA(ah))
+               return;
+
+       /* first, raise noise immunity level, up to max */
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel + 1);
+               return;
+       }
+
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi >  params->rssiThrLow) {
+                       /*
+                        * Beacon signal in mid and high range,
+                        * raise firstep level.
+                        */
+                       if (aniState->firstepLevel+1 < params->maxFirstepLevel)
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel + 1);
+               } else {
+                       /*
+                        * Beacon rssi is low, zero firstep level to maximize
+                        * CCK sensitivity in 11b/g mode.
+                        */
+                       /* XXX can optimize */
+                       if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) {
+                               if (aniState->firstepLevel > 0)
+                                       ar5416AniControl(ah,
+                                           HAL_ANI_FIRSTEP_LEVEL, 0);
+                       }
+               }
+       }
+}
+
+static void
+ar5416AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const struct ar5212AniParams *params = aniState->params;
+
+       aniState->listenTime = 0;
+       /*
+        * NB: these are written on reset based on the
+        *     ini so we must re-write them!
+        */
+       HALDEBUG(ah, HAL_DEBUG_ANI,
+           "%s: Writing ofdmbase=%u   cckbase=%u\n", __func__,
+           params->ofdmPhyErrBase, params->cckPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHY_ERR_1, params->ofdmPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHY_ERR_2, params->cckPhyErrBase);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+       OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_CCK_TIMING);
+
+       /* Clear the mib counters and save them in the stats */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+       aniState->ofdmPhyErrCount = 0;
+       aniState->cckPhyErrCount = 0;
+}
+
+/*
+ * Restore/reset the ANI parameters and reset the statistics.
+ * This routine must be called for every channel change.
+ *
+ * NOTE: This is where ah_curani is set; other ani code assumes
+ *       it is setup to reflect the current channel.
+ */
+void
+ar5416AniReset(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
+       HAL_OPMODE opmode, int restore)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       uint32_t rxfilter;
+       int index;
+
+       index = ar5416GetAniChannelIndex(ah, chan);
+       aniState = &ahp->ah_ani[index];
+       ahp->ah_curani = aniState;
+#if 0
+       ath_hal_printf(ah,"%s: chan %u/0x%x restore %d setup %d opmode %u\n",
+           __func__, chan->channel, chan->channelFlags, restore,
+           aniState->isSetup, opmode);
+#else
+       HALDEBUG(ah, HAL_DEBUG_ANI,
+           "%s: chan %u/0x%x restore %d setup %d opmode %u\n",
+           __func__, chan->channel, chan->channelFlags, restore,
+           aniState->isSetup, opmode);
+#endif
+       OS_MARK(ah, AH_MARK_ANI_RESET, opmode);
+
+       /*
+        * Turn off PHY error frame delivery while we futz with settings.
+        */
+       rxfilter = ar5212GetRxFilter(ah);
+       ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
+       /*
+        * Automatic processing is done only in station mode right now.
+        */
+       if (opmode == HAL_M_STA)
+               ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA;
+       else
+               ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA;
+       /*
+        * Set all ani parameters.  We either set them to initial
+        * values or restore the previous ones for the channel.
+        * XXX if ANI follows hardware, we don't care what mode we're
+        * XXX in, we should keep the ani parameters
+        */
+       if (restore && aniState->isSetup) {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel);
+               ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel);
+               ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                !aniState->ofdmWeakSigDetectOff);
+               ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
+                                aniState->cckWeakSigThreshold);
+               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                aniState->firstepLevel);
+       } else {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
+               ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
+               ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                       AH_TRUE);
+               ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);
+               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
+               aniState->isSetup = AH_TRUE;
+       }
+       ar5416AniRestart(ah, aniState);
+
+       /* restore RX filter mask */
+       ar5212SetRxFilter(ah, rxfilter);
+}
+
+/*
+ * Process a MIB interrupt.  We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
+void
+ar5416ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t phyCnt1, phyCnt2;
+
+       HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x "
+           "filtofdm 0x%x filtcck 0x%x\n",
+           __func__, OS_REG_READ(ah, AR_MIBC),
+           OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2),
+           OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK));
+
+       /*
+        * First order of business is to clear whatever caused
+        * the interrupt so we don't keep getting interrupted.
+        * We have the usual mib counters that are reset-on-read
+        * and the additional counters that appeared starting in
+        * Hainan.  We collect the mib counters and explicitly
+        * zero additional counters we are not using.  Anything
+        * else is reset only if it caused the interrupt.
+        */
+       /* NB: these are not reset-on-read */
+       phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);
+       phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);
+       /* not used, always reset them in case they are the cause */
+       OS_REG_WRITE(ah, AR_FILTOFDM, 0);
+       OS_REG_WRITE(ah, AR_FILTCCK, 0);
+       if ((OS_REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING) == 0)
+               OS_REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+
+       /* Clear the mib counters and save them in the stats */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+       ahp->ah_stats.ast_nodestats = *stats;
+
+       /*
+        * Check for an ani stat hitting the trigger threshold.
+        * When this happens we get a MIB interrupt and the top
+        * 2 bits of the counter register will be 0b11, hence
+        * the mask check of phyCnt?.
+        */
+       if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
+           ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+               struct ar5212AniState *aniState = ahp->ah_curani;
+               const struct ar5212AniParams *params = aniState->params;
+               uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+               ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
+               ahp->ah_stats.ast_ani_ofdmerrs +=
+                       ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+               aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+               cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
+               ahp->ah_stats.ast_ani_cckerrs +=
+                       cckPhyErrCnt - aniState->cckPhyErrCount;
+               aniState->cckPhyErrCount = cckPhyErrCnt;
+
+               /*
+                * NB: figure out which counter triggered.  If both
+                * trigger we'll only deal with one as the processing
+                * clobbers the error counter so the trigger threshold
+                * check will never be true.
+                */
+               if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh)
+                       ar5416AniOfdmErrTrigger(ah);
+               if (aniState->cckPhyErrCount > params->cckTrigHigh)
+                       ar5416AniCckErrTrigger(ah);
+               /* NB: always restart to insure the h/w counters are reset */
+               ar5416AniRestart(ah, aniState);
+       }
+}
+
+static void
+ar5416AniLowerImmunity(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       const struct ar5212AniParams *params;
+
+       HALASSERT(ANI_ENA(ah));
+
+       aniState = ahp->ah_curani;
+       params = aniState->params;
+       if (ANI_ENA_RSSI(ah)) {
+               int32_t rssi = BEACON_RSSI(ahp);
+               if (rssi > params->rssiThrHigh) {
+                       /*
+                        * Beacon signal is high, leave ofdm weak signal
+                        * detection off or it may oscillate.  Let it fall
+                        * through.
+                        */
+               } else if (rssi > params->rssiThrLow) {
+                       /*
+                        * Beacon rssi in mid range, turn on ofdm weak signal
+                        * detection or lower firstep level.
+                        */
+                       if (aniState->ofdmWeakSigDetectOff) {
+                               ar5416AniControl(ah,
+                                   HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+                                   AH_TRUE);
+                               return;
+                       }
+                       if (aniState->firstepLevel > 0) {
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel - 1);
+                               return;
+                       }
+               } else {
+                       /*
+                        * Beacon rssi is low, reduce firstep level.
+                        */
+                       if (aniState->firstepLevel > 0) {
+                               ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
+                                                aniState->firstepLevel - 1);
+                               return;
+                       }
+               }
+       }
+       /* then lower spur immunity level, down to zero */
+       if (aniState->spurImmunityLevel > 0) {
+               ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+                                aniState->spurImmunityLevel - 1);
+               return;
+       }
+       /*
+        * if all else fails, lower noise immunity level down to a min value
+        * zero for now
+        */
+       if (aniState->noiseImmunityLevel > 0) {
+               ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
+                                aniState->noiseImmunityLevel - 1);
+               return;
+       }
+}
+
+#define CLOCK_RATE 44000       /* XXX use mac_usec or similar */
+/* convert HW counter values to ms using 11g clock rate, goo9d enough
+   for 11a and Turbo */
+
+/*
+ * Return an approximation of the time spent ``listening'' by
+ * deducting the cycles spent tx'ing and rx'ing from the total
+ * cycle count since our last call.  A return value <0 indicates
+ * an invalid/inconsistent time.
+ */
+static int32_t
+ar5416AniGetListenTime(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState;
+       uint32_t txFrameCount, rxFrameCount, cycleCount;
+       int32_t listenTime;
+
+       txFrameCount = OS_REG_READ(ah, AR_TFCNT);
+       rxFrameCount = OS_REG_READ(ah, AR_RFCNT);
+       cycleCount = OS_REG_READ(ah, AR_CCCNT);
+
+       aniState = ahp->ah_curani;
+       if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
+               /*
+                * Cycle counter wrap (or initial call); it's not possible
+                * to accurately calculate a value because the registers
+                * right shift rather than wrap--so punt and return 0.
+                */
+               listenTime = 0;
+               ahp->ah_stats.ast_ani_lzero++;
+       } else {
+               int32_t ccdelta = cycleCount - aniState->cycleCount;
+               int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
+               int32_t tfdelta = txFrameCount - aniState->txFrameCount;
+               listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
+       }
+       aniState->cycleCount = cycleCount;
+       aniState->txFrameCount = txFrameCount;
+       aniState->rxFrameCount = rxFrameCount;
+       return listenTime;
+}
+
+/*
+ * Update ani stats in preparation for listen time processing.
+ */
+static void
+updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       const struct ar5212AniParams *params = aniState->params;
+       uint32_t phyCnt1, phyCnt2;
+       int32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+       /* Clear the mib counters and save them in the stats */
+       ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
+
+       /* NB: these are not reset-on-read */
+       phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);
+       phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);
+
+       /* NB: these are spec'd to never roll-over */
+       ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
+       if (ofdmPhyErrCnt < 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n",
+                   ofdmPhyErrCnt, phyCnt1);
+               ofdmPhyErrCnt = AR_PHY_COUNTMAX;
+       }
+       ahp->ah_stats.ast_ani_ofdmerrs +=
+            ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+       aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+       cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
+       if (cckPhyErrCnt < 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n",
+                   cckPhyErrCnt, phyCnt2);
+               cckPhyErrCnt = AR_PHY_COUNTMAX;
+       }
+       ahp->ah_stats.ast_ani_cckerrs +=
+               cckPhyErrCnt - aniState->cckPhyErrCount;
+       aniState->cckPhyErrCount = cckPhyErrCnt;
+}
+
+/*
+ * Do periodic processing.  This routine is called from the
+ * driver's rx interrupt handler after processing frames.
+ */
+void
+ar5416AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
+               HAL_CHANNEL *chan)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       struct ar5212AniState *aniState = ahp->ah_curani;
+       const struct ar5212AniParams *params;
+       int32_t listenTime;
+
+       ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi;
+
+       /* XXX can aniState be null? */
+       if (aniState == AH_NULL)
+               return;
+       if (!ANI_ENA(ah))
+               return;
+
+       listenTime = ar5416AniGetListenTime(ah);
+       if (listenTime < 0) {
+               ahp->ah_stats.ast_ani_lneg++;
+               /* restart ANI period if listenTime is invalid */
+               ar5416AniRestart(ah, aniState);
+       }
+       /* XXX beware of overflow? */
+       aniState->listenTime += listenTime;
+
+       OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime);
+
+       params = aniState->params;
+       if (aniState->listenTime > 5*params->period) {
+               /*
+                * Check to see if need to lower immunity if
+                * 5 aniPeriods have passed
+                */
+               updateMIBStats(ah, aniState);
+               if (aniState->ofdmPhyErrCount <= aniState->listenTime *
+                   params->ofdmTrigLow/1000 &&
+                   aniState->cckPhyErrCount <= aniState->listenTime *
+                   params->cckTrigLow/1000)
+                       ar5416AniLowerImmunity(ah);
+               ar5416AniRestart(ah, aniState);
+       } else if (aniState->listenTime > params->period) {
+               updateMIBStats(ah, aniState);
+               /* check to see if need to raise immunity */
+               if (aniState->ofdmPhyErrCount > aniState->listenTime *
+                   params->ofdmTrigHigh / 1000) {
+                       ar5416AniOfdmErrTrigger(ah);
+                       ar5416AniRestart(ah, aniState);
+               } else if (aniState->cckPhyErrCount > aniState->listenTime *
+                          params->cckTrigHigh / 1000) {
+                       ar5416AniCckErrTrigger(ah);
+                       ar5416AniRestart(ah, aniState);
+               }
+       }
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_attach.c    2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_attach.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#include "ar5416/ar5416.ini"
+
+static void
+ar5416AniSetup(struct ath_hal *ah)
+{
+       static const struct ar5212AniParams aniparams = {
+               .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
+               .totalSizeDesired       = { -55, -55, -55, -55, -62 },
+               .coarseHigh             = { -14, -14, -14, -14, -12 },
+               .coarseLow              = { -64, -64, -64, -64, -70 },
+               .firpwr                 = { -78, -78, -78, -78, -80 },
+               .maxSpurImmunityLevel   = 2,
+               .cycPwrThr1             = { 2, 4, 6 },
+               .maxFirstepLevel        = 2,    /* levels 0..2 */
+               .firstep                = { 0, 4, 8 },
+               .ofdmTrigHigh           = 500,
+               .ofdmTrigLow            = 200,
+               .cckTrigHigh            = 200,
+               .cckTrigLow             = 100,
+               .rssiThrHigh            = 40,
+               .rssiThrLow             = 7,
+               .period                 = 100,
+       };
+       /* NB: ANI is not enabled yet */
+       ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE);
+}
+
+/*
+ * Attach for an AR5416 part.
+ */
+void
+ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+       struct ath_hal_5212 *ahp;
+       struct ath_hal *ah;
+
+       ahp = &ahp5416->ah_5212;
+       ar5212InitState(ahp, devid, sc, st, sh, status);
+       ah = &ahp->ah_priv.h;
+
+       /* override 5212 methods for our needs */
+       ah->ah_magic                    = AR5416_MAGIC;
+       ah->ah_getRateTable             = ar5416GetRateTable;
+       ah->ah_detach                   = ar5416Detach;
+
+       /* Reset functions */
+       ah->ah_reset                    = ar5416Reset;
+       ah->ah_phyDisable               = ar5416PhyDisable;
+       ah->ah_disable                  = ar5416Disable;
+       ah->ah_perCalibration           = ar5416PerCalibration;
+       ah->ah_perCalibrationN          = ar5416PerCalibrationN,
+       ah->ah_resetCalValid            = ar5416ResetCalValid,
+       ah->ah_setTxPowerLimit          = ar5416SetTxPowerLimit;
+
+       /* Transmit functions */
+       ah->ah_stopTxDma                = ar5416StopTxDma;
+       ah->ah_setupTxDesc              = ar5416SetupTxDesc;
+       ah->ah_setupXTxDesc             = ar5416SetupXTxDesc;
+       ah->ah_fillTxDesc               = ar5416FillTxDesc;
+       ah->ah_procTxDesc               = ar5416ProcTxDesc;
+
+       /* Receive Functions */
+       ah->ah_startPcuReceive          = ar5416StartPcuReceive;
+       ah->ah_stopPcuReceive           = ar5416StopPcuReceive;
+       ah->ah_setupRxDesc              = ar5416SetupRxDesc;
+       ah->ah_procRxDesc               = ar5416ProcRxDesc;
+       ah->ah_rxMonitor                = ar5416AniPoll,
+       ah->ah_procMibEvent             = ar5416ProcessMibIntr,
+
+       /* Misc Functions */
+       ah->ah_getDiagState             = ar5416GetDiagState;
+       ah->ah_setLedState              = ar5416SetLedState;
+       ah->ah_gpioCfgOutput            = ar5416GpioCfgOutput;
+       ah->ah_gpioCfgInput             = ar5416GpioCfgInput;
+       ah->ah_gpioGet                  = ar5416GpioGet;
+       ah->ah_gpioSet                  = ar5416GpioSet;
+       ah->ah_gpioSetIntr              = ar5416GpioSetIntr;
+       ah->ah_resetTsf                 = ar5416ResetTsf;
+       ah->ah_getRfGain                = ar5416GetRfgain;
+       ah->ah_setAntennaSwitch         = ar5416SetAntennaSwitch;
+       ah->ah_setDecompMask            = ar5416SetDecompMask;
+       ah->ah_setCoverageClass         = ar5416SetCoverageClass;
+
+       ah->ah_resetKeyCacheEntry       = ar5416ResetKeyCacheEntry;
+       ah->ah_setKeyCacheEntry         = ar5416SetKeyCacheEntry;
+
+       /* Power Management Functions */
+       ah->ah_setPowerMode             = ar5416SetPowerMode;
+
+       /* Beacon Management Functions */
+       ah->ah_setBeaconTimers          = ar5416SetBeaconTimers;
+       ah->ah_beaconInit               = ar5416BeaconInit;
+       ah->ah_setStationBeaconTimers   = ar5416SetStaBeaconTimers;
+       ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers;
+
+       /* XXX 802.11n Functions */
+#if 0
+       ah->ah_chainTxDesc              = ar5416ChainTxDesc;
+       ah->ah_setupFirstTxDesc         = ar5416SetupFirstTxDesc;
+       ah->ah_setupLastTxDesc          = ar5416SetupLastTxDesc;
+       ah->ah_set11nRateScenario       = ar5416Set11nRateScenario;
+       ah->ah_set11nAggrMiddle         = ar5416Set11nAggrMiddle;
+       ah->ah_clr11nAggr               = ar5416Clr11nAggr;
+       ah->ah_set11nBurstDuration      = ar5416Set11nBurstDuration;
+       ah->ah_get11nExtBusy            = ar5416Get11nExtBusy;
+       ah->ah_set11nMac2040            = ar5416Set11nMac2040;
+       ah->ah_get11nRxClear            = ar5416Get11nRxClear;
+       ah->ah_set11nRxClear            = ar5416Set11nRxClear;
+#endif
+
+       /* Interrupt functions */
+       ah->ah_isInterruptPending       = ar5416IsInterruptPending;
+       ah->ah_getPendingInterrupts     = ar5416GetPendingInterrupts;
+       ah->ah_setInterrupts            = ar5416SetInterrupts;
+
+       ahp->ah_priv.ah_getWirelessModes= ar5416GetWirelessModes;
+       ahp->ah_priv.ah_eepromRead      = ar5416EepromRead;
+#ifdef AH_SUPPORT_WRITE_EEPROM
+       ahp->ah_priv.ah_eepromWrite     = ar5416EepromWrite;
+#endif
+       ahp->ah_priv.ah_gpioCfgOutput   = ar5416GpioCfgOutput;
+       ahp->ah_priv.ah_gpioCfgInput    = ar5416GpioCfgInput;
+       ahp->ah_priv.ah_gpioGet         = ar5416GpioGet;
+       ahp->ah_priv.ah_gpioSet         = ar5416GpioSet;
+       ahp->ah_priv.ah_gpioSetIntr     = ar5416GpioSetIntr;
+       ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits;
+
+       /*
+        * Start by setting all Owl devices to 2x2
+        */
+       AH5416(ah)->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK;
+       AH5416(ah)->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK;
+}
+
+/*
+ * Attach for an AR5416 part.
+ */
+struct ath_hal *
+ar5416Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+       struct ath_hal_5416 *ahp5416;
+       struct ath_hal_5212 *ahp;
+       struct ath_hal *ah;
+       uint32_t val;
+       HAL_STATUS ecode;
+       HAL_BOOL rfStatus;
+
+       HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
+           __func__, sc, (void*) st, (void*) sh);
+
+       /* NB: memory is returned zero'd */
+       ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416) +
+               /* extra space for Owl 2.1/2.2 WAR */
+               sizeof(ar5416Addac)
+       );
+       if (ahp5416 == AH_NULL) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                   "%s: cannot allocate memory for state block\n", __func__);
+               *status = HAL_ENOMEM;
+               return AH_NULL;
+       }
+       ar5416InitState(ahp5416, devid, sc, st, sh, status);
+       ahp = &ahp5416->ah_5212;
+       ah = &ahp->ah_priv.h;
+
+       if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
+               /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+       /* Read Revisions from Chips before taking out of reset */
+       val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
+       AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;
+       AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION;
+
+       /* setup common ini data; rf backends handle remainder */
+       HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes, 6);
+       HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common, 2);
+
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac, 2);
+
+       if (!IS_5416V2_2(ah)) {         /* Owl 2.1/2.0 */
+               struct ini {
+                       uint32_t        *data;          /* NB: !const */
+                       int             rows, cols;
+               };
+               /* override CLKDRV value */
+               OS_MEMCPY(&AH5416(ah)[1], ar5416Addac, sizeof(ar5416Addac));
+               AH5416(ah)->ah_ini_addac.data = (uint32_t *) &AH5416(ah)[1];
+               HAL_INI_VAL((struct ini *)&AH5416(ah)->ah_ini_addac, 31, 1) = 0;
+       }
+
+       if (!ar5416ChipReset(ah, AH_NULL)) {    /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",
+                   __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
+
+       if (!ar5212ChipTest(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
+                   __func__);
+               ecode = HAL_ESELFTEST;
+               goto bad;
+       }
+
+       /*
+        * Set correct Baseband to analog shift
+        * setting to access analog chips.
+        */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       /* Read Radio Chip Rev Extract */
+       AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
+       switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
+        case AR_RAD5122_SREV_MAJOR:    /* Fowl: 5G/2x2 */
+        case AR_RAD2122_SREV_MAJOR:    /* Fowl: 2+5G/2x2 */
+        case AR_RAD2133_SREV_MAJOR:    /* Fowl: 2G/3x3 */
+       case AR_RAD5133_SREV_MAJOR:     /* Fowl: 2+5G/3x3 */
+               break;
+       default:
+               if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
+                       /*
+                        * When RF_Silen is used the analog chip is reset.
+                        * So when the system boots with radio switch off
+                        * the RF chip rev reads back as zero and we need
+                        * to use the mac+phy revs to set the radio rev.
+                        */
+                       AH_PRIVATE(ah)->ah_analog5GhzRev =
+                               AR_RAD5133_SREV_MAJOR;
+                       break;
+               }
+               /* NB: silently accept anything in release code per Atheros */
+#ifdef AH_DEBUG
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: 5G Radio Chip Rev 0x%02X is not supported by "
+                   "this driver\n", __func__,
+                   AH_PRIVATE(ah)->ah_analog5GhzRev);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+#endif
+       }
+
+       ecode = ath_hal_v14EepromAttach(ah);
+       if (ecode != HAL_OK)
+               goto bad;
+
+       /*
+        * Got everything we need now to setup the capabilities.
+        */
+       if (!ar5416FillCapabilityInfo(ah)) {
+               ecode = HAL_EEREAD;
+               goto bad;
+       }
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error getting mac address from EEPROM\n", __func__);
+               goto bad;
+        }
+       /* XXX How about the serial number ? */
+       /* Read Reg Domain */
+       AH_PRIVATE(ah)->ah_currentRD =
+           ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
+
+       /*
+        * ah_miscMode is populated by ar5416FillCapabilityInfo()
+        * starting from griffin. Set here to make sure that
+        * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
+        * placed into hardware.
+        */
+       if (ahp->ah_miscMode != 0)
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: Attaching AR2133 radio\n",
+           __func__);
+       rfStatus = ar2133RfAttach(ah, &ecode);
+       if (!rfStatus) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
+                   __func__, ecode);
+               goto bad;
+       }
+
+       ar5416AniSetup(ah);                     /* Anti Noise Immunity */
+       ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
+
+       return ah;
+bad:
+       if (ahp)
+               ar5416Detach((struct ath_hal *) ahp);
+       if (status)
+               *status = ecode;
+       return AH_NULL;
+}
+
+void
+ar5416Detach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
+
+       HALASSERT(ah != AH_NULL);
+       HALASSERT(ah->ah_magic == AR5416_MAGIC);
+
+       ar5416AniDetach(ah);
+       ar5212RfDetach(ah);
+       ah->ah_disable(ah);
+       ar5416SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
+       ath_hal_eepromDetach(ah);
+       ath_hal_free(ah);
+}
+
+/*
+ * Fill all software cached or static hardware state information.
+ * Return failure if capabilities are to come from EEPROM and
+ * cannot be read.
+ */
+HAL_BOOL
+ar5416FillCapabilityInfo(struct ath_hal *ah)
+{
+       struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
+       HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
+       uint16_t val;
+
+       /* Construct wireless mode from EEPROM */
+       pCap->halWirelessModes = 0;
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
+               pCap->halWirelessModes |= HAL_MODE_11A
+                                      |  HAL_MODE_11NA_HT20
+                                      |  HAL_MODE_11NA_HT40PLUS
+                                      |  HAL_MODE_11NA_HT40MINUS
+                                      ;
+       }
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE)) {
+               pCap->halWirelessModes |= HAL_MODE_11G
+                                      |  HAL_MODE_11NG_HT20
+                                      |  HAL_MODE_11NG_HT40PLUS
+                                      |  HAL_MODE_11NG_HT40MINUS
+                                      ;
+               pCap->halWirelessModes |= HAL_MODE_11A
+                                      |  HAL_MODE_11NA_HT20
+                                      |  HAL_MODE_11NA_HT40PLUS
+                                      |  HAL_MODE_11NA_HT40MINUS
+                                      ;
+       }
+
+       pCap->halLow2GhzChan = 2312;
+       pCap->halHigh2GhzChan = 2732;
+
+       pCap->halLow5GhzChan = 4915;
+       pCap->halHigh5GhzChan = 6100;
+
+       pCap->halCipherCkipSupport = AH_FALSE;
+       pCap->halCipherTkipSupport = AH_TRUE;
+       pCap->halCipherAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES);
+
+       pCap->halMicCkipSupport    = AH_FALSE;
+       pCap->halMicTkipSupport    = AH_TRUE;
+       pCap->halMicAesCcmSupport  = ath_hal_eepromGetFlag(ah, AR_EEP_AES);
+       /*
+        * Starting with Griffin TX+RX mic keys can be combined
+        * in one key cache slot.
+        */
+       pCap->halTkipMicTxRxKeySupport = AH_TRUE;
+       pCap->halChanSpreadSupport = AH_TRUE;
+       pCap->halSleepAfterBeaconBroken = AH_TRUE;
+
+       pCap->halCompressSupport = AH_FALSE;
+       pCap->halBurstSupport = AH_TRUE;
+       pCap->halFastFramesSupport = AH_FALSE;  /* XXX? */
+       pCap->halChapTuningSupport = AH_TRUE;
+       pCap->halTurboPrimeSupport = AH_TRUE;
+
+       pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G;
+
+       pCap->halPSPollBroken = AH_TRUE;        /* XXX fixed in later revs? */
+       pCap->halVEOLSupport = AH_TRUE;
+       pCap->halBssIdMaskSupport = AH_TRUE;
+       pCap->halMcastKeySrchSupport = AH_FALSE;
+       pCap->halTsfAddSupport = AH_TRUE;
+
+       if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)
+               pCap->halTotalQueues = val;
+       else
+               pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
+
+       if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK)
+               pCap->halKeyCacheSize = val;
+       else
+               pCap->halKeyCacheSize = AR5416_KEYTABLE_SIZE;
+
+       /* XXX not needed */
+       pCap->halChanHalfRate = AH_FALSE;       /* XXX ? */
+       pCap->halChanQuarterRate = AH_FALSE;    /* XXX ? */
+
+       pCap->halTstampPrecision = 32;
+       pCap->halHwPhyCounterSupport = AH_TRUE;
+
+       pCap->halFastCCSupport = AH_TRUE;
+       pCap->halNumGpioPins = 6;
+       pCap->halWowSupport = AH_FALSE;
+       pCap->halWowMatchPatternExact = AH_FALSE;
+       pCap->halBtCoexSupport = AH_FALSE;      /* XXX need support */
+       pCap->halAutoSleepSupport = AH_FALSE;
+#if 0  /* XXX not yet */
+       pCap->halNumAntCfg2GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_2GHZ);
+       pCap->halNumAntCfg5GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_5GHZ);
+#endif
+       pCap->halHTSupport = AH_TRUE;
+       pCap->halTxChainMask = ath_hal_eepromGet(ah, AR_EEP_TXMASK, AH_NULL);
+       /* XXX CB71 uses GPIO 0 to indicate 3 rx chains */
+       pCap->halRxChainMask = ath_hal_eepromGet(ah, AR_EEP_RXMASK, AH_NULL);
+       pCap->halRtsAggrLimit = 8*1024;         /* Owl 2.0 limit */
+       pCap->halMbssidAggrSupport = AH_TRUE;
+       pCap->halForcePpmSupport = AH_TRUE;
+       pCap->halEnhancedPmSupport = AH_TRUE;
+
+       if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
+           ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
+               /* NB: enabled by default */
+               ahpriv->ah_rfkillEnabled = AH_TRUE;
+               pCap->halRfSilentSupport = AH_TRUE;
+       }
+
+       ahpriv->ah_rxornIsFatal = AH_FALSE;
+
+       return AH_TRUE;
+}
+
+static const char*
+ar5416Probe(uint16_t vendorid, uint16_t devid)
+{
+       if (vendorid == ATHEROS_VENDOR_ID &&
+           (devid == AR5416_DEVID_PCI || devid == AR5416_DEVID_PCIE))
+               return "Atheros 5416";
+       return AH_NULL;
+}
+AH_CHIP(AR5416, ar5416Probe, ar5416Attach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_beacon.c    2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_beacon.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#define TU_TO_USEC(_tu)                ((_tu) << 10)
+
+/*
+ * Initialize all of the hardware registers used to
+ * send beacons.  Note that for station operation the
+ * driver calls ar5416SetStaBeaconTimers instead.
+ */
+void
+ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
+{
+       uint32_t bperiod;
+
+       OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bt->bt_nexttbtt));
+       OS_REG_WRITE(ah, AR_NEXT_DBA, TU_TO_USEC(bt->bt_nextdba) >> 3);
+       OS_REG_WRITE(ah, AR_NEXT_SWBA, TU_TO_USEC(bt->bt_nextswba) >> 3);
+       OS_REG_WRITE(ah, AR_NEXT_NDP, TU_TO_USEC(bt->bt_nextatim));
+
+       bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD);
+       OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, bperiod);
+       OS_REG_WRITE(ah, AR_DBA_PERIOD, bperiod);
+       OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod);
+       OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod);
+
+       /*
+        * Reset TSF if required.
+        */
+       if (bt->bt_intval & AR_BEACON_RESET_TSF)
+               ar5416ResetTsf(ah);
+
+       /* enable timers */
+       /* NB: flags == 0 handled specially for backwards compatibility */
+       OS_REG_SET_BIT(ah, AR_TIMER_MODE,
+           bt->bt_flags != 0 ? bt->bt_flags :
+               AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA);
+}
+
+/*
+ * Initializes all of the hardware registers used to
+ * send beacons.  Note that for station operation the
+ * driver calls ar5212SetStaBeaconTimers instead.
+ */
+void
+ar5416BeaconInit(struct ath_hal *ah,
+       uint32_t next_beacon, uint32_t beacon_period)
+{
+       HAL_BEACON_TIMERS bt;
+
+       bt.bt_nexttbtt = next_beacon;
+       /*
+        * TIMER1: in AP/adhoc mode this controls the DMA beacon
+        * alert timer; otherwise it controls the next wakeup time.
+        * TIMER2: in AP mode, it controls the SBA beacon alert
+        * interrupt; otherwise it sets the start of the next CFP.
+        */
+       bt.bt_flags = 0;
+       switch (AH_PRIVATE(ah)->ah_opmode) {
+       case HAL_M_STA:
+       case HAL_M_MONITOR:
+               bt.bt_nextdba = 0xffff;
+               bt.bt_nextswba = 0x7ffff;
+               bt.bt_flags |= AR_TIMER_MODE_TBTT;
+               break;
+       case HAL_M_IBSS:
+               OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ATIM_TXPOLICY);
+               bt.bt_flags |= AR_TIMER_MODE_NDP;
+               /* fall thru... */
+       case HAL_M_HOSTAP:
+               bt.bt_nextdba = (next_beacon -
+                       ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */
+               bt.bt_nextswba = (next_beacon -
+                       ath_hal_sw_beacon_response_time) << 3;  /* 1/8 TU */
+               bt.bt_flags |= AR_TIMER_MODE_TBTT
+                           |  AR_TIMER_MODE_DBA
+                           |  AR_TIMER_MODE_SWBA;
+               break;
+       }
+       /*
+        * Set the ATIM window
+        * Our hardware does not support an ATIM window of 0
+        * (beacons will not work).  If the ATIM windows is 0,
+        * force it to 1.
+        */
+       bt.bt_nextatim = next_beacon + 1;
+       bt.bt_intval = beacon_period &
+               (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
+       ar5416SetBeaconTimers(ah, &bt);
+}
+
+#define AR_BEACON_PERIOD_MAX   0xffff
+
+void
+ar5416ResetStaBeaconTimers(struct ath_hal *ah)
+{
+       uint32_t val;
+
+       OS_REG_WRITE(ah, AR_NEXT_TBTT, 0);              /* no beacons */
+       val = OS_REG_READ(ah, AR_STA_ID1);
+       val |= AR_STA_ID1_PWR_SAV;              /* XXX */
+       /* tell the h/w that the associated AP is not PCF capable */
+       OS_REG_WRITE(ah, AR_STA_ID1,
+               val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF));
+       OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, AR_BEACON_PERIOD_MAX);
+       OS_REG_WRITE(ah, AR_DBA_PERIOD, AR_BEACON_PERIOD_MAX);
+}
+
+/*
+ * Set all the beacon related bits on the h/w for stations
+ * i.e. initializes the corresponding h/w timers;
+ * also tells the h/w whether to anticipate PCF beacons
+ */
+void
+ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
+{
+       uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod;
+
+       HALASSERT(bs->bs_intval != 0);
+
+       /* NB: no cfp setting since h/w automatically takes care */
+
+       OS_REG_WRITE(ah, AR_NEXT_TBTT, bs->bs_nexttbtt);
+
+       /*
+        * Start the beacon timers by setting the BEACON register
+        * to the beacon interval; no need to write tim offset since
+        * h/w parses IEs.
+        */
+       OS_REG_WRITE(ah, AR5416_BEACON_PERIOD,
+                        TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
+       OS_REG_WRITE(ah, AR_DBA_PERIOD,
+                        TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
+
+       /*
+        * Configure the BMISS interrupt.  Note that we
+        * assume the caller blocks interrupts while enabling
+        * the threshold.
+        */
+       HALASSERT(bs->bs_bmissthreshold <=
+               (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S));
+       OS_REG_RMW_FIELD(ah, AR_RSSI_THR,
+               AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
+
+       /*
+        * Program the sleep registers to correlate with the beacon setup.
+        */
+
+       /*
+        * Oahu beacons timers on the station were used for power
+        * save operation (waking up in anticipation of a beacon)
+        * and any CFP function; Venice does sleep/power-save timers
+        * differently - so this is the right place to set them up;
+        * don't think the beacon timers are used by venice sta hw
+        * for any useful purpose anymore
+        * Setup venice's sleep related timers
+        * Current implementation assumes sw processing of beacons -
+        *   assuming an interrupt is generated every beacon which
+        *   causes the hardware to become awake until the sw tells
+        *   it to go to sleep again; beacon timeout is to allow for
+        *   beacon jitter; cab timeout is max time to wait for cab
+        *   after seeing the last DTIM or MORE CAB bit
+        */
+#define CAB_TIMEOUT_VAL     10 /* in TU */
+#define BEACON_TIMEOUT_VAL  10 /* in TU */
+#define SLEEP_SLOP          3  /* in TU */
+
+       /*
+        * For max powersave mode we may want to sleep for longer than a
+        * beacon period and not want to receive all beacons; modify the
+        * timers accordingly; make sure to align the next TIM to the
+        * next DTIM if we decide to wake for DTIMs only
+        */
+       beaconintval = bs->bs_intval & HAL_BEACON_PERIOD;
+       HALASSERT(beaconintval != 0);
+       if (bs->bs_sleepduration > beaconintval) {
+               HALASSERT(roundup(bs->bs_sleepduration, beaconintval) ==
+                               bs->bs_sleepduration);
+               beaconintval = bs->bs_sleepduration;
+       }
+       dtimperiod = bs->bs_dtimperiod;
+       if (bs->bs_sleepduration > dtimperiod) {
+               HALASSERT(dtimperiod == 0 ||
+                       roundup(bs->bs_sleepduration, dtimperiod) ==
+                               bs->bs_sleepduration);
+               dtimperiod = bs->bs_sleepduration;
+       }
+       HALASSERT(beaconintval <= dtimperiod);
+       if (beaconintval == dtimperiod)
+               nextTbtt = bs->bs_nextdtim;
+       else
+               nextTbtt = bs->bs_nexttbtt;
+       nextdtim = bs->bs_nextdtim;
+
+       OS_REG_WRITE(ah, AR_NEXT_DTIM,
+               TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
+       OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
+
+       /* cab timeout is now in 1/8 TU */
+       OS_REG_WRITE(ah, AR_SLEEP1,
+               SM((CAB_TIMEOUT_VAL << 3), AR5416_SLEEP1_CAB_TIMEOUT)
+               | AR_SLEEP1_ASSUME_DTIM);
+       /* beacon timeout is now in 1/8 TU */
+       OS_REG_WRITE(ah, AR_SLEEP2,
+               SM((BEACON_TIMEOUT_VAL << 3), AR5416_SLEEP2_BEACON_TIMEOUT));
+
+       OS_REG_WRITE(ah, AR_TIM_PERIOD, beaconintval);
+       OS_REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod);
+       OS_REG_SET_BIT(ah, AR_TIMER_MODE,
+            AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n",
+           __func__, bs->bs_nextdtim);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n",
+           __func__, nextTbtt);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n",
+           __func__, beaconintval);
+       HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n",
+           __func__, dtimperiod);
+#undef CAB_TIMEOUT_VAL
+#undef BEACON_TIMEOUT_VAL
+#undef SLEEP_SLOP
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.c       2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,663 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/* Owl specific stuff */
+#define NUM_NOISEFLOOR_READINGS 6       /* 3 chains * (ctl + ext) */
+
+static void ar5416StartNFCal(struct ath_hal *ah);
+static void ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *);
+static int16_t ar5416GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+
+/*
+ * Determine if calibration is supported by device and channel flags
+ */
+static OS_INLINE HAL_BOOL
+ar5416IsCalSupp(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_CAL_TYPE calType)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+
+       switch (calType & cal->suppCals) {
+       case IQ_MISMATCH_CAL:
+               /* Run IQ Mismatch for non-CCK only */
+               return !IS_CHAN_B(chan);
+       case ADC_GAIN_CAL:
+       case ADC_DC_CAL:
+               /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
+               return !IS_CHAN_B(chan) &&
+                   !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan));
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Setup HW to collect samples used for current cal
+ */
+static void
+ar5416SetupMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal)
+{
+       /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
+           AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+           currCal->calData->calCountMax);
+
+       /* Select calibration to run */
+       switch (currCal->calData->calType) {
+       case IQ_MISMATCH_CAL:
+               OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: start IQ Mismatch calibration\n", __func__);
+               break;
+       case ADC_GAIN_CAL:
+               OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: start ADC Gain calibration\n", __func__);
+               break;
+       case ADC_DC_CAL:
+               OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: start ADC DC calibration\n", __func__);
+               break;
+       case ADC_DC_INIT_CAL:
+               OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: start Init ADC DC calibration\n", __func__);
+               break;
+       }
+       /* Kick-off cal */
+       OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+/*
+ * Initialize shared data structures and prepare a cal to be run.
+ */
+static void
+ar5416ResetMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+
+       /* Reset data structures shared between different calibrations */
+       OS_MEMZERO(cal->caldata, sizeof(cal->caldata));
+       cal->calSamples = 0;
+
+       /* Setup HW for new calibration */
+       ar5416SetupMeasurement(ah, currCal);
+
+       /* Change SW state to RUNNING for this calibration */
+       currCal->calState = CAL_RUNNING;
+}
+
+#if 0
+/*
+ * Run non-periodic calibrations.
+ */
+static HAL_BOOL
+ar5416RunInitCals(struct ath_hal *ah, int init_cal_count)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CHANNEL_INTERNAL ichan;     /* XXX bogus */
+       HAL_CAL_LIST *curCal = ahp->ah_cal_curr;
+       HAL_BOOL isCalDone;
+       int i;
+
+       if (curCal == AH_NULL)
+               return AH_FALSE;
+
+       ichan.calValid = 0;
+       for (i = 0; i < init_cal_count; i++) {
+               /* Reset this Cal */
+               ar5416ResetMeasurement(ah, curCal);
+               /* Poll for offset calibration complete */
+               if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: Cal %d failed to finish in 100ms.\n",
+                           __func__, curCal->calData->calType);
+                       /* Re-initialize list pointers for periodic cals */
+                       cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;
+                       return AH_FALSE;
+               }
+               /* Run this cal */
+               ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask,
+                   curCal, &isCalDone);
+               if (!isCalDone)
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: init cal %d did not complete.\n",
+                           __func__, curCal->calData->calType);
+               if (curCal->calNext != AH_NULL)
+                       curCal = curCal->calNext;
+       }
+
+       /* Re-initialize list pointers for periodic cals */
+       cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;
+       return AH_TRUE;
+}
+#endif
+
+/*
+ * Initialize Calibration infrastructure.
+ */
+HAL_BOOL
+ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       ichan = ath_hal_checkchannel(ah, chan);
+       HALASSERT(ichan != AH_NULL);
+
+       if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+               /* Enable Rx Filter Cal */
+               OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+               OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+
+               /* Clear the carrier leak cal bit */
+               OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+
+               /* kick off the cal */
+               OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+
+               /* Poll for offset calibration complete */
+               if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: offset calibration failed to complete in 1ms; "
+                           "noisy environment?\n", __func__);
+                       return AH_FALSE;
+               }
+
+               /* Set the cl cal bit and rerun the cal a 2nd time */
+               /* Enable Rx Filter Cal */
+               OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+               OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+
+               OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+       }
+
+       /* Calibrate the AGC */
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+
+       /* Poll for offset calibration complete */
+       if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: offset calibration did not complete in 1ms; "
+                   "noisy environment?\n", __func__);
+               return AH_FALSE;
+       }
+
+       /*
+        * Do NF calibration after DC offset and other CALs.
+        * Per system engineers, noise floor value can sometimes be 20 dB
+        * higher than normal value if DC offset and noise floor cal are
+        * triggered at the same time.
+        */
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+       /* Initialize list pointers */
+       cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;
+
+       /*
+        * Enable IQ, ADC Gain, ADC DC Offset Cals
+        */
+       if (AR_SREV_SOWL_10_OR_LATER(ah)) {
+               /* Setup all non-periodic, init time only calibrations */
+               /* XXX: Init DC Offset not working yet */
+#if 0
+               if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) {
+                       INIT_CAL(&cal->adcDcCalInitData);
+                       INSERT_CAL(cal, &cal->adcDcCalInitData);
+               }
+               /* Initialize current pointer to first element in list */
+               cal->cal_curr = cal->cal_list;
+
+               if (cal->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0))
+                       return AH_FALSE;
+#endif
+       }
+
+       /* If Cals are supported, add them to list via INIT/INSERT_CAL */
+       if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) {
+               INIT_CAL(&cal->adcGainCalData);
+               INSERT_CAL(cal, &cal->adcGainCalData);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: enable ADC Gain Calibration.\n", __func__);
+       }
+       if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) {
+               INIT_CAL(&cal->adcDcCalData);
+               INSERT_CAL(cal, &cal->adcDcCalData);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: enable ADC DC Calibration.\n", __func__);
+       }
+       if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) {
+               INIT_CAL(&cal->iqCalData);
+               INSERT_CAL(cal, &cal->iqCalData);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%s: enable IQ Calibration.\n", __func__);
+       }
+       /* Initialize current pointer to first element in list */
+       cal->cal_curr = cal->cal_list;
+
+       /* Kick off measurements for the first cal */
+       if (cal->cal_curr != AH_NULL)
+               ar5416ResetMeasurement(ah, cal->cal_curr);
+
+       /* Mark all calibrations on this channel as being invalid */
+       ichan->calValid = 0;
+
+       return AH_TRUE;
+}
+
+/*
+ * Entry point for upper layers to restart current cal.
+ * Reset the calibration valid bit in channel.
+ */
+HAL_BOOL
+ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
+       HAL_CAL_LIST *currCal = cal->cal_curr;
+
+       if (!AR_SREV_SOWL_10_OR_LATER(ah))
+               return AH_FALSE;
+       if (currCal == AH_NULL)
+               return AH_FALSE;
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               return AH_FALSE;
+       }
+       /*
+        * Expected that this calibration has run before, post-reset.
+        * Current state should be done
+        */
+       if (currCal->calState != CAL_DONE) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: Calibration state incorrect, %d\n",
+                   __func__, currCal->calState);
+               return AH_FALSE;
+       }
+
+       /* Verify Cal is supported on this channel */
+       if (!ar5416IsCalSupp(ah, chan, currCal->calData->calType))
+               return AH_FALSE;
+
+       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+           "%s: Resetting Cal %d state for channel %u/0x%x\n",
+           __func__, currCal->calData->calType, chan->channel,
+           chan->channelFlags);
+
+       /* Disable cal validity in channel */
+       ichan->calValid &= ~currCal->calData->calType;
+       currCal->calState = CAL_WAITING;
+
+       return AH_TRUE;
+}
+
+/*
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+static void
+ar5416DoCalibration(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *ichan,
+       uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+
+       /* Cal is assumed not done until explicitly set below */
+       *isCalDone = AH_FALSE;
+
+       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+           "%s: %s Calibration, state %d, calValid 0x%x\n",
+           __func__, currCal->calData->calName, currCal->calState,
+           ichan->calValid);
+
+       /* Calibration in progress. */
+       if (currCal->calState == CAL_RUNNING) {
+               /* Check to see if it has finished. */
+               if (!(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_CAL)) {
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "%s: sample %d of %d finished\n",
+                           __func__, cal->calSamples,
+                           currCal->calData->calNumSamples);
+                       /*
+                        * Collect measurements for active chains.
+                        */
+                       currCal->calData->calCollect(ah);
+                       if (++cal->calSamples >= currCal->calData->calNumSamples) {
+                               int i, numChains = 0;
+                               for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+                                       if (rxchainmask & (1 << i))
+                                               numChains++;
+                               }
+                               /*
+                                * Process accumulated data
+                                */
+                               currCal->calData->calPostProc(ah, numChains);
+
+                               /* Calibration has finished. */
+                               ichan->calValid |= currCal->calData->calType;
+                               currCal->calState = CAL_DONE;
+                               *isCalDone = AH_TRUE;
+                       } else {
+                               /*
+                                * Set-up to collect of another sub-sample.
+                                */
+                               ar5416SetupMeasurement(ah, currCal);
+                       }
+               }
+       } else if (!(ichan->calValid & currCal->calData->calType)) {
+               /* If current cal is marked invalid in channel, kick it off */
+               ar5416ResetMeasurement(ah, currCal);
+       }
+}
+
+/*
+ * Internal interface to schedule periodic calibration work.
+ */
+HAL_BOOL
+ar5416PerCalibrationN(struct ath_hal *ah,  HAL_CHANNEL *chan,
+       u_int rxchainmask, HAL_BOOL longcal, HAL_BOOL *isCalDone)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CAL_LIST *currCal = cal->cal_curr;
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       OS_MARK(ah, AH_MARK_PERCAL, chan->channel);
+
+       *isCalDone = AH_TRUE;
+
+       /* Invalid channel check */
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               return AH_FALSE;
+       }
+
+       /*
+        * For given calibration:
+        * 1. Call generic cal routine
+        * 2. When this cal is done (isCalDone) if we have more cals waiting
+        *    (eg after reset), mask this to upper layers by not propagating
+        *    isCalDone if it is set to TRUE.
+        *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
+        *    to be run.
+        */
+       if (currCal != AH_NULL &&
+           (currCal->calState == CAL_RUNNING ||
+            currCal->calState == CAL_WAITING)) {
+               ar5416DoCalibration(ah, ichan, rxchainmask, currCal, isCalDone);
+               if (*isCalDone == AH_TRUE) {
+                       cal->cal_curr = currCal = currCal->calNext;
+                       if (currCal->calState == CAL_WAITING) {
+                               *isCalDone = AH_FALSE;
+                               ar5416ResetMeasurement(ah, currCal);
+                       }
+               }
+       }
+
+       /* Do NF cal only at longer intervals */
+       if (longcal) {
+               /*
+                * Get the value from the previous NF cal
+                * and update the history buffer.
+                */
+               ar5416GetNf(ah, ichan);
+
+               /*
+                * Load the NF from history buffer of the current channel.
+                * NF is slow time-variant, so it is OK to use a
+                * historical value.
+                */
+               ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan);
+
+               /* start NF calibration, without updating BB NF register*/
+               ar5416StartNFCal(ah);
+
+               if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
+                       /* report up and clear internal state */
+                       chan->channelFlags |= CHANNEL_CW_INT;
+                       ichan->channelFlags &= ~CHANNEL_CW_INT;
+               }
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Recalibrate the lower PHY chips to account for temperature/environment
+ * changes.
+ */
+HAL_BOOL
+ar5416PerCalibration(struct ath_hal *ah,  HAL_CHANNEL *chan, HAL_BOOL *isIQdone)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       HAL_CAL_LIST *curCal = cal->cal_curr;
+
+       if (curCal != AH_NULL && curCal->calData->calType == IQ_MISMATCH_CAL) {
+               return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask,
+                   AH_TRUE, isIQdone);
+       } else {
+               HAL_BOOL isCalDone;
+
+               *isIQdone = AH_FALSE;
+               return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask,
+                   AH_TRUE, &isCalDone);
+       }
+}
+
+static HAL_BOOL
+ar5416GetEepromNoiseFloorThresh(struct ath_hal *ah,
+       const HAL_CHANNEL_INTERNAL *chan, int16_t *nft)
+{
+       switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+               ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_5, nft);
+               break;
+       case CHANNEL_B:
+       case CHANNEL_G:
+       case CHANNEL_G_HT20:
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_2, nft);
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               return AH_FALSE;
+       }
+       return AH_TRUE;
+}
+
+static void
+ar5416StartNFCal(struct ath_hal *ah)
+{
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+static void
+ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       static const uint32_t ar5416_cca_regs[] = {
+               AR_PHY_CCA,
+               AR_PHY_CH1_CCA,
+               AR_PHY_CH2_CCA,
+               AR_PHY_EXT_CCA,
+               AR_PHY_CH1_EXT_CCA,
+               AR_PHY_CH2_EXT_CCA
+       };
+       struct ar5212NfCalHist *h;
+       int i, j;
+       int32_t val;
+       uint8_t chainmask;
+
+       /*
+        * Force NF calibration for all chains.
+        */
+       if (AR_SREV_KITE(ah)) {
+               /* Kite has only one chain */
+               chainmask = 0x9;
+       } else if (AR_SREV_MERLIN(ah)) {
+               /* Merlin has only two chains */
+               chainmask = 0x1B;
+       } else {
+               chainmask = 0x3F;
+       }
+
+       /*
+        * Write filtered NF values into maxCCApwr register parameter
+        * so we can load below.
+        */
+       h = AH5416(ah)->ah_cal.nfCalHist;
+       for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
+               if (chainmask & (1 << i)) {
+                       val = OS_REG_READ(ah, ar5416_cca_regs[i]);
+                       val &= 0xFFFFFE00;
+                       val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff);
+                       OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
+               }
+
+       /* Load software filtered NF value into baseband internal minCCApwr variable. */
+       OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
+       OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+       OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+       /* Wait for load to complete, should be fast, a few 10s of us. */
+       for (j = 0; j < 1000; j++) {
+               if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0)
+                       break;
+               OS_DELAY(10);
+       }
+
+       /*
+        * Restore maxCCAPower register parameter again so that we're not capped
+        * by the median we just loaded.  This will be initial (and max) value
+        * of next noise floor calibration the baseband does.
+        */
+       for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
+               if (chainmask & (1 << i)) {
+                       val = OS_REG_READ(ah, ar5416_cca_regs[i]);
+                       val &= 0xFFFFFE00;
+                       val |= (((uint32_t)(-50) << 1) & 0x1ff);
+                       OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
+               }
+}
+
+void
+ar5416InitNfHistBuff(struct ar5212NfCalHist *h)
+{
+       int i, j;
+
+       for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) {
+               h[i].currIndex = 0;
+               h[i].privNF = AR5416_CCA_MAX_GOOD_VALUE;
+               h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX;
+               for (j = 0; j < AR512_NF_CAL_HIST_MAX; j ++)
+                       h[i].nfCalBuffer[j] = AR5416_CCA_MAX_GOOD_VALUE;
+       }
+}
+
+/*
+ * Update the noise floor buffer as a ring buffer
+ */
+static void
+ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray)
+{
+       int i;
+
+       for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) {
+               h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+               if (++h[i].currIndex >= AR512_NF_CAL_HIST_MAX)
+                       h[i].currIndex = 0;
+               if (h[i].invalidNFcount > 0) {
+                       if (nfarray[i] < AR5416_CCA_MIN_BAD_VALUE ||
+                           nfarray[i] > AR5416_CCA_MAX_HIGH_VALUE) {
+                               h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX;
+                       } else {
+                               h[i].invalidNFcount--;
+                               h[i].privNF = nfarray[i];
+                       }
+               } else {
+                       h[i].privNF = ar5212GetNfHistMid(h[i].nfCalBuffer);
+               }
+       }
+}
+
+/*
+ * Read the NF and check it against the noise floor threshhold
+ */
+static int16_t
+ar5416GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+       int16_t nf, nfThresh;
+
+       if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: NF didn't complete in calibration window\n", __func__);
+               nf = 0;
+       } else {
+               /* Finished NF cal, check against threshold */
+               int16_t nfarray[NUM_NOISEFLOOR_READINGS] = { 0 };
+
+               /* TODO - enhance for multiple chains and ext ch */
+               ath_hal_getNoiseFloor(ah, nfarray);
+               nf = nfarray[0];
+               if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) {
+                       if (nf > nfThresh) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "%s: noise floor failed detected; "
+                                   "detected %d, threshold %d\n", __func__,
+                                   nf, nfThresh);
+                               /*
+                                * NB: Don't discriminate 2.4 vs 5Ghz, if this
+                                *     happens it indicates a problem regardless
+                                *     of the band.
+                                */
+                               chan->channelFlags |= CHANNEL_CW_INT;
+                               nf = 0;
+                       }
+               } else {
+                       nf = 0;
+               }
+               ar5416UpdateNFHistBuff(AH5416(ah)->ah_cal.nfCalHist, nfarray);
+               chan->rawNoiseFloor = nf;
+       }
+       return nf;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal.h       2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _ATH_AR5416_CAL_H_
+#define _ATH_AR5416_CAL_H_
+
+typedef enum {
+       ADC_DC_INIT_CAL = 0x1,
+       ADC_GAIN_CAL    = 0x2,
+       ADC_DC_CAL      = 0x4,
+       IQ_MISMATCH_CAL = 0x8
+} HAL_CAL_TYPE;
+
+/* Calibrate state */
+typedef enum {
+       CAL_INACTIVE,
+       CAL_WAITING,
+       CAL_RUNNING,
+       CAL_DONE
+} HAL_CAL_STATE;
+
+typedef union {
+       uint32_t        u;
+       int32_t         s;
+} HAL_CAL_SAMPLE;
+
+#define        MIN_CAL_SAMPLES     1
+#define        MAX_CAL_SAMPLES    64
+#define        INIT_LOG_COUNT      5
+#define        PER_MIN_LOG_COUNT   2
+#define        PER_MAX_LOG_COUNT  10
+
+/* Per Calibration data structure */
+typedef struct per_cal_data {
+       const char      *calName;               /* for diagnostics */
+       HAL_CAL_TYPE    calType;                /* Type of calibration */
+       uint32_t        calNumSamples;          /* # SW samples to collect */
+       uint32_t        calCountMax;            /* # HW samples to collect */
+       void (*calCollect)(struct ath_hal *);   /* Accumulator function */
+                                               /* Post-processing function */
+       void (*calPostProc)(struct ath_hal *, uint8_t);
+} HAL_PERCAL_DATA;
+
+/* List structure for calibration data */
+typedef struct cal_list {
+       struct cal_list         *calNext;
+       HAL_CAL_STATE           calState;
+       const HAL_PERCAL_DATA   *calData;
+} HAL_CAL_LIST;
+
+struct ar5416PerCal {
+       /*
+        * Periodic calibration state.
+        */
+       HAL_CAL_TYPE    suppCals;
+       HAL_CAL_LIST    iqCalData;
+       HAL_CAL_LIST    adcGainCalData;
+       HAL_CAL_LIST    adcDcCalInitData;
+       HAL_CAL_LIST    adcDcCalData;
+       HAL_CAL_LIST    *cal_list;
+       HAL_CAL_LIST    *cal_last;
+       HAL_CAL_LIST    *cal_curr;
+#define AR5416_MAX_CHAINS              3       /* XXX dup's eeprom def */
+       HAL_CAL_SAMPLE  caldata[4][AR5416_MAX_CHAINS];
+       int             calSamples;
+       /*
+        * Noise floor cal histogram support.
+        * XXX be nice to re-use space in ar5212
+        */
+#define        AR5416_NUM_NF_READINGS          6       /* (3 chains * (ctl + ext) */
+       struct ar5212NfCalHist nfCalHist[AR5416_NUM_NF_READINGS];
+};
+
+#define INIT_CAL(_perCal) do {                                         \
+       (_perCal)->calState = CAL_WAITING;                              \
+       (_perCal)->calNext = AH_NULL;                                   \
+} while (0)
+
+#define INSERT_CAL(_cal, _perCal) do {                                 \
+       if ((_cal)->cal_last == AH_NULL) {                              \
+               (_cal)->cal_list = (_cal)->cal_last = (_perCal);        \
+               ((_cal)->cal_last)->calNext = (_perCal);                \
+       } else {                                                        \
+               ((_cal)->cal_last)->calNext = (_perCal);                \
+               (_cal)->cal_last = (_perCal);                           \
+               (_perCal)->calNext = (_cal)->cal_list;                  \
+       }                                                               \
+} while (0)
+
+HAL_BOOL ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan);
+HAL_BOOL ar5416PerCalibration(struct ath_hal *,  HAL_CHANNEL *,
+           HAL_BOOL *isIQdone);
+HAL_BOOL ar5416PerCalibrationN(struct ath_hal *ah, HAL_CHANNEL *chan,
+           u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone);
+HAL_BOOL ar5416ResetCalValid(struct ath_hal *ah,  HAL_CHANNEL *chan);
+
+void   ar5416IQCalCollect(struct ath_hal *ah);
+void   ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains);
+void   ar5416AdcGainCalCollect(struct ath_hal *ah);
+void   ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains);
+void   ar5416AdcDcCalCollect(struct ath_hal *ah);
+void   ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains);
+void   ar5416InitNfHistBuff(struct ar5212NfCalHist *h);
+#endif /* _ATH_AR5416_CAL_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcdc.c 2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal_adcdc.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/* Adc DC Offset Cal aliases */
+#define        totalAdcDcOffsetIOddPhase(i)    caldata[0][i].s
+#define        totalAdcDcOffsetIEvenPhase(i)   caldata[1][i].s
+#define        totalAdcDcOffsetQOddPhase(i)    caldata[2][i].s
+#define        totalAdcDcOffsetQEvenPhase(i)   caldata[3][i].s
+
+void
+ar5416AdcDcCalCollect(struct ath_hal *ah)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       int i;
+
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               cal->totalAdcDcOffsetIOddPhase(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               cal->totalAdcDcOffsetIEvenPhase(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               cal->totalAdcDcOffsetQOddPhase(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               cal->totalAdcDcOffsetQEvenPhase(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+                  cal->calSamples, i,
+                  cal->totalAdcDcOffsetIOddPhase(i),
+                  cal->totalAdcDcOffsetIEvenPhase(i),
+                  cal->totalAdcDcOffsetQOddPhase(i),
+                  cal->totalAdcDcOffsetQEvenPhase(i));
+       }
+}
+
+void
+ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       const HAL_PERCAL_DATA *calData = cal->cal_curr->calData;
+       uint32_t numSamples;
+       int i;
+
+       numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
+       for (i = 0; i < numChains; i++) {
+               uint32_t iOddMeasOffset = cal->totalAdcDcOffsetIOddPhase(i);
+               uint32_t iEvenMeasOffset = cal->totalAdcDcOffsetIEvenPhase(i);
+               int32_t qOddMeasOffset = cal->totalAdcDcOffsetQOddPhase(i);
+               int32_t qEvenMeasOffset = cal->totalAdcDcOffsetQEvenPhase(i);
+               int32_t qDcMismatch, iDcMismatch;
+               uint32_t val;
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "Starting ADC DC Offset Cal for Chain %d\n", i);
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_i = %d\n",
+                   iOddMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_i = %d\n",
+                   iEvenMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_q = %d\n",
+                   qOddMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_q = %d\n",
+                   qEvenMeasOffset);
+
+               HALASSERT(numSamples);
+
+               iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
+                   numSamples) & 0x1ff;
+               qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
+                   numSamples) & 0x1ff;
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   " dc_offset_mismatch_i = 0x%08x\n", iDcMismatch);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   " dc_offset_mismatch_q = 0x%08x\n", qDcMismatch);
+
+               val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+               val &= 0xc0000fff;
+               val |= (qDcMismatch << 12) | (iDcMismatch << 21);
+               OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "ADC DC Offset Cal done for Chain %d\n", i);
+       }
+       OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+           AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_adcgain.c       2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal_adcgain.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/* Adc Gain Cal aliases */
+#define        totalAdcIOddPhase(i)    caldata[0][i].u
+#define        totalAdcIEvenPhase(i)   caldata[1][i].u
+#define        totalAdcQOddPhase(i)    caldata[2][i].u
+#define        totalAdcQEvenPhase(i)   caldata[3][i].u
+
+/*
+ * Collect data from HW to later perform ADC Gain Calibration
+ */
+void
+ar5416AdcGainCalCollect(struct ath_hal *ah)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       int i;
+
+       /*
+       * Accumulate ADC Gain cal measures for active chains
+       */
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               cal->totalAdcIOddPhase(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               cal->totalAdcIEvenPhase(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               cal->totalAdcQOddPhase(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               cal->totalAdcQEvenPhase(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+                   cal->calSamples, i, cal->totalAdcIOddPhase(i),
+                   cal->totalAdcIEvenPhase(i), cal->totalAdcQOddPhase(i),
+                   cal->totalAdcQEvenPhase(i));
+       }
+}
+
+/*
+ * Use HW data to do ADC Gain Calibration
+ */
+void
+ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       uint32_t i;
+
+       for (i = 0; i < numChains; i++) {
+               uint32_t iOddMeasOffset  = cal->totalAdcIOddPhase(i);
+               uint32_t iEvenMeasOffset = cal->totalAdcIEvenPhase(i);
+               uint32_t qOddMeasOffset  = cal->totalAdcQOddPhase(i);
+               uint32_t qEvenMeasOffset = cal->totalAdcQEvenPhase(i);
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "Start ADC Gain Cal for Chain %d\n", i);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "  pwr_meas_odd_i = 0x%08x\n", iOddMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "  pwr_meas_even_i = 0x%08x\n", iEvenMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "  pwr_meas_odd_q = 0x%08x\n", qOddMeasOffset);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "  pwr_meas_even_q = 0x%08x\n", qEvenMeasOffset);
+
+               if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
+                       uint32_t iGainMismatch =
+                           ((iEvenMeasOffset*32)/iOddMeasOffset) & 0x3f;
+                       uint32_t qGainMismatch =
+                           ((qOddMeasOffset*32)/qEvenMeasOffset) & 0x3f;
+                       uint32_t val;
+
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           " gain_mismatch_i = 0x%08x\n",
+                           iGainMismatch);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           " gain_mismatch_q = 0x%08x\n",
+                           qGainMismatch);
+
+                       val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+                       val &= 0xfffff000;
+                       val |= (qGainMismatch) | (iGainMismatch << 6);
+                       OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+                       HALDEBUG(ah,  HAL_DEBUG_PERCAL,
+                           "ADC Gain Cal done for Chain %d\n", i);
+               }
+       }
+       OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+           AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_cal_iq.c    2009-05-15 11:11:28.000000000 +0100
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_cal_iq.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/* IQ Cal aliases */
+#define        totalPowerMeasI(i)      caldata[0][i].u
+#define        totalPowerMeasQ(i)      caldata[1][i].u
+#define        totalIqCorrMeas(i)      caldata[2][i].s
+
+/*
+ * Collect data from HW to later perform IQ Mismatch Calibration
+ */
+void
+ar5416IQCalCollect(struct ath_hal *ah)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       int i;
+
+       /*
+        * Accumulate IQ cal measures for active chains
+        */
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               cal->totalPowerMeasI(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+               cal->totalPowerMeasQ(i) +=
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+               cal->totalIqCorrMeas(i) += (int32_t)
+                   OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+                   cal->calSamples, i, cal->totalPowerMeasI(i),
+                   cal->totalPowerMeasQ(i), cal->totalIqCorrMeas(i));
+       }
+}
+
+/*
+ * Use HW data to do IQ Mismatch Calibration
+ */
+void
+ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains)
+{
+       struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
+       int i;
+
+       for (i = 0; i < numChains; i++) {
+               uint32_t powerMeasI = cal->totalPowerMeasI(i);
+               uint32_t powerMeasQ = cal->totalPowerMeasQ(i);
+               uint32_t iqCorrMeas = cal->totalIqCorrMeas(i);
+               uint32_t qCoffDenom, iCoffDenom;
+               int iqCorrNeg;
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "Start IQ Cal and Correction for Chain %d\n", i);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                   "Orignal: iq_corr_meas = 0x%08x\n", iqCorrMeas);
+
+               iqCorrNeg = 0;
+               /* iqCorrMeas is always negative. */
+               if (iqCorrMeas > 0x80000000)  {
+                       iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+                       iqCorrNeg = 1;
+               }
+
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_i = 0x%08x\n",
+                   powerMeasI);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_q = 0x%08x\n",
+                   powerMeasQ);
+               HALDEBUG(ah, HAL_DEBUG_PERCAL, " iqCorrNeg is 0x%08x\n",
+                   iqCorrNeg);
+
+               iCoffDenom = (powerMeasI/2 + powerMeasQ/2)/ 128;
+               qCoffDenom = powerMeasQ / 64;
+               /* Protect against divide-by-0 */
+               if (powerMeasQ != 0) {
+                       /* IQ corr_meas is already negated if iqcorr_neg == 1 */
+                       int32_t iCoff = iqCorrMeas/iCoffDenom;
+                       int32_t qCoff = powerMeasI/qCoffDenom - 64;
+
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, " iCoff = 0x%08x\n",
+                           iCoff);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL, " qCoff = 0x%08x\n",
+                           qCoff);
+
+                       /* Negate iCoff if iqCorrNeg == 0 */
+                       iCoff = iCoff & 0x3f;
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "New:  iCoff = 0x%08x\n", iCoff);
+
+                       if (iqCorrNeg == 0x0)
+                               iCoff = 0x40 - iCoff;
+                       if (qCoff > 15)
+                               qCoff = 15;
+                       else if (qCoff <= -16)
+                               qCoff = 16;
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           " : iCoff = 0x%x  qCoff = 0x%x\n", iCoff, qCoff);
+
+                       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i),
+                           AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff);
+                       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i),
+                           AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff);
+                       HALDEBUG(ah, HAL_DEBUG_PERCAL,
+                           "IQ Cal and Correction done for Chain %d\n", i);
+               }
+       }
+       OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
+           AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_eeprom.c    2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_eeprom.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/*
+ * Read 16 bits of data from offset into *data
+ */
+HAL_BOOL
+ar5416EepromRead(struct ath_hal *ah, u_int off, uint16_t *data)
+{
+        OS_REG_READ(ah,  AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+               if (!ath_hal_wait(ah, AR_EEPROM_STATUS_DATA,
+           AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0))
+               return AH_FALSE;
+               *data = MS(OS_REG_READ(ah, AR_EEPROM_STATUS_DATA),
+                  AR_EEPROM_STATUS_DATA_VAL);
+       return AH_TRUE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_gpio.c      2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_gpio.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#ifdef AH_DEBUG
+#include "ah_desc.h"                   /* NB: for HAL_PHYERR* */
+#endif
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#define        AR_NUM_GPIO     6               /* 6 GPIO pins */
+#define AR_GPIO_BIT(_gpio)     (1 << _gpio)
+
+/*
+ * Configure GPIO Output lines
+ */
+HAL_BOOL
+ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio)
+{
+       HALASSERT(gpio < AR_NUM_GPIO);
+       OS_REG_CLR_BIT(ah, AR_GPIO_INTR_OUT, AR_GPIO_BIT(gpio));
+       return AH_TRUE;
+}
+
+/*
+ * Configure GPIO Input lines
+ */
+HAL_BOOL
+ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
+{
+       HALASSERT(gpio < AR_NUM_GPIO);
+       OS_REG_SET_BIT(ah, AR_GPIO_INTR_OUT, AR_GPIO_BIT(gpio));
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - set output lines
+ */
+HAL_BOOL
+ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
+{
+       uint32_t reg;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+       reg = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_OUT_VAL);
+       if (val & 1)
+               reg |= AR_GPIO_BIT(gpio);
+       else
+               reg &= ~AR_GPIO_BIT(gpio);
+
+       OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_OUT_VAL, reg);
+       return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - get input lines
+ */
+uint32_t
+ar5416GpioGet(struct ath_hal *ah, uint32_t gpio)
+{
+       if (gpio >= AR_NUM_GPIO)
+               return 0xffffffff;
+       return ((OS_REG_READ(ah, AR_GPIO_IN) & AR_GPIO_BIT(gpio)) >> gpio);
+}
+
+/*
+ * Set the GPIO Interrupt
+ */
+void
+ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
+{
+       uint32_t val;
+
+       HALASSERT(gpio < AR_NUM_GPIO);
+       /* XXX bounds check gpio */
+       val = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_INTR_CTRL);
+       if (ilevel)             /* 0 == interrupt on pin high */
+               val &= ~AR_GPIO_BIT(gpio);
+       else                    /* 1 == interrupt on pin low */
+               val |= AR_GPIO_BIT(gpio);
+       OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_INTR_CTRL, val);
+
+       /* Change the interrupt mask. */
+       val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), AR_INTR_GPIO);
+       val |= AR_GPIO_BIT(gpio);
+       OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_GPIO, val);
+
+       val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), AR_INTR_GPIO);
+       val |= AR_GPIO_BIT(gpio);
+       OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, AR_INTR_GPIO, val);
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_interrupts.c        2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_interrupts.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+
+/*
+ * Checks to see if an interrupt is pending on our NIC
+ *
+ * Returns: TRUE    if an interrupt is pending
+ *          FALSE   if not
+ */
+HAL_BOOL
+ar5416IsInterruptPending(struct ath_hal *ah)
+{
+       uint32_t isr;
+       /*
+        * Some platforms trigger our ISR before applying power to
+        * the card, so make sure the INTPEND is really 1, not 0xffffffff.
+        */
+       isr = OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE);
+       if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_MAC_IRQ) != 0)
+               return AH_TRUE;
+
+       isr = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
+       if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_SYNC_DEFAULT))
+               return AH_TRUE;
+
+       return AH_FALSE;
+}
+
+/*
+ * Reads the Interrupt Status Register value from the NIC, thus deasserting
+ * the interrupt line, and returns both the masked and unmasked mapped ISR
+ * values.  The value returned is mapped to abstract the hw-specific bit
+ * locations in the Interrupt Status Register.
+ *
+ * Returns: A hardware-abstracted bitmap of all non-masked-out
+ *          interrupts pending, as well as an unmasked value
+ */
+HAL_BOOL
+ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)
+{
+       uint32_t isr, isr0, isr1, sync_cause;
+
+       /*
+        * Verify there's a mac interrupt and the RTC is on.
+        */
+       if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) &&
+           (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON)
+               isr = OS_REG_READ(ah, AR_ISR);
+       else
+               isr = 0;
+       sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
+       sync_cause &= AR_INTR_SYNC_DEFAULT;
+       if (isr == 0 && sync_cause == 0) {
+               *masked = 0;
+               return AH_FALSE;
+       }
+
+       if (isr != 0) {
+               struct ath_hal_5212 *ahp = AH5212(ah);
+               uint32_t mask2;
+
+               mask2 = 0;
+               if (isr & AR_ISR_BCNMISC) {
+                       uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2);
+                       if (isr2 & AR_ISR_S2_TIM)
+                               mask2 |= HAL_INT_TIM;
+                       if (isr2 & AR_ISR_S2_DTIM)
+                               mask2 |= HAL_INT_DTIM;
+                       if (isr2 & AR_ISR_S2_DTIMSYNC)
+                               mask2 |= HAL_INT_DTIMSYNC;
+                       if (isr2 & (AR_ISR_S2_CABEND ))
+                               mask2 |= HAL_INT_CABEND;
+                       if (isr2 & AR_ISR_S2_GTT)
+                               mask2 |= HAL_INT_GTT;
+                       if (isr2 & AR_ISR_S2_CST)
+                               mask2 |= HAL_INT_CST;
+                       if (isr2 & AR_ISR_S2_TSFOOR)
+                               mask2 |= HAL_INT_TSFOOR;
+               }
+
+               isr = OS_REG_READ(ah, AR_ISR_RAC);
+               if (isr == 0xffffffff) {
+                       *masked = 0;
+                       return AH_FALSE;;
+               }
+
+               *masked = isr & HAL_INT_COMMON;
+               if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+                       *masked |= HAL_INT_RX;
+               if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) {
+                       *masked |= HAL_INT_TX;
+                       isr0 = OS_REG_READ(ah, AR_ISR_S0_S);
+                       ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK);
+                       ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC);
+                       isr1 = OS_REG_READ(ah, AR_ISR_S1_S);
+                       ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR);
+                       ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL);
+               }
+
+               /* Interrupt Mitigation on AR5416 */
+#ifdef AR5416_INT_MITIGATION
+               if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+                       *masked |= HAL_INT_RX;
+               if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
+                       *masked |= HAL_INT_TX;
+#endif
+               *masked |= mask2;
+       }
+       if (sync_cause != 0) {
+               if (sync_cause & (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) {
+                       *masked |= HAL_INT_FATAL;
+               }
+               if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RADM CPL timeout\n",
+                           __func__);
+                       OS_REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
+                       OS_REG_WRITE(ah, AR_RC, 0);
+                       *masked |= HAL_INT_FATAL;
+               }
+               /*
+                * On fatal errors collect ISR state for debugging.
+                */
+               if (*masked & HAL_INT_FATAL) {
+                       AH_PRIVATE(ah)->ah_fatalState[0] = isr;
+                       AH_PRIVATE(ah)->ah_fatalState[1] = sync_cause;
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: fatal error, ISR_RAC 0x%x SYNC_CAUSE 0x%x\n",
+                           __func__, isr, sync_cause);
+               }
+
+               OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+               /* NB: flush write */
+               (void) OS_REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Atomically enables NIC interrupts.  Interrupts are passed in
+ * via the enumerated bitmask in ints.
+ */
+HAL_INT
+ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       uint32_t omask = ahp->ah_maskReg;
+       uint32_t mask,mask2;
+
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",
+           __func__, omask, ints);
+
+       if (omask & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+               (void) OS_REG_READ(ah, AR_IER);
+
+               OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+               (void) OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+               OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+               (void) OS_REG_READ(ah, AR_INTR_SYNC_ENABLE);
+       }
+
+       mask = ints & HAL_INT_COMMON;
+       mask2 = 0;
+
+       if (ints & HAL_INT_TX) {
+               if (ahp->ah_txOkInterruptMask)
+                       mask |= AR_IMR_TXOK;
+               if (ahp->ah_txErrInterruptMask)
+                       mask |= AR_IMR_TXERR;
+               if (ahp->ah_txDescInterruptMask)
+                       mask |= AR_IMR_TXDESC;
+               if (ahp->ah_txEolInterruptMask)
+                       mask |= AR_IMR_TXEOL;
+       }
+       if (ints & HAL_INT_RX)
+               mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC;
+#ifdef AR5416_INT_MITIGATION
+       /*
+        * Overwrite default mask if Interrupt mitigation
+        * is specified for AR5416
+        */
+       mask = ints & HAL_INT_COMMON;
+       if (ints & HAL_INT_TX)
+               mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
+       if (ints & HAL_INT_RX)
+               mask |= AR_IMR_RXERR | AR_IMR_RXMINTR | AR_IMR_RXINTM;
+#endif
+       if (ints & (HAL_INT_BMISC)) {
+               mask |= AR_IMR_BCNMISC;
+               if (ints & HAL_INT_TIM)
+                       mask2 |= AR_IMR_S2_TIM;
+               if (ints & HAL_INT_DTIM)
+                       mask2 |= AR_IMR_S2_DTIM;
+               if (ints & HAL_INT_DTIMSYNC)
+                       mask2 |= AR_IMR_S2_DTIMSYNC;
+               if (ints & HAL_INT_CABEND)
+                       mask2 |= (AR_IMR_S2_CABEND );
+               if (ints & HAL_INT_GTT)
+                       mask2 |= AR_IMR_S2_GTT;
+               if (ints & HAL_INT_CST)
+                       mask2 |= AR_IMR_S2_CST;
+               if (ints & HAL_INT_TSFOOR)
+                       mask2 |= AR_IMR_S2_TSFOOR;
+       }
+
+       /* Write the new IMR and store off our SW copy. */
+       HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
+       OS_REG_WRITE(ah, AR_IMR, mask);
+       mask = OS_REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
+                                       AR_IMR_S2_DTIM |
+                                       AR_IMR_S2_DTIMSYNC |
+                                       AR_IMR_S2_CABEND |
+                                       AR_IMR_S2_CABTO  |
+                                       AR_IMR_S2_TSFOOR |
+                                       AR_IMR_S2_GTT |
+                                       AR_IMR_S2_CST);
+       OS_REG_WRITE(ah, AR_IMR_S2, mask | mask2);
+
+       ahp->ah_maskReg = ints;
+
+       /* Re-enable interrupts if they were enabled before. */
+       if (ints & HAL_INT_GLOBAL) {
+               HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
+               OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+
+               OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_MAC_IRQ);
+               OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+               OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
+               OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, AR_INTR_SYNC_DEFAULT);
+       }
+
+       return omask;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_keycache.c  2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_keycache.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+
+static const int keyType[] = {
+       1,      /* HAL_CIPHER_WEP */
+       0,      /* HAL_CIPHER_AES_OCB */
+       2,      /* HAL_CIPHER_AES_CCM */
+       0,      /* HAL_CIPHER_CKIP */
+       3,      /* HAL_CIPHER_TKIP */
+       0,      /* HAL_CIPHER_CLR */
+};
+
+/*
+ * Clear the specified key cache entry and any associated MIC entry.
+ */
+HAL_BOOL
+ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+
+       if (ar5212ResetKeyCacheEntry(ah, entry)) {
+               ahp->ah_keytype[entry] = keyType[HAL_CIPHER_CLR];
+               return AH_TRUE;
+       } else
+               return AH_FALSE;
+}
+
+/*
+ * Sets the contents of the specified key cache entry
+ * and any associated MIC entry.
+ */
+HAL_BOOL
+ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
+                       const HAL_KEYVAL *k, const uint8_t *mac,
+                       int xorKey)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+
+       if (ar5212SetKeyCacheEntry(ah, entry, k, mac, xorKey)) {
+               ahp->ah_keytype[entry] = keyType[k->kv_type];
+               return AH_TRUE;
+       } else
+               return AH_FALSE;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_misc.c      2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_misc.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#ifdef AH_DEBUG
+#include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
+#endif
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/*
+ * Return the wireless modes (a,b,g,t) supported by hardware.
+ *
+ * This value is what is actually supported by the hardware
+ * and is unaffected by regulatory/country code settings.
+ *
+ */
+u_int
+ar5416GetWirelessModes(struct ath_hal *ah)
+{
+       u_int mode;
+
+       mode = ar5212GetWirelessModes(ah);
+       if (mode & HAL_MODE_11A)
+               mode |= HAL_MODE_11NA_HT20
+                    |  HAL_MODE_11NA_HT40PLUS
+                    |  HAL_MODE_11NA_HT40MINUS
+                    ;
+       if (mode & HAL_MODE_11G)
+               mode |= HAL_MODE_11NG_HT20
+                    |  HAL_MODE_11NG_HT40PLUS
+                    |  HAL_MODE_11NG_HT40MINUS
+                    ;
+       return mode;
+}
+
+/*
+ * Change the LED blinking pattern to correspond to the connectivity
+ */
+void
+ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
+{
+       static const uint32_t ledbits[8] = {
+               AR_MAC_LED_ASSOC_NONE,          /* HAL_LED_INIT */
+               AR_MAC_LED_ASSOC_PEND,          /* HAL_LED_SCAN */
+               AR_MAC_LED_ASSOC_PEND,          /* HAL_LED_AUTH */
+               AR_MAC_LED_ASSOC_ACTIVE,        /* HAL_LED_ASSOC*/
+               AR_MAC_LED_ASSOC_ACTIVE,        /* HAL_LED_RUN */
+               AR_MAC_LED_ASSOC_NONE,
+               AR_MAC_LED_ASSOC_NONE,
+               AR_MAC_LED_ASSOC_NONE,
+       };
+       uint32_t bits;
+
+       bits = OS_REG_READ(ah, AR_MAC_LED);
+       bits = (bits &~ AR_MAC_LED_MODE)
+            | SM(AR_MAC_LED_MODE_POWON, AR_MAC_LED_MODE)
+#if 1
+            | SM(AR_MAC_LED_MODE_NETON, AR_MAC_LED_MODE)
+#endif
+            ;
+       bits = (bits &~ AR_MAC_LED_ASSOC)
+            | SM(ledbits[state & 0x7], AR_MAC_LED_ASSOC);
+       OS_REG_WRITE(ah, AR_MAC_LED, bits);
+}
+
+/*
+ * Reset the current hardware tsf for stamlme.
+ */
+void
+ar5416ResetTsf(struct ath_hal *ah)
+{
+       uint32_t v;
+       int i;
+
+       for (i = 0; i < 10; i++) {
+               v = OS_REG_READ(ah, AR_SLP32_MODE);
+               if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
+                       break;
+               OS_DELAY(10);
+       }
+       OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
+}
+
+HAL_BOOL
+ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
+{
+       return AH_TRUE;
+}
+
+/* Setup decompression for given key index */
+HAL_BOOL
+ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
+{
+       return HAL_OK;
+}
+
+/* Setup coverage class */
+void
+ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
+{
+}
+
+/*
+ * Return approximation of extension channel busy over an time interval
+ * 0% (clear) -> 100% (busy)
+ *
+ */
+uint32_t
+ar5416Get11nExtBusy(struct ath_hal *ah)
+{
+    struct ath_hal_5416 *ahp = AH5416(ah);
+    uint32_t busy; /* percentage */
+    uint32_t cycleCount, ctlBusy, extBusy;
+
+    ctlBusy = OS_REG_READ(ah, AR_RCCNT);
+    extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
+    cycleCount = OS_REG_READ(ah, AR_CCCNT);
+
+    if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
+        /*
+         * Cycle counter wrap (or initial call); it's not possible
+         * to accurately calculate a value because the registers
+         * right shift rather than wrap--so punt and return 0.
+         */
+        busy = 0;
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
+           __func__);
+
+    } else {
+        uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
+        uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
+        uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
+        uint32_t ctlClearDelta = 0;
+
+        /* Compute control channel rxclear.
+         * The cycle delta may be less than the control channel delta.
+         * This could be solved by freezing the timers (or an atomic read,
+         * if one was available). Checking for the condition should be
+         * sufficient.
+         */
+        if (cycleDelta > ctlBusyDelta) {
+            ctlClearDelta = cycleDelta - ctlBusyDelta;
+        }
+
+        /* Compute ratio of extension channel busy to control channel clear
+         * as an approximation to extension channel cleanliness.
+         *
+         * According to the hardware folks, ext rxclear is undefined
+         * if the ctrl rxclear is de-asserted (i.e. busy)
+         */
+        if (ctlClearDelta) {
+            busy = (extBusyDelta * 100) / ctlClearDelta;
+        } else {
+            busy = 100;
+        }
+        if (busy > 100) {
+            busy = 100;
+        }
+#if 0
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
+             "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
+             "busy %d\n",
+              __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
+#endif
+    }
+
+    ahp->ah_cycleCount = cycleCount;
+    ahp->ah_ctlBusy = ctlBusy;
+    ahp->ah_extBusy = extBusy;
+
+    return busy;
+}
+
+/*
+ * Configure 20/40 operation
+ *
+ * 20/40 = joint rx clear (control and extension)
+ * 20    = rx clear (control)
+ *
+ * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
+ *         from 20/40 => 20 only
+ */
+void
+ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
+{
+    uint32_t macmode;
+
+    /* Configure MAC for 20/40 operation */
+    if (mode == HAL_HT_MACMODE_2040) {
+        macmode = AR_2040_JOINED_RX_CLEAR;
+    } else {
+        macmode = 0;
+    }
+    OS_REG_WRITE(ah, AR_2040_MODE, macmode);
+}
+
+/*
+ * Get Rx clear (control/extension channel)
+ *
+ * Returns active low (busy) for ctrl/ext channel
+ * Owl 2.0
+ */
+HAL_HT_RXCLEAR
+ar5416Get11nRxClear(struct ath_hal *ah)
+{
+    HAL_HT_RXCLEAR rxclear = 0;
+    uint32_t val;
+
+    val = OS_REG_READ(ah, AR_DIAG_SW);
+
+    /* control channel */
+    if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
+        rxclear |= HAL_RX_CLEAR_CTL_LOW;
+    }
+    /* extension channel */
+    if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
+        rxclear |= HAL_RX_CLEAR_EXT_LOW;
+    }
+    return rxclear;
+}
+
+/*
+ * Set Rx clear (control/extension channel)
+ *
+ * Useful for forcing the channel to appear busy for
+ * debugging/diagnostics
+ * Owl 2.0
+ */
+void
+ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
+{
+    /* control channel */
+    if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
+        OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
+    } else {
+        OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
+    }
+    /* extension channel */
+    if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
+        OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
+    } else {
+        OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
+    }
+}
+
+HAL_STATUS
+ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+        uint32_t capability, uint32_t *result)
+{
+       switch (type) {
+       case HAL_CAP_BB_HANG:
+               switch (capability) {
+               case HAL_BB_HANG_RIFS:
+                       return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP;
+               case HAL_BB_HANG_DFS:
+                       return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP;
+               case HAL_BB_HANG_RX_CLEAR:
+                       return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
+               }
+               break;
+       case HAL_CAP_MAC_HANG:
+               return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
+                   (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
+                   AR_SREV_SOWL(ah)) ?
+                       HAL_OK : HAL_ENOTSUPP;
+       default:
+               break;
+       }
+       return ar5212GetCapability(ah, type, capability, result);
+}
+
+static int ar5416DetectMacHang(struct ath_hal *ah);
+static int ar5416DetectBBHang(struct ath_hal *ah);
+
+HAL_BOOL
+ar5416GetDiagState(struct ath_hal *ah, int request,
+       const void *args, uint32_t argsize,
+       void **result, uint32_t *resultsize)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       int hangs;
+
+       if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
+               return AH_TRUE;
+       switch (request) {
+       case HAL_DIAG_EEPROM:
+               return ath_hal_eepromDiag(ah, request,
+                   args, argsize, result, resultsize);
+       case HAL_DIAG_CHECK_HANGS:
+               if (argsize != sizeof(int))
+                       return AH_FALSE;
+               hangs = *(const int *) args;
+               ahp->ah_hangs = 0;
+               if (hangs & HAL_BB_HANGS)
+                       ahp->ah_hangs |= ar5416DetectBBHang(ah);
+               /* NB: if BB is hung MAC will be hung too so skip check */
+               if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
+                       ahp->ah_hangs |= ar5416DetectMacHang(ah);
+               *result = &ahp->ah_hangs;
+               *resultsize = sizeof(ahp->ah_hangs);
+               return AH_TRUE;
+       }
+       return ar5212GetDiagState(ah, request,
+           args, argsize, result, resultsize);
+}
+
+typedef struct {
+       uint32_t dma_dbg_3;
+       uint32_t dma_dbg_4;
+       uint32_t dma_dbg_5;
+       uint32_t dma_dbg_6;
+} mac_dbg_regs_t;
+
+typedef enum {
+       dcu_chain_state         = 0x1,
+       dcu_complete_state      = 0x2,
+       qcu_state               = 0x4,
+       qcu_fsp_ok              = 0x8,
+       qcu_fsp_state           = 0x10,
+       qcu_stitch_state        = 0x20,
+       qcu_fetch_state         = 0x40,
+       qcu_complete_state      = 0x80
+} hal_mac_hangs_t;
+
+typedef struct {
+       int states;
+       uint8_t dcu_chain_state;
+       uint8_t dcu_complete_state;
+       uint8_t qcu_state;
+       uint8_t qcu_fsp_ok;
+       uint8_t qcu_fsp_state;
+       uint8_t qcu_stitch_state;
+       uint8_t qcu_fetch_state;
+       uint8_t qcu_complete_state;
+} hal_mac_hang_check_t;
+
+static HAL_BOOL
+ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
+    const hal_mac_hang_check_t *check)
+{
+       int found_states;
+
+       found_states = 0;
+       if (check->states & dcu_chain_state) {
+               int i;
+
+               for (i = 0; i < 6; i++) {
+                       if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
+                           check->dcu_chain_state)
+                               found_states |= dcu_chain_state;
+               }
+               for (i = 0; i < 4; i++) {
+                       if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
+                           check->dcu_chain_state)
+                               found_states |= dcu_chain_state;
+               }
+       }
+       if (check->states & dcu_complete_state) {
+               if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
+                       found_states |= dcu_complete_state;
+       }
+       if (check->states & qcu_stitch_state) {
+               if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
+                       found_states |= qcu_stitch_state;
+       }
+       if (check->states & qcu_fetch_state) {
+               if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
+                       found_states |= qcu_fetch_state;
+       }
+       if (check->states & qcu_complete_state) {
+               if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
+                       found_states |= qcu_complete_state;
+       }
+       return (found_states == check->states);
+}
+
+#define NUM_STATUS_READS 50
+
+static int
+ar5416DetectMacHang(struct ath_hal *ah)
+{
+       static const hal_mac_hang_check_t hang_sig1 = {
+               .dcu_chain_state        = 0x6,
+               .dcu_complete_state     = 0x1,
+               .states                 = dcu_chain_state
+                                       | dcu_complete_state,
+       };
+       static const hal_mac_hang_check_t hang_sig2 = {
+               .qcu_stitch_state       = 0x9,
+               .qcu_fetch_state        = 0x8,
+               .qcu_complete_state     = 0x4,
+               .states                 = qcu_stitch_state
+                                       | qcu_fetch_state
+                                       | qcu_complete_state,
+        };
+       mac_dbg_regs_t mac_dbg;
+       int i;
+
+       mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
+       mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
+       mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
+       mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
+       for (i = 1; i <= NUM_STATUS_READS; i++) {
+               if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
+                   mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
+                   mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
+                   mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
+                       return 0;
+       }
+
+       if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
+               return HAL_MAC_HANG_SIG1;
+       if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
+               return HAL_MAC_HANG_SIG2;
+
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown MAC hang signature "
+           "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
+           __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
+           mac_dbg.dma_dbg_6);
+
+       return HAL_MAC_HANG_UNKNOWN;
+}
+
+/*
+ * Determine if the baseband using the Observation Bus Register
+ */
+static int
+ar5416DetectBBHang(struct ath_hal *ah)
+{
+#define N(a) (sizeof(a)/sizeof(a[0]))
+       /*
+        * Check the PCU Observation Bus 1 register (0x806c)
+        * NUM_STATUS_READS times
+        *
+        * 4 known BB hang signatures -
+        * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
+        * [2] bits 8,9 are 1, bit 11 is 0. State machine state
+        *     (bits 25-31) is 0x52
+        * [3] bits 8,9 are 1, bit 11 is 0. State machine state
+        *     (bits 25-31) is 0x18
+        * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
+        *     Rx State (bits 20-24) is 0x7.
+        */
+       static const struct {
+               uint32_t val;
+               uint32_t mask;
+               int code;
+       } hang_list[] = {
+               /* Reg Value   Reg Mask    Hang Code XXX */
+               { 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
+               { 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
+               { 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
+               { 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
+       };
+       uint32_t hang_sig;
+       int i;
+
+       hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
+       for (i = 1; i <= NUM_STATUS_READS; i++) {
+               if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
+                       return 0;
+       }
+       for (i = 0; i < N(hang_list); i++)
+               if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s BB hang, signature 0x%x, code 0x%x\n",
+                           __func__, hang_sig, hang_list[i].code);
+                       return hang_list[i].code;
+               }
+
+       HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown BB hang signature! "
+           "<0x806c>=0x%x\n", __func__, hang_sig);
+
+       return HAL_BB_HANG_UNKNOWN;
+#undef N
+}
+#undef NUM_STATUS_READS
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_phy.c       2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_phy.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+
+/* shorthands to compact tables for readability */
+#define        OFDM    IEEE80211_T_OFDM
+#define        CCK     IEEE80211_T_CCK
+#define HT      IEEE80211_T_HT
+
+HAL_RATE_TABLE ar5416_11ng_table = {
+    28,  /* number of rates */
+    { 0 },
+    {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   1 Mb */ {  AH_TRUE, CCK,     1000,    0x1b,    0x00, (0x80| 2),   0, 0, 0 },
+/*   2 Mb */ {  AH_TRUE, CCK,     2000,    0x1a,    0x04, (0x80| 4),   1, 0, 0 },
+/* 5.5 Mb */ {  AH_TRUE, CCK,     5500,    0x19,    0x04, (0x80|11),   2, 0, 0 },
+/*  11 Mb */ {  AH_TRUE, CCK,    11000,    0x18,    0x04, (0x80|22),   3, 0, 0 },
+/* Remove rates 6, 9 from rate ctrl */
+/*   6 Mb */ { AH_FALSE, OFDM,    6000,    0x0b,    0x00,        12,   4, 0, 0 },
+/*   9 Mb */ { AH_FALSE, OFDM,    9000,    0x0f,    0x00,        18,   4, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,   12000,    0x0a,    0x00,        24,   6, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,   18000,    0x0e,    0x00,        36,   6, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   24000,    0x09,    0x00,        48,   8, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   36000,    0x0d,    0x00,        72,   8, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   48000,    0x08,    0x00,        96,   8, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   54000,    0x0c,    0x00,       108,   8, 0, 0 },
+/* 6.5 Mb */ {  AH_TRUE, HT,      6500,    0x80,    0x00,                0,   8, 0, 0 },
+/*  13 Mb */ {  AH_TRUE, HT,    13000,    0x81,    0x00,         1,   8, 0, 0 },
+/*19.5 Mb */ {  AH_TRUE, HT,     19500,    0x82,    0x00,         2,   8, 0, 0 },
+/*  26 Mb */ {  AH_TRUE, HT,    26000,    0x83,    0x00,         3,   8, 0, 0 },
+/*  39 Mb */ {  AH_TRUE, HT,    39000,    0x84,    0x00,         4,   8, 0, 0 },
+/*  52 Mb */ {  AH_TRUE, HT,            52000,    0x85,    0x00,         5,   8, 0, 0 },
+/*58.5 Mb */ {  AH_TRUE, HT,    58500,    0x86,    0x00,         6,   8, 0, 0 },
+/*  65 Mb */ {  AH_TRUE, HT,    65000,    0x87,    0x00,         7,   8, 0, 0 },
+/*  13 Mb */ {  AH_TRUE, HT,    13000,    0x88,    0x00,         8,   8, 0, 0 },
+/*  26 Mb */ {  AH_TRUE, HT,    26000,    0x89,    0x00,         9,   8, 0, 0 },
+/*  39 Mb */ {  AH_TRUE, HT,    39000,    0x8a,    0x00,        10,   8, 0, 0 },
+/*  52 Mb */ {  AH_TRUE, HT,    52000,    0x8b,    0x00,        11,   8, 0, 0 },
+/*  78 Mb */ {  AH_TRUE, HT,    78000,    0x8c,    0x00,        12,   8, 0, 0 },
+/* 104 Mb */ {  AH_TRUE, HT,   104000,    0x8d,    0x00,        13,   8, 0, 0 },
+/* 117 Mb */ {  AH_TRUE, HT,   117000,    0x8e,    0x00,        14,   8, 0, 0 },
+/* 130 Mb */ {  AH_TRUE, HT,   130000,    0x8f,    0x00,        15,   8, 0, 0 },
+       },
+};
+
+static HAL_RATE_TABLE ar5416_11na_table = {
+    24,  /* number of rates */
+    { 0 },
+    {
+/*                                                 short            ctrl  */
+/*                valid                rateCode Preamble  dot11Rate Rate */
+/*   6 Mb */ {  AH_TRUE, OFDM,    6000,    0x0b,    0x00, (0x80|12),   0, 0, 0 },
+/*   9 Mb */ {  AH_TRUE, OFDM,    9000,    0x0f,    0x00,        18,   0, 0, 0 },
+/*  12 Mb */ {  AH_TRUE, OFDM,   12000,    0x0a,    0x00, (0x80|24),   2, 0, 0 },
+/*  18 Mb */ {  AH_TRUE, OFDM,   18000,    0x0e,    0x00,        36,   2, 0, 0 },
+/*  24 Mb */ {  AH_TRUE, OFDM,   24000,    0x09,    0x00, (0x80|48),   4, 0, 0 },
+/*  36 Mb */ {  AH_TRUE, OFDM,   36000,    0x0d,    0x00,        72,   8, 0, 0 },
+/*  48 Mb */ {  AH_TRUE, OFDM,   48000,    0x08,    0x00,        96,   8, 0, 0 },
+/*  54 Mb */ {  AH_TRUE, OFDM,   54000,    0x0c,    0x00,       108,   8, 0, 0 },
+/* 6.5 Mb */ {  AH_TRUE, HT,      6500,    0x80,    0x00,         0,   8, 0, 0 },
+/*  13 Mb */ {  AH_TRUE, HT,    13000,    0x81,    0x00,         1,   8, 0, 0 },
+/*19.5 Mb */ {  AH_TRUE, HT,     19500,    0x82,    0x00,         2,   8, 0, 0 },
+/*  26 Mb */ {  AH_TRUE, HT,    26000,    0x83,    0x00,         3,   8, 0, 0 },
+/*  39 Mb */ {  AH_TRUE, HT,    39000,    0x84,    0x00,         4,   8, 0, 0 },
+/*  52 Mb */ {  AH_TRUE, HT,            52000,    0x85,    0x00,         5,   8, 0, 0 },
+/*58.5 Mb */ {  AH_TRUE, HT,    58500,    0x86,    0x00,         6,   8, 0, 0 },
+/*  65 Mb */ {  AH_TRUE, HT,    65000,    0x87,    0x00,         7,   8, 0, 0 },
+/*  13 Mb */ {  AH_TRUE, HT,    13000,    0x88,    0x00,         8,   8, 0, 0 },
+/*  26 Mb */ {  AH_TRUE, HT,    26000,    0x89,    0x00,         9,   8, 0, 0 },
+/*  39 Mb */ {  AH_TRUE, HT,    39000,    0x8a,    0x00,        10,   8, 0, 0 },
+/*  52 Mb */ {  AH_TRUE, HT,    52000,    0x8b,    0x00,        11,   8, 0, 0 },
+/*  78 Mb */ {  AH_TRUE, HT,    78000,    0x8c,    0x00,        12,   8, 0, 0 },
+/* 104 Mb */ {  AH_TRUE, HT,   104000,    0x8d,    0x00,        13,   8, 0, 0 },
+/* 117 Mb */ {  AH_TRUE, HT,   117000,    0x8e,    0x00,        14,   8, 0, 0 },
+/* 130 Mb */ {  AH_TRUE, HT,   130000,    0x8f,    0x00,        15,   8, 0, 0 },
+       },
+};
+
+#undef OFDM
+#undef CCK
+#undef HT
+
+const HAL_RATE_TABLE *
+ar5416GetRateTable(struct ath_hal *ah, u_int mode)
+{
+       HAL_RATE_TABLE *rt;
+       switch (mode) {
+       case HAL_MODE_11NG_HT20:
+       case HAL_MODE_11NG_HT40PLUS:
+       case HAL_MODE_11NG_HT40MINUS:
+               rt = &ar5416_11ng_table;
+               break;
+       case HAL_MODE_11NA_HT20:
+       case HAL_MODE_11NA_HT40PLUS:
+       case HAL_MODE_11NA_HT40MINUS:
+               rt = &ar5416_11na_table;
+               break;
+       default:
+               return ar5212GetRateTable(ah, mode);
+       }
+       ath_hal_setupratetable(ah, rt);
+       return rt;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_power.c     2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_power.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+
+/*
+ * Notify Power Mgt is enabled in self-generated frames.
+ * If requested, force chip awake.
+ *
+ * Returns A_OK if chip is awake or successfully forced awake.
+ *
+ * WARNING WARNING WARNING
+ * There is a problem with the chip where sometimes it will not wake up.
+ */
+static HAL_BOOL
+ar5416SetPowerModeAwake(struct ath_hal *ah, int setChip)
+{
+#define        POWER_UP_TIME   200000
+       uint32_t val;
+       int i = 0;
+
+       if (setChip) {
+               /*
+                * Do a Power-On-Reset if OWL is shutdown
+                * the NetBSD driver  power-cycles the Cardbus slot
+                * as part of the reset procedure.
+                */
+               if ((OS_REG_READ(ah, AR_RTC_STATUS)
+                       & AR_RTC_PM_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
+                       if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON))
+                               goto bad;
+               }
+
+               OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+               OS_DELAY(50);   /* Give chip the chance to awake */
+
+               for (i = POWER_UP_TIME / 50; i != 0; i--) {
+                       val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
+                       if (val == AR_RTC_STATUS_ON)
+                               break;
+                       OS_DELAY(50);
+                       OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+               }
+       bad:
+               if (i == 0) {
+#ifdef AH_DEBUG
+                       ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n",
+                               __func__, POWER_UP_TIME/1000);
+#endif
+                       return AH_FALSE;
+               }
+       }
+
+       OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       return AH_TRUE;
+#undef POWER_UP_TIME
+}
+
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
+static void
+ar5416SetPowerModeSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       if (setChip) {
+               /* Clear the RTC force wake bit to allow the mac to sleep */
+               OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+               OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF);
+               /* Shutdown chip. Active low */
+               OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
+       }
+}
+
+/*
+ * Notify Power Management is enabled in self-generating
+ * fames.  If request, set power mode of chip to
+ * auto/normal.  Duration in units of 128us (1/8 TU).
+ */
+static void
+ar5416SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
+{
+       OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+       if (setChip)
+               OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+}
+
+/*
+ * Set power mgt to the requested mode, and conditionally set
+ * the chip as well
+ */
+HAL_BOOL
+ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+#ifdef AH_DEBUG
+       static const char* modes[] = {
+               "AWAKE",
+               "FULL-SLEEP",
+               "NETWORK SLEEP",
+               "UNDEFINED"
+       };
+#endif
+       int status = AH_TRUE;
+       if (!setChip)
+               return AH_TRUE;
+
+       HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
+           modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : "");
+       switch (mode) {
+       case HAL_PM_AWAKE:
+               status = ar5416SetPowerModeAwake(ah, setChip);
+               break;
+       case HAL_PM_FULL_SLEEP:
+               ar5416SetPowerModeSleep(ah, setChip);
+               break;
+       case HAL_PM_NETWORK_SLEEP:
+               ar5416SetPowerModeNetworkSleep(ah, setChip);
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode 0x%x\n",
+                   __func__, mode);
+               return AH_FALSE;
+       }
+       ahp->ah_powerMode = mode;
+       return status;
+}
+
+/*
+ * Return the current sleep mode of the chip
+ */
+HAL_POWER_MODE
+ar5416GetPowerMode(struct ath_hal *ah)
+{
+       int mode = OS_REG_READ(ah, AR_RTC_STATUS);
+       switch (mode & AR_RTC_PM_STATUS_M) {
+       case AR_RTC_STATUS_ON:
+       case AR_RTC_STATUS_WAKEUP:
+               return HAL_PM_AWAKE;
+       case AR_RTC_STATUS_SLEEP:
+               return HAL_PM_NETWORK_SLEEP;
+       case AR_RTC_STATUS_SHUTDOWN:
+               return HAL_PM_FULL_SLEEP;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: unknown power mode, RTC_STATUS 0x%x\n",
+                   __func__, mode);
+               return HAL_PM_UNDEFINED;
+       }
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_recv.c      2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_recv.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_desc.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416desc.h"
+
+/*
+ * Start receive at the PCU engine
+ */
+void
+ar5416StartPcuReceive(struct ath_hal *ah)
+{
+       struct ath_hal_private *ahp = AH_PRIVATE(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_RX, "%s: Start PCU Receive \n", __func__);
+       ar5212EnableMibCounters(ah);
+       /* NB: restore current settings */
+       ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE);
+       /*
+        * NB: must do after enabling phy errors to avoid rx
+        *     frames w/ corrupted descriptor status.
+        */
+       OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
+}
+
+/*
+ * Stop receive at the PCU engine
+ * and abort current frame in PCU
+ */
+void
+ar5416StopPcuReceive(struct ath_hal *ah)
+{
+       OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
+
+       HALDEBUG(ah, HAL_DEBUG_RX, "%s: Stop PCU Receive \n", __func__);
+       ar5212DisableMibCounters(ah);
+}
+
+/*
+ * Initialize RX descriptor, by clearing the status and setting
+ * the size (and any other flags).
+ */
+HAL_BOOL
+ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+    uint32_t size, u_int flags)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       HALASSERT((size &~ AR_BufLen) == 0);
+
+       ads->ds_ctl1 = size & AR_BufLen;
+       if (flags & HAL_RXDESC_INTREQ)
+               ads->ds_ctl1 |= AR_RxIntrReq;
+
+       /* this should be enough */
+       ads->ds_rxstatus8 &= ~AR_RxDone;
+
+       return AH_TRUE;
+}
+
+/*
+ * Process an RX descriptor, and return the status to the caller.
+ * Copy some hardware specific items into the software portion
+ * of the descriptor.
+ *
+ * NB: the caller is responsible for validating the memory contents
+ *     of the descriptor (e.g. flushing any cached copy).
+ */
+HAL_STATUS
+ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,
+    uint32_t pa, struct ath_desc *nds, uint64_t tsf,
+    struct ath_rx_status *rs)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       struct ar5416_desc *ands = AR5416DESC(nds);
+
+       if ((ads->ds_rxstatus8 & AR_RxDone) == 0)
+               return HAL_EINPROGRESS;
+       /*
+        * Given the use of a self-linked tail be very sure that the hw is
+        * done with this descriptor; the hw may have done this descriptor
+        * once and picked it up again...make sure the hw has moved on.
+        */
+       if ((ands->ds_rxstatus8 & AR_RxDone) == 0
+           && OS_REG_READ(ah, AR_RXDP) == pa)
+               return HAL_EINPROGRESS;
+
+       rs->rs_status = 0;
+       rs->rs_flags = 0;
+
+       rs->rs_datalen = ads->ds_rxstatus1 & AR_DataLen;
+       rs->rs_tstamp =  ads->AR_RcvTimestamp;
+
+       /* XXX what about KeyCacheMiss? */
+
+       rs->rs_rssi = MS(ads->ds_rxstatus4, AR_RxRSSICombined);
+       rs->rs_rssi_ctl[0] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt00);
+       rs->rs_rssi_ctl[1] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt01);
+       rs->rs_rssi_ctl[2] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt02);
+       rs->rs_rssi_ext[0] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt10);
+       rs->rs_rssi_ext[1] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt11);
+       rs->rs_rssi_ext[2] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt12);
+
+       if (ads->ds_rxstatus8 & AR_RxKeyIdxValid)
+               rs->rs_keyix = MS(ads->ds_rxstatus8, AR_KeyIdx);
+       else
+               rs->rs_keyix = HAL_RXKEYIX_INVALID;
+
+       /* NB: caller expected to do rate table mapping */
+       rs->rs_rate = RXSTATUS_RATE(ah, ads);
+       rs->rs_more = (ads->ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+
+       rs->rs_isaggr = (ads->ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+       rs->rs_moreaggr = (ads->ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
+       rs->rs_antenna = MS(ads->ds_rxstatus3, AR_RxAntenna);
+
+       if (ads->ds_rxstatus3 & AR_GI)
+               rs->rs_flags |= HAL_RX_GI;
+       if (ads->ds_rxstatus3 & AR_2040)
+               rs->rs_flags |= HAL_RX_2040;
+
+       if (ads->ds_rxstatus8 & AR_PreDelimCRCErr)
+               rs->rs_flags |= HAL_RX_DELIM_CRC_PRE;
+       if (ads->ds_rxstatus8 & AR_PostDelimCRCErr)
+               rs->rs_flags |= HAL_RX_DELIM_CRC_POST;
+       if (ads->ds_rxstatus8 & AR_DecryptBusyErr)
+               rs->rs_flags |= HAL_RX_DECRYPT_BUSY;
+       if (ads->ds_rxstatus8 & AR_HiRxChain)
+               rs->rs_flags |= HAL_RX_HI_RX_CHAIN;
+
+       if ((ads->ds_rxstatus8 & AR_RxFrameOK) == 0) {
+               /*
+                * These four bits should not be set together.  The
+                * 5416 spec states a Michael error can only occur if
+                * DecryptCRCErr not set (and TKIP is used).  Experience
+                * indicates however that you can also get Michael errors
+                * when a CRC error is detected, but these are specious.
+                * Consequently we filter them out here so we don't
+                * confuse and/or complicate drivers.
+                */
+               if (ads->ds_rxstatus8 & AR_CRCErr)
+                       rs->rs_status |= HAL_RXERR_CRC;
+               else if (ads->ds_rxstatus8 & AR_PHYErr) {
+                       u_int phyerr;
+
+                       rs->rs_status |= HAL_RXERR_PHY;
+                       phyerr = MS(ads->ds_rxstatus8, AR_PHYErrCode);
+                       rs->rs_phyerr = phyerr;
+               } else if (ads->ds_rxstatus8 & AR_DecryptCRCErr)
+                       rs->rs_status |= HAL_RXERR_DECRYPT;
+               else if (ads->ds_rxstatus8 & AR_MichaelErr)
+                       rs->rs_status |= HAL_RXERR_MIC;
+       }
+
+       return HAL_OK;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_reset.c     2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,2895 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_reset.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+#ifdef AH_SUPPORT_AR9280
+#include "ar5416/ar9280.h"
+#endif
+
+/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */
+#define        EEP_MINOR(_ah) \
+       (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK)
+#define IS_EEP_MINOR_V2(_ah)   (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2)
+#define IS_EEP_MINOR_V3(_ah)   (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3)
+
+/* Additional Time delay to wait after activiting the Base band */
+#define BASE_ACTIVATE_DELAY    100     /* 100 usec */
+#define PLL_SETTLE_DELAY       300     /* 300 usec */
+#define RTC_PLL_SETTLE_DELAY    1000    /* 1 ms     */
+
+static void ar5416InitDMA(struct ath_hal *ah);
+static void ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan);
+static void ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode);
+static void ar5416InitQoS(struct ath_hal *ah);
+static void ar5416InitUserSettings(struct ath_hal *ah);
+
+static HAL_BOOL ar5416SetTransmitPower(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain);
+
+#if 0
+static HAL_BOOL        ar5416ChannelChange(struct ath_hal *, HAL_CHANNEL *);
+#endif
+static void ar5416SetDeltaSlope(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+static void ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan);
+#ifdef AH_SUPPORT_AR9280
+static void ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan);
+#endif
+
+static HAL_BOOL ar5416SetResetPowerOn(struct ath_hal *ah);
+static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type);
+static void ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan);
+static HAL_BOOL ar5416SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah,
+       struct ar5416eeprom *pEepData,
+       HAL_CHANNEL_INTERNAL *chan, int16_t *ratesArray,
+       uint16_t cfgCtl, uint16_t AntennaReduction,
+       uint16_t twiceMaxRegulatoryPower,
+       uint16_t powerLimit);
+static HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah,
+       struct ar5416eeprom *pEepData,
+       HAL_CHANNEL_INTERNAL *chan,
+       int16_t *pTxPowerIndexOffset);
+static uint16_t ar5416GetMaxEdgePower(uint16_t freq,
+       CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz);
+static void ar5416GetTargetPowers(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_HT *powInfo,
+       uint16_t numChannels, CAL_TARGET_POWER_HT *pNewPower,
+       uint16_t numRates, HAL_BOOL isHt40Target);
+static void ar5416GetTargetPowersLeg(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_LEG *powInfo,
+       uint16_t numChannels, CAL_TARGET_POWER_LEG *pNewPower,
+       uint16_t numRates, HAL_BOOL isExtTarget);
+
+static int16_t interpolate(uint16_t target, uint16_t srcLeft,
+       uint16_t srcRight, int16_t targetLeft, int16_t targetRight);
+static void ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan);
+static void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet,
+       uint8_t * bChans, uint16_t availPiers,
+       uint16_t tPdGainOverlap, int16_t *pMinCalPower,
+       uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues,
+       uint16_t numXpdGains);
+static HAL_BOOL getLowerUpperIndex(uint8_t target, uint8_t *pList,
+       uint16_t listSize,  uint16_t *indexL, uint16_t *indexR);
+static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax,
+       uint8_t *pPwrList, uint8_t *pVpdList,
+       uint16_t numIntercepts, uint8_t *pRetVpdList);
+
+/*
+ * Places the device in and out of reset and then places sane
+ * values in the registers based on EEPROM config, initialization
+ * vectors (as determined by the mode), and station configuration
+ *
+ * bChannelChange is used to preserve DMA/PCU registers across
+ * a HW Reset during channel change.
+ */
+HAL_BOOL
+ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
+       HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
+{
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+#define        FAIL(_code)     do { ecode = _code; goto bad; } while (0)
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *ichan;
+       uint32_t softLedCfg;
+       uint32_t saveDefAntenna, saveLedState;
+       uint32_t macStaId1;
+       uint16_t rfXpdGain[2];
+       u_int modesIndex, freqIndex;
+       HAL_STATUS ecode;
+       int i, regWrites = 0;
+       uint32_t powerVal, rssiThrReg;
+       uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow;
+
+       OS_MARK(ah, AH_MARK_RESET, bChannelChange);
+#define        IS(_c,_f)       (((_c)->channelFlags & _f) || 0)
+       if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+       if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+#undef IS
+
+       /* Bring out of sleep mode */
+       if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n",
+                   __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_RESET,
+                   "%s: Ch=%u Max=%d Min=%d\n",__func__,
+                   ichan->channel, ichan->maxTxPower, ichan->minTxPower);
+       }
+       switch (opmode) {
+       case HAL_M_STA:
+       case HAL_M_IBSS:
+       case HAL_M_HOSTAP:
+       case HAL_M_MONITOR:
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
+                   __func__, opmode);
+               FAIL(HAL_EINVAL);
+               break;
+       }
+       HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
+
+       /* XXX Turn on fast channel change for 5416 */
+       /*
+        * Preserve the bmiss rssi threshold and count threshold
+        * across resets
+        */
+       rssiThrReg = OS_REG_READ(ah, AR_RSSI_THR);
+       /* If reg is zero, first time thru set to default val */
+       if (rssiThrReg == 0)
+               rssiThrReg = INIT_RSSI_THR;
+
+       /*
+        * Preserve the antenna on a channel change
+        */
+       saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
+       if (saveDefAntenna == 0)                /* XXX magic constants */
+               saveDefAntenna = 1;
+
+       /* Save hardware flag before chip reset clears the register */
+       macStaId1 = OS_REG_READ(ah, AR_STA_ID1) &
+               (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);
+
+       /* Save led state from pci config register */
+       saveLedState = OS_REG_READ(ah, AR_MAC_LED) &
+               (AR_MAC_LED_ASSOC | AR_MAC_LED_MODE |
+                AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW);
+       softLedCfg = OS_REG_READ(ah, AR_GPIO_INTR_OUT);
+
+       /*
+        * Adjust gain parameters before reset if
+        * there's an outstanding gain updated.
+        */
+       (void) ar5416GetRfgain(ah);
+
+       if (!ar5416ChipReset(ah, chan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Restore bmiss rssi & count thresholds */
+       OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg);
+
+       /* Setup the indices for the next set of register array writes */
+       /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
+       switch (chan->channelFlags & CHANNEL_ALL) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+                modesIndex = 1;
+                freqIndex  = 1;
+               break;
+       case CHANNEL_T:
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+                modesIndex = 2;
+                freqIndex  = 1;
+               break;
+       case CHANNEL_PUREG:
+       case CHANNEL_G_HT20:
+       case CHANNEL_B: /* treat as channel G , no  B mode suport in owl */
+               modesIndex = 4;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               modesIndex = 3;
+               freqIndex  = 2;
+               break;
+       case CHANNEL_108G:
+               modesIndex = 5;
+               freqIndex  = 2;
+               break;
+       default:
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
+                   __func__, chan->channelFlags);
+               FAIL(HAL_EINVAL);
+       }
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       /* Set correct Baseband to analog shift setting to access analog chips. */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+        /*
+        * Write addac shifts
+        */
+       OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+#if 0
+       /* NB: only required for Sowl */
+       ar5416EepromSetAddac(ah, ichan);
+#endif
+       regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1,
+           regWrites);
+       OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+       /* XXX Merlin ini fixups */
+       /* XXX Merlin 100us delay for shift registers */
+       regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex,
+           regWrites);
+#ifdef AH_SUPPORT_AR9280
+       if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
+               regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain,
+                   modesIndex, regWrites);
+               regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain,
+                   modesIndex, regWrites);
+       }
+#endif
+       /* XXX Merlin 100us delay for shift registers */
+       regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_common, 1, regWrites);
+       /* Setup 11n MAC/Phy mode registers */
+       ar5416Set11nRegs(ah,chan);
+       /* XXX updated regWrites? */
+       ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
+#ifdef AH_SUPPORT_AR9280
+       if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
+               /* 5GHz channels w/ Fast Clock use different modal values */
+               regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes,
+                   modesIndex, regWrites);
+       }
+#endif
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n",
+               __func__, OS_REG_READ(ah,AR_PHY_DAG_CTRLCCK));
+       HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n",
+               __func__, OS_REG_READ(ah,AR_PHY_ADC_CTL));
+
+       /* Set the mute mask to the correct default */
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2)
+               OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
+
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
+               /* Clear reg to alllow RX_CLEAR line debug */
+               OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
+       }
+       if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
+#ifdef notyet
+               /* Enable burst prefetch for the data queues */
+               OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
+               /* Enable double-buffering */
+               OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
+#endif
+       }
+
+       /* Set ADC/DAC select values */
+       OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
+
+       if (AH5416(ah)->ah_rx_chainmask == 0x5 ||
+           AH5416(ah)->ah_tx_chainmask == 0x5)
+               OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN);
+       /* Setup Chain Masks */
+       OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, AH5416(ah)->ah_rx_chainmask);
+       OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, AH5416(ah)->ah_rx_chainmask);
+       OS_REG_WRITE(ah, AR_SELFGEN_MASK, AH5416(ah)->ah_tx_chainmask);
+
+       /* Setup the transmit power values. */
+       if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Write the analog registers */
+       if (!ahp->ah_rfHal->setRfRegs(ah, ichan, freqIndex, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: ar5212SetRfRegs failed\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
+       if (IS_CHAN_OFDM(chan)|| IS_CHAN_HT(chan))
+               ar5416SetDeltaSlope(ah, ichan);
+
+#ifdef AH_SUPPORT_AR9280
+       if (AR_SREV_MERLIN_10_OR_LATER(ah))
+               ar9280SpurMitigate(ah, ichan);
+       else
+#endif
+               ar5416SpurMitigate(ah, ichan);
+
+       /* Setup board specific options for EEPROM version 3 */
+       if (!ar5416SetBoardValues(ah, ichan)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error setting board options\n", __func__);
+               FAIL(HAL_EIO);
+       }
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
+       OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
+               | macStaId1
+               | AR_STA_ID1_RTS_USE_DEF
+               | ahp->ah_staId1Defaults
+       );
+       ar5212SetOperatingMode(ah, opmode);
+
+       /* Set Venice BSSID mask according to current state */
+       OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
+       OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
+
+       /* Restore previous led state */
+       OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | saveLedState);
+       /* Restore soft Led state to GPIO */
+       OS_REG_WRITE(ah, AR_GPIO_INTR_OUT, softLedCfg);
+
+       /* Restore previous antenna */
+       OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+
+       /* then our BSSID */
+       OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
+       OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
+
+       /* Restore bmiss rssi & count thresholds */
+       OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
+
+       OS_REG_WRITE(ah, AR_ISR, ~0);           /* cleared on write */
+
+       if (!ar5212SetChannel(ah, ichan))
+               FAIL(HAL_EIO);
+
+       OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
+
+       /* Set 1:1 QCU to DCU mapping for all queues */
+       for (i = 0; i < AR_NUM_DCU; i++)
+               OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+       ahp->ah_intrTxqs = 0;
+       for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
+               ar5212ResetTxQueue(ah, i);
+
+       ar5416InitIMR(ah, opmode);
+       ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
+       ar5416InitQoS(ah);
+       ar5416InitUserSettings(ah);
+
+       /*
+        * disable seq number generation in hw
+        */
+        OS_REG_WRITE(ah, AR_STA_ID1,
+            OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
+
+       ar5416InitDMA(ah);
+
+       /*
+        * program OBS bus to see MAC interrupts
+        */
+       OS_REG_WRITE(ah, AR_OBS, 8);
+
+#ifdef AR5416_INT_MITIGATION
+       OS_REG_WRITE(ah, AR_MIRT, 0);
+       OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
+       OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
+#endif
+
+       ar5416InitBB(ah, chan);
+
+       /* Setup compression registers */
+       ar5212SetCompRegs(ah);          /* XXX not needed? */
+
+       /*
+        * 5416 baseband will check the per rate power table
+        * and select the lower of the two
+        */
+       ackTpcPow = 63;
+       ctsTpcPow = 63;
+       chirpTpcPow = 63;
+       powerVal = SM(ackTpcPow, AR_TPC_ACK) |
+               SM(ctsTpcPow, AR_TPC_CTS) |
+               SM(chirpTpcPow, AR_TPC_CHIRP);
+       OS_REG_WRITE(ah, AR_TPC, powerVal);
+
+       if (!ar5416InitCal(ah, chan))
+               FAIL(HAL_ESELFTEST);
+
+       AH_PRIVATE(ah)->ah_opmode = opmode;     /* record operating mode */
+
+       if (bChannelChange) {
+               if (!(ichan->privFlags & CHANNEL_DFS))
+                       ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+               chan->channelFlags = ichan->channelFlags;
+               chan->privFlags = ichan->privFlags;
+               chan->maxRegTxPower = ichan->maxRegTxPower;
+               chan->maxTxPower = ichan->maxTxPower;
+               chan->minTxPower = ichan->minTxPower;
+       }
+
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
+
+       OS_MARK(ah, AH_MARK_RESET_DONE, 0);
+
+       return AH_TRUE;
+bad:
+       OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
+       if (*status)
+               *status = ecode;
+       return AH_FALSE;
+#undef FAIL
+#undef N
+}
+
+#if 0
+/*
+ * This channel change evaluates whether the selected hardware can
+ * perform a synthesizer-only channel change (no reset).  If the
+ * TX is not stopped, or the RFBus cannot be granted in the given
+ * time, the function returns false as a reset is necessary
+ */
+HAL_BOOL
+ar5416ChannelChange(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t       ulCount;
+       uint32_t   data, synthDelay, qnum;
+       uint16_t   rfXpdGain[4];
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       /*
+        * Map public channel to private.
+        */
+       ichan = ath_hal_checkchannel(ah, chan);
+
+       /* TX must be stopped or RF Bus grant will not work */
+       for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) {
+               if (ar5212NumTxPending(ah, qnum)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: frames pending on queue %d\n", __func__, qnum);
+                       return AH_FALSE;
+               }
+       }
+
+       /*
+        * Kill last Baseband Rx Frame - Request analog bus grant
+        */
+       OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST);
+       if (!ath_hal_wait(ah, AR_PHY_RFBUS_GNT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: could not kill baseband rx\n",
+                   __func__);
+               return AH_FALSE;
+       }
+
+       ar5416Set11nRegs(ah, chan);     /* NB: setup 5416-specific regs */
+
+       /* Change the synth */
+       if (!ar5212SetChannel(ah, ichan))
+               return AH_FALSE;
+
+       /* Setup the transmit power values. */
+       if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error init'ing transmit power\n", __func__);
+               return AH_FALSE;
+       }
+
+       /*
+        * Wait for the frequency synth to settle (synth goes on
+        * via PHY_ACTIVE_EN).  Read the phy active delay register.
+        * Value is in 100ns increments.
+        */
+       data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_CCK(ichan)) {
+               synthDelay = (4 * data) / 22;
+       } else {
+               synthDelay = data / 10;
+       }
+
+       OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
+
+       /* Release the RFBus Grant */
+       OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+
+       /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
+       if (IS_CHAN_OFDM(ichan)|| IS_CHAN_HT(chan)) {
+               if (ahp->ah_eeprom.ee_version >= AR_EEPROM_VER5_3 &&
+                   !IS_CHAN_B(chan))
+                       ar5212SetSpurMitigation(ah, ichan);
+               ar5416SetDeltaSlope(ah, ichan);
+       }
+
+       /* XXX spur mitigation for Melin */
+
+       /* Copy over internal channel flags to public hal channel */
+
+       if (!(ichan->privFlags & CHANNEL_DFS))
+               ichan->privFlags &= ~CHANNEL_INTERFERENCE;
+       chan->channelFlags = ichan->channelFlags;
+       chan->privFlags = ichan->privFlags;
+       chan->maxRegTxPower = ichan->maxRegTxPower;
+       chan->maxTxPower = ichan->maxTxPower;
+       chan->minTxPower = ichan->minTxPower;
+       AH_PRIVATE(ah)->ah_curchan->ah_channel_time=0;
+       AH_PRIVATE(ah)->ah_curchan->ah_tsf_last = ar5212GetTsf64(ah);
+       ar5212TxEnable(ah,AH_TRUE);
+       return AH_TRUE;
+}
+#endif
+
+static void
+ar5416InitDMA(struct ath_hal *ah)
+{
+
+       /*
+        * set AHB_MODE not to do cacheline prefetches
+        */
+       OS_REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN);
+
+       /*
+        * let mac dma reads be in 128 byte chunks
+        */
+       OS_REG_WRITE(ah, AR_TXCFG,
+               (OS_REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK) | AR_TXCFG_DMASZ_128B);
+
+       /*
+        * let mac dma writes be in 128 byte chunks
+        */
+       OS_REG_WRITE(ah, AR_RXCFG,
+               (OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK) | AR_RXCFG_DMASZ_128B);
+
+       /* XXX restore TX trigger level */
+
+       /*
+        * Setup receive FIFO threshold to hold off TX activities
+        */
+       OS_REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
+
+       /*
+        * reduce the number of usable entries in PCU TXBUF to avoid
+        * wrap around.
+        */
+       OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+}
+
+static void
+ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t synthDelay;
+
+       /*
+        * Wait for the frequency synth to settle (synth goes on
+        * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
+        * Value is in 100ns increments.
+         */
+       synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+       if (IS_CHAN_CCK(chan)) {
+               synthDelay = (4 * synthDelay) / 22;
+       } else {
+               synthDelay /= 10;
+       }
+
+       /* Turn on PLL on 5416 */
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s %s channel\n",
+           __func__, IS_CHAN_5GHZ(chan) ? "5GHz" : "2GHz");
+       ar5416InitPLL(ah, chan);
+
+       /* Activate the PHY (includes baseband activate and synthesizer on) */
+       OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+       /*
+        * If the AP starts the calibration before the base band timeout
+        * completes  we could get rx_clear false triggering.  Add an
+        * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
+        * does not happen.
+        */
+       if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+               OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
+       } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+               OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
+       } else {
+               OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
+       }
+}
+
+static void
+ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       /*
+        * Setup interrupt handling.  Note that ar5212ResetTxQueue
+        * manipulates the secondary IMR's as queues are enabled
+        * and disabled.  This is done with RMW ops to insure the
+        * settings we make here are preserved.
+        */
+        ahp->ah_maskReg = AR_IMR_TXERR | AR_IMR_TXURN
+                       | AR_IMR_RXERR | AR_IMR_RXORN
+                        | AR_IMR_BCNMISC;
+
+#ifdef AR5416_INT_MITIGATION
+               ahp->ah_maskReg |= AR_IMR_TXINTM | AR_IMR_RXINTM
+                       |  AR_IMR_TXMINTR | AR_IMR_RXMINTR;
+#else
+        ahp->ah_maskReg |= AR_IMR_TXOK | AR_IMR_RXOK;
+#endif
+       if (opmode == HAL_M_HOSTAP)
+               ahp->ah_maskReg |= AR_IMR_MIB;
+       OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
+       /* Enable bus errors that are OR'd to set the HIUERR bit */
+
+#if 0
+       OS_REG_WRITE(ah, AR_IMR_S2,
+               OS_REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT | AR_IMR_S2_CST);
+#endif
+}
+
+static void
+ar5416InitQoS(struct ath_hal *ah)
+{
+       /* QoS support */
+       OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);      /* XXX magic */
+       OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);        /* XXX magic */
+
+       /* Turn on NOACK Support for QoS packets */
+       OS_REG_WRITE(ah, AR_NOACK,
+               SM(2, AR_NOACK_2BIT_VALUE) |
+               SM(5, AR_NOACK_BIT_OFFSET) |
+               SM(0, AR_NOACK_BYTE_OFFSET));
+
+       /*
+        * initialize TXOP for all TIDs
+        */
+       OS_REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
+       OS_REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
+       OS_REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
+       OS_REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
+       OS_REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
+}
+
+static void
+ar5416InitUserSettings(struct ath_hal *ah)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       /* Restore user-specified settings */
+       if (ahp->ah_miscMode != 0)
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+       if (ahp->ah_sifstime != (u_int) -1)
+               ar5212SetSifsTime(ah, ahp->ah_sifstime);
+       if (ahp->ah_slottime != (u_int) -1)
+               ar5212SetSlotTime(ah, ahp->ah_slottime);
+       if (ahp->ah_acktimeout != (u_int) -1)
+               ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
+       if (ahp->ah_ctstimeout != (u_int) -1)
+               ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
+       if (AH_PRIVATE(ah)->ah_diagreg != 0)
+               OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
+#if 0 /* XXX Todo */
+       if (ahp->ah_globaltxtimeout != (u_int) -1)
+               ar5416SetGlobalTxTimeout(ah, ahp->ah_globaltxtimeout);
+#endif
+}
+
+/*
+ * Places the hardware into reset and then pulls it out of reset
+ */
+HAL_BOOL
+ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t rfMode = 0;
+
+       OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0);
+       /*
+        * Warm reset is optimistic.
+        */
+       if (AR_SREV_MERLIN_20_OR_LATER(ah) &&
+           ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) {
+               if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON))
+                       return AH_FALSE;
+       } else {
+               if (!ar5416SetResetReg(ah, HAL_RESET_WARM))
+                       return AH_FALSE;
+       }
+
+       /* Bring out of sleep mode (AGAIN) */
+       if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+              return AH_FALSE;
+
+       ar5416InitPLL(ah, chan);
+
+       /*
+        * Perform warm reset before the mode/PLL/turbo registers
+        * are changed in order to deactivate the radio.  Mode changes
+        * with an active radio can result in corrupted shifts to the
+        * radio device.
+        */
+       if (chan != AH_NULL) {
+               /* treat channel B as channel G , no  B mode suport in owl */
+               rfMode |= (IS_CHAN_G(chan) || IS_CHAN_B(chan)) ?
+                       AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+               if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
+                       /* phy mode bits for 5GHz channels require Fast Clock */
+                       rfMode |= AR_PHY_MODE_DYNAMIC
+                              |  AR_PHY_MODE_DYN_CCK_DISABLE;
+               } else if (!AR_SREV_MERLIN_10_OR_LATER(ah)) {
+                       rfMode |= (IS_CHAN_5GHZ(chan)) ?
+                               AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
+               }
+               OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Delta slope coefficient computation.
+ * Required for OFDM operation.
+ */
+static void
+ar5416GetDeltaSlopeValues(struct ath_hal *ah, uint32_t coef_scaled,
+                          uint32_t *coef_mantissa, uint32_t *coef_exponent)
+{
+#define COEF_SCALE_S 24
+    uint32_t coef_exp, coef_man;
+    /*
+     * ALGO -> coef_exp = 14-floor(log2(coef));
+     * floor(log2(x)) is the highest set bit position
+     */
+    for (coef_exp = 31; coef_exp > 0; coef_exp--)
+            if ((coef_scaled >> coef_exp) & 0x1)
+                    break;
+    /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */
+    HALASSERT(coef_exp);
+    coef_exp = 14 - (coef_exp - COEF_SCALE_S);
+
+    /*
+     * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5);
+     * The coefficient is already shifted up for scaling
+     */
+    coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
+
+    *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
+    *coef_exponent = coef_exp - 16;
+
+#undef COEF_SCALE_S
+}
+
+void
+ar5416SetDeltaSlope(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+#define INIT_CLOCKMHZSCALED    0x64000000
+       uint32_t coef_scaled, ds_coef_exp, ds_coef_man;
+       uint32_t clockMhzScaled = INIT_CLOCKMHZSCALED;
+
+       CHAN_CENTERS centers;
+
+       if (IS_CHAN_TURBO(chan))
+               clockMhzScaled *= 2;
+       /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */
+       /* scale for selected channel bandwidth */
+       if (IS_CHAN_HALF_RATE(chan)) {
+               clockMhzScaled = clockMhzScaled >> 1;
+       } else if (IS_CHAN_QUARTER_RATE(chan)) {
+               clockMhzScaled = clockMhzScaled >> 2;
+       }
+
+       /*
+        * ALGO -> coef = 1e8/fcarrier*fclock/40;
+        * scaled coef to provide precision for this floating calculation
+        */
+       ar5416GetChannelCenters(ah, chan, &centers);
+       coef_scaled = clockMhzScaled / centers.synth_center;
+
+       ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp);
+
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+               AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+       OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+               AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+
+        /*
+         * For Short GI,
+         * scaled coeff is 9/10 that of normal coeff
+         */
+        coef_scaled = (9 * coef_scaled)/10;
+
+        ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp);
+
+        /* for short gi */
+        OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+                AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
+        OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+                AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
+#undef INIT_CLOCKMHZSCALED
+}
+
+/*
+ * Convert to baseband spur frequency given input channel frequency
+ * and compute register settings below.
+ */
+#define SPUR_RSSI_THRESH 40
+
+static void
+ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+    static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+                AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
+    static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+                AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
+    static const int inc[4] = { 0, 100, 0, 0 };
+
+    int bb_spur = AR_NO_SPUR;
+    int bin, cur_bin;
+    int spur_freq_sd;
+    int spur_delta_phase;
+    int denominator;
+    int upper, lower, cur_vit_mask;
+    int tmp, new;
+    int i;
+
+    int8_t mask_m[123];
+    int8_t mask_p[123];
+    int8_t mask_amt;
+    int tmp_mask;
+    int cur_bb_spur;
+    HAL_BOOL is2GHz = IS_CHAN_2GHZ(chan);
+
+    OS_MEMZERO(mask_m, sizeof(mask_m));
+    OS_MEMZERO(mask_p, sizeof(mask_p));
+
+    /*
+     * Need to verify range +/- 9.5 for static ht20, otherwise spur
+     * is out-of-band and can be ignored.
+     */
+    for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+        cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
+        if (AR_NO_SPUR == cur_bb_spur)
+            break;
+        cur_bb_spur = cur_bb_spur - (chan->channel * 10);
+        if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
+            bb_spur = cur_bb_spur;
+            break;
+        }
+    }
+    if (AR_NO_SPUR == bb_spur)
+        return;
+
+    bin = bb_spur * 32;
+
+    tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
+    new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+    OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), new);
+
+    new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+        AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+        AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+        AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+        SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+    OS_REG_WRITE(ah, AR_PHY_SPUR_REG, new);
+    /*
+     * Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz
+     * config, no offset for HT20.
+     * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
+     * /80 for dyn2040.
+     */
+    spur_delta_phase = ((bb_spur * 524288) / 100) &
+        AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+    /*
+     * in 11A mode the denominator of spur_freq_sd should be 40 and
+     * it should be 44 in 11G
+     */
+    denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
+    spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
+
+    new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+        SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+        SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+    OS_REG_WRITE(ah, AR_PHY_TIMING11, new);
+
+
+    /*
+     * ============================================
+     * pilot mask 1 [31:0] = +6..-26, no 0 bin
+     * pilot mask 2 [19:0] = +26..+7
+     *
+     * channel mask 1 [31:0] = +6..-26, no 0 bin
+     * channel mask 2 [19:0] = +26..+7
+     */
+    //cur_bin = -26;
+    cur_bin = -6000;
+    upper = bin + 100;
+    lower = bin - 100;
+
+    for (i = 0; i < 4; i++) {
+        int pilot_mask = 0;
+        int chan_mask  = 0;
+        int bp         = 0;
+        for (bp = 0; bp < 30; bp++) {
+            if ((cur_bin > lower) && (cur_bin < upper)) {
+                pilot_mask = pilot_mask | 0x1 << bp;
+                chan_mask  = chan_mask | 0x1 << bp;
+            }
+            cur_bin += 100;
+        }
+        cur_bin += inc[i];
+        OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+        OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+    }
+
+    /* =================================================
+     * viterbi mask 1 based on channel magnitude
+     * four levels 0-3
+     *  - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
+     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
+     *  - enable_mask_ppm, all bins move with freq
+     *
+     *  - mask_select,    8 bits for rates (reg 67,0x990c)
+     *  - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
+     *      choose which mask to use mask or mask2
+     */
+
+    /*
+     * viterbi mask 2  2nd set for per data rate puncturing
+     * four levels 0-3
+     *  - mask_select, 8 bits for rates (reg 67)
+     *  - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
+     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
+     */
+    cur_vit_mask = 6100;
+    upper        = bin + 120;
+    lower        = bin - 120;
+
+    for (i = 0; i < 123; i++) {
+        if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+            if ((abs(cur_vit_mask - bin)) < 75) {
+                mask_amt = 1;
+            } else {
+                mask_amt = 0;
+            }
+            if (cur_vit_mask < 0) {
+                mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+            } else {
+                mask_p[cur_vit_mask / 100] = mask_amt;
+            }
+        }
+        cur_vit_mask -= 100;
+    }
+
+    tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+          | (mask_m[48] << 26) | (mask_m[49] << 24)
+          | (mask_m[50] << 22) | (mask_m[51] << 20)
+          | (mask_m[52] << 18) | (mask_m[53] << 16)
+          | (mask_m[54] << 14) | (mask_m[55] << 12)
+          | (mask_m[56] << 10) | (mask_m[57] <<  8)
+          | (mask_m[58] <<  6) | (mask_m[59] <<  4)
+          | (mask_m[60] <<  2) | (mask_m[61] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+    tmp_mask =             (mask_m[31] << 28)
+          | (mask_m[32] << 26) | (mask_m[33] << 24)
+          | (mask_m[34] << 22) | (mask_m[35] << 20)
+          | (mask_m[36] << 18) | (mask_m[37] << 16)
+          | (mask_m[48] << 14) | (mask_m[39] << 12)
+          | (mask_m[40] << 10) | (mask_m[41] <<  8)
+          | (mask_m[42] <<  6) | (mask_m[43] <<  4)
+          | (mask_m[44] <<  2) | (mask_m[45] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+    tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+          | (mask_m[18] << 26) | (mask_m[18] << 24)
+          | (mask_m[20] << 22) | (mask_m[20] << 20)
+          | (mask_m[22] << 18) | (mask_m[22] << 16)
+          | (mask_m[24] << 14) | (mask_m[24] << 12)
+          | (mask_m[25] << 10) | (mask_m[26] <<  8)
+          | (mask_m[27] <<  6) | (mask_m[28] <<  4)
+          | (mask_m[29] <<  2) | (mask_m[30] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+    tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
+          | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
+          | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
+          | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
+          | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
+          | (mask_m[10] << 10) | (mask_m[11] <<  8)
+          | (mask_m[12] <<  6) | (mask_m[13] <<  4)
+          | (mask_m[14] <<  2) | (mask_m[15] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+    tmp_mask =             (mask_p[15] << 28)
+          | (mask_p[14] << 26) | (mask_p[13] << 24)
+          | (mask_p[12] << 22) | (mask_p[11] << 20)
+          | (mask_p[10] << 18) | (mask_p[ 9] << 16)
+          | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
+          | (mask_p[ 6] << 10) | (mask_p[ 5] <<  8)
+          | (mask_p[ 4] <<  6) | (mask_p[ 3] <<  4)
+          | (mask_p[ 2] <<  2) | (mask_p[ 1] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+    tmp_mask =             (mask_p[30] << 28)
+          | (mask_p[29] << 26) | (mask_p[28] << 24)
+          | (mask_p[27] << 22) | (mask_p[26] << 20)
+          | (mask_p[25] << 18) | (mask_p[24] << 16)
+          | (mask_p[23] << 14) | (mask_p[22] << 12)
+          | (mask_p[21] << 10) | (mask_p[20] <<  8)
+          | (mask_p[19] <<  6) | (mask_p[18] <<  4)
+          | (mask_p[17] <<  2) | (mask_p[16] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+    tmp_mask =             (mask_p[45] << 28)
+          | (mask_p[44] << 26) | (mask_p[43] << 24)
+          | (mask_p[42] << 22) | (mask_p[41] << 20)
+          | (mask_p[40] << 18) | (mask_p[39] << 16)
+          | (mask_p[38] << 14) | (mask_p[37] << 12)
+          | (mask_p[36] << 10) | (mask_p[35] <<  8)
+          | (mask_p[34] <<  6) | (mask_p[33] <<  4)
+          | (mask_p[32] <<  2) | (mask_p[31] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+    tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+          | (mask_p[59] << 26) | (mask_p[58] << 24)
+          | (mask_p[57] << 22) | (mask_p[56] << 20)
+          | (mask_p[55] << 18) | (mask_p[54] << 16)
+          | (mask_p[53] << 14) | (mask_p[52] << 12)
+          | (mask_p[51] << 10) | (mask_p[50] <<  8)
+          | (mask_p[49] <<  6) | (mask_p[48] <<  4)
+          | (mask_p[47] <<  2) | (mask_p[46] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+#ifdef AH_SUPPORT_AR9280
+#define        AR_BASE_FREQ_2GHZ       2300
+#define        AR_BASE_FREQ_5GHZ       4900
+#define        AR_SPUR_FEEQ_BOUND_HT40 19
+#define        AR_SPUR_FEEQ_BOUND_HT20 10
+
+static void
+ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
+{
+    static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+                AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
+    static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+                AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
+    static int inc[4] = { 0, 100, 0, 0 };
+
+    int bb_spur = AR_NO_SPUR;
+    int freq;
+    int bin, cur_bin;
+    int bb_spur_off, spur_subchannel_sd;
+    int spur_freq_sd;
+    int spur_delta_phase;
+    int denominator;
+    int upper, lower, cur_vit_mask;
+    int tmp, newVal;
+    int i;
+    CHAN_CENTERS centers;
+
+    int8_t mask_m[123];
+    int8_t mask_p[123];
+    int8_t mask_amt;
+    int tmp_mask;
+    int cur_bb_spur;
+    HAL_BOOL is2GHz = IS_CHAN_2GHZ(ichan);
+
+    OS_MEMZERO(&mask_m, sizeof(int8_t) * 123);
+    OS_MEMZERO(&mask_p, sizeof(int8_t) * 123);
+
+    ar5416GetChannelCenters(ah, ichan, &centers);
+    freq = centers.synth_center;
+
+    /*
+     * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40,
+     * otherwise spur is out-of-band and can be ignored.
+     */
+    for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+        cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
+        /* Get actual spur freq in MHz from EEPROM read value */
+        if (is2GHz) {
+            cur_bb_spur =  (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
+        } else {
+            cur_bb_spur =  (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
+        }
+
+        if (AR_NO_SPUR == cur_bb_spur)
+            break;
+        cur_bb_spur = cur_bb_spur - freq;
+
+        if (IS_CHAN_HT40(ichan)) {
+            if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
+                (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
+                bb_spur = cur_bb_spur;
+                break;
+            }
+        } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
+                   (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
+            bb_spur = cur_bb_spur;
+            break;
+        }
+    }
+
+    if (AR_NO_SPUR == bb_spur) {
+#if 1
+        /*
+         * MRC CCK can interfere with beacon detection and cause deaf/mute.
+         * Disable MRC CCK for now.
+         */
+        OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+#else
+        /* Enable MRC CCK if no spur is found in this channel. */
+        OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+#endif
+        return;
+    } else {
+        /*
+         * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur
+         * is found in this channel.
+         */
+        OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+    }
+
+    bin = bb_spur * 320;
+
+    tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
+
+    newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+    OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal);
+
+    newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+        AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+        AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+        AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+        SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+    OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
+
+    /* Pick control or extn channel to cancel the spur */
+    if (IS_CHAN_HT40(ichan)) {
+        if (bb_spur < 0) {
+            spur_subchannel_sd = 1;
+            bb_spur_off = bb_spur + 10;
+        } else {
+            spur_subchannel_sd = 0;
+            bb_spur_off = bb_spur - 10;
+        }
+    } else {
+        spur_subchannel_sd = 0;
+        bb_spur_off = bb_spur;
+    }
+
+    /*
+     * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
+     * /80 for dyn2040.
+     */
+    if (IS_CHAN_HT40(ichan))
+        spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+    else
+        spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+    /*
+     * in 11A mode the denominator of spur_freq_sd should be 40 and
+     * it should be 44 in 11G
+     */
+    denominator = IS_CHAN_2GHZ(ichan) ? 44 : 40;
+    spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
+
+    newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+        SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+        SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+    OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal);
+
+    /* Choose to cancel between control and extension channels */
+    newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
+    OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
+
+    /*
+     * ============================================
+     * Set Pilot and Channel Masks
+     *
+     * pilot mask 1 [31:0] = +6..-26, no 0 bin
+     * pilot mask 2 [19:0] = +26..+7
+     *
+     * channel mask 1 [31:0] = +6..-26, no 0 bin
+     * channel mask 2 [19:0] = +26..+7
+     */
+    cur_bin = -6000;
+    upper = bin + 100;
+    lower = bin - 100;
+
+    for (i = 0; i < 4; i++) {
+        int pilot_mask = 0;
+        int chan_mask  = 0;
+        int bp         = 0;
+        for (bp = 0; bp < 30; bp++) {
+            if ((cur_bin > lower) && (cur_bin < upper)) {
+                pilot_mask = pilot_mask | 0x1 << bp;
+                chan_mask  = chan_mask | 0x1 << bp;
+            }
+            cur_bin += 100;
+        }
+        cur_bin += inc[i];
+        OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+        OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+    }
+
+    /* =================================================
+     * viterbi mask 1 based on channel magnitude
+     * four levels 0-3
+     *  - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
+     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
+     *  - enable_mask_ppm, all bins move with freq
+     *
+     *  - mask_select,    8 bits for rates (reg 67,0x990c)
+     *  - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
+     *      choose which mask to use mask or mask2
+     */
+
+    /*
+     * viterbi mask 2  2nd set for per data rate puncturing
+     * four levels 0-3
+     *  - mask_select, 8 bits for rates (reg 67)
+     *  - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
+     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
+     */
+    cur_vit_mask = 6100;
+    upper        = bin + 120;
+    lower        = bin - 120;
+
+    for (i = 0; i < 123; i++) {
+        if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+            if ((abs(cur_vit_mask - bin)) < 75) {
+                mask_amt = 1;
+            } else {
+                mask_amt = 0;
+            }
+            if (cur_vit_mask < 0) {
+                mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+            } else {
+                mask_p[cur_vit_mask / 100] = mask_amt;
+            }
+        }
+        cur_vit_mask -= 100;
+    }
+
+    tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+          | (mask_m[48] << 26) | (mask_m[49] << 24)
+          | (mask_m[50] << 22) | (mask_m[51] << 20)
+          | (mask_m[52] << 18) | (mask_m[53] << 16)
+          | (mask_m[54] << 14) | (mask_m[55] << 12)
+          | (mask_m[56] << 10) | (mask_m[57] <<  8)
+          | (mask_m[58] <<  6) | (mask_m[59] <<  4)
+          | (mask_m[60] <<  2) | (mask_m[61] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+    tmp_mask =             (mask_m[31] << 28)
+          | (mask_m[32] << 26) | (mask_m[33] << 24)
+          | (mask_m[34] << 22) | (mask_m[35] << 20)
+          | (mask_m[36] << 18) | (mask_m[37] << 16)
+          | (mask_m[48] << 14) | (mask_m[39] << 12)
+          | (mask_m[40] << 10) | (mask_m[41] <<  8)
+          | (mask_m[42] <<  6) | (mask_m[43] <<  4)
+          | (mask_m[44] <<  2) | (mask_m[45] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+    tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+          | (mask_m[18] << 26) | (mask_m[18] << 24)
+          | (mask_m[20] << 22) | (mask_m[20] << 20)
+          | (mask_m[22] << 18) | (mask_m[22] << 16)
+          | (mask_m[24] << 14) | (mask_m[24] << 12)
+          | (mask_m[25] << 10) | (mask_m[26] <<  8)
+          | (mask_m[27] <<  6) | (mask_m[28] <<  4)
+          | (mask_m[29] <<  2) | (mask_m[30] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+    tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
+          | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
+          | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
+          | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
+          | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
+          | (mask_m[10] << 10) | (mask_m[11] <<  8)
+          | (mask_m[12] <<  6) | (mask_m[13] <<  4)
+          | (mask_m[14] <<  2) | (mask_m[15] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+    tmp_mask =             (mask_p[15] << 28)
+          | (mask_p[14] << 26) | (mask_p[13] << 24)
+          | (mask_p[12] << 22) | (mask_p[11] << 20)
+          | (mask_p[10] << 18) | (mask_p[ 9] << 16)
+          | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
+          | (mask_p[ 6] << 10) | (mask_p[ 5] <<  8)
+          | (mask_p[ 4] <<  6) | (mask_p[ 3] <<  4)
+          | (mask_p[ 2] <<  2) | (mask_p[ 1] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+    tmp_mask =             (mask_p[30] << 28)
+          | (mask_p[29] << 26) | (mask_p[28] << 24)
+          | (mask_p[27] << 22) | (mask_p[26] << 20)
+          | (mask_p[25] << 18) | (mask_p[24] << 16)
+          | (mask_p[23] << 14) | (mask_p[22] << 12)
+          | (mask_p[21] << 10) | (mask_p[20] <<  8)
+          | (mask_p[19] <<  6) | (mask_p[18] <<  4)
+          | (mask_p[17] <<  2) | (mask_p[16] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+    tmp_mask =             (mask_p[45] << 28)
+          | (mask_p[44] << 26) | (mask_p[43] << 24)
+          | (mask_p[42] << 22) | (mask_p[41] << 20)
+          | (mask_p[40] << 18) | (mask_p[39] << 16)
+          | (mask_p[38] << 14) | (mask_p[37] << 12)
+          | (mask_p[36] << 10) | (mask_p[35] <<  8)
+          | (mask_p[34] <<  6) | (mask_p[33] <<  4)
+          | (mask_p[32] <<  2) | (mask_p[31] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+    tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+          | (mask_p[59] << 26) | (mask_p[58] << 24)
+          | (mask_p[57] << 22) | (mask_p[56] << 20)
+          | (mask_p[55] << 18) | (mask_p[54] << 16)
+          | (mask_p[53] << 14) | (mask_p[52] << 12)
+          | (mask_p[51] << 10) | (mask_p[50] <<  8)
+          | (mask_p[49] <<  6) | (mask_p[48] <<  4)
+          | (mask_p[47] <<  2) | (mask_p[46] <<  0);
+    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+    OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+#endif /* AH_SUPPORT_AR9280 */
+
+/*
+ * Set a limit on the overall output power.  Used for dynamic
+ * transmit power control and the like.
+ *
+ * NB: limit is in units of 0.5 dbM.
+ */
+HAL_BOOL
+ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
+{
+       uint16_t dummyXpdGains[2];
+
+       AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
+       return ar5416SetTransmitPower(ah, AH_PRIVATE(ah)->ah_curchan,
+                       dummyXpdGains);
+}
+
+HAL_BOOL
+ar5416GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans)
+{
+       struct ath_hal_5212 *ahp = AH5212(ah);
+       int16_t minPower, maxPower;
+       HAL_CHANNEL *chan;
+       int i;
+
+       /*
+        * Get Pier table max and min powers.
+        */
+       for (i = 0; i < nchans; i++) {
+               chan = &chans[i];
+               if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) {
+                       /* NB: rf code returns 1/4 dBm units, convert */
+                       chan->maxTxPower = maxPower / 2;
+                       chan->minTxPower = minPower / 2;
+               } else {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: no min/max power for %u/0x%x\n",
+                           __func__, chan->channel, chan->channelFlags);
+                       chan->maxTxPower = AR5416_MAX_RATE_POWER;
+                       chan->minTxPower = 0;
+               }
+       }
+#ifdef AH_DEBUG
+       for (i=0; i<nchans; i++) {
+               HALDEBUG(ah, HAL_DEBUG_RESET,
+                   "Chan %d: MaxPow = %d MinPow = %d\n",
+                   chans[i].channel,chans[i].maxTxPower, chans[i].minTxPower);
+       }
+#endif
+       return AH_TRUE;
+}
+
+/* XXX gag, this is sick */
+typedef enum Ar5416_Rates {
+       rate6mb,  rate9mb,  rate12mb, rate18mb,
+       rate24mb, rate36mb, rate48mb, rate54mb,
+       rate1l,   rate2l,   rate2s,   rate5_5l,
+       rate5_5s, rate11l,  rate11s,  rateXr,
+       rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
+       rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
+       rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
+       rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
+       rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
+       Ar5416RateSize
+} AR5416_RATES;
+
+/**************************************************************
+ * ar5416SetTransmitPower
+ *
+ * Set the transmit power in the baseband for the given
+ * operating channel and mode.
+ */
+static HAL_BOOL
+ar5416SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain)
+{
+#define POW_SM(_r, _s)     (((_r) & 0x3f) << (_s))
+#define N(a)            (sizeof (a) / sizeof (a[0]))
+
+    MODAL_EEP_HEADER   *pModal;
+    struct ath_hal_5212 *ahp = AH5212(ah);
+    int16_t            ratesArray[Ar5416RateSize];
+    int16_t            txPowerIndexOffset = 0;
+    uint8_t            ht40PowerIncForPdadc = 2;
+    int                        i;
+
+    uint16_t           cfgCtl;
+    uint16_t           powerLimit;
+    uint16_t           twiceAntennaReduction;
+    uint16_t           twiceMaxRegulatoryPower;
+    int16_t            maxPower;
+    HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+    struct ar5416eeprom        *pEepData = &ee->ee_base;
+
+    HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
+
+    /* Setup info for the actual eeprom */
+    ath_hal_memzero(ratesArray, sizeof(ratesArray));
+    cfgCtl = ath_hal_getctl(ah, (HAL_CHANNEL *)chan);
+    powerLimit = chan->maxRegTxPower * 2;
+    twiceAntennaReduction = chan->antennaMax;
+    twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit);
+    pModal = &pEepData->modalHeader[IS_CHAN_2GHZ(chan)];
+    HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n",
+       __func__,chan->channel, cfgCtl );
+
+    if (IS_EEP_MINOR_V2(ah)) {
+        ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+    }
+
+    if (!ar5416SetPowerPerRateTable(ah, pEepData,  chan,
+                                    &ratesArray[0],cfgCtl,
+                                    twiceAntennaReduction,
+                                   twiceMaxRegulatoryPower, powerLimit)) {
+        HALDEBUG(ah, HAL_DEBUG_ANY,
+           "%s: unable to set tx power per rate table\n", __func__);
+        return AH_FALSE;
+    }
+
+    if (!ar5416SetPowerCalTable(ah,  pEepData, chan, &txPowerIndexOffset)) {
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n",
+           __func__);
+        return AH_FALSE;
+    }
+
+    maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
+
+    if (IS_CHAN_2GHZ(chan)) {
+        maxPower = AH_MAX(maxPower, ratesArray[rate1l]);
+    }
+
+    if (IS_CHAN_HT40(chan)) {
+        maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]);
+    }
+
+    ahp->ah_tx6PowerInHalfDbm = maxPower;
+    AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower;
+    ahp->ah_txPowerIndexOffset = txPowerIndexOffset;
+
+    /*
+     * txPowerIndexOffset is set by the SetPowerTable() call -
+     *  adjust the rate table (0 offset if rates EEPROM not loaded)
+     */
+    for (i = 0; i < N(ratesArray); i++) {
+        ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+        if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+            ratesArray[i] = AR5416_MAX_RATE_POWER;
+    }
+
+#ifdef AH_EEPROM_DUMP
+    ar5416PrintPowerPerRate(ah, ratesArray);
+#endif
+
+    /* Write the OFDM power per rate set */
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+        POW_SM(ratesArray[rate18mb], 24)
+          | POW_SM(ratesArray[rate12mb], 16)
+          | POW_SM(ratesArray[rate9mb], 8)
+          | POW_SM(ratesArray[rate6mb], 0)
+    );
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+        POW_SM(ratesArray[rate54mb], 24)
+          | POW_SM(ratesArray[rate48mb], 16)
+          | POW_SM(ratesArray[rate36mb], 8)
+          | POW_SM(ratesArray[rate24mb], 0)
+    );
+
+    if (IS_CHAN_2GHZ(chan)) {
+        /* Write the CCK power per rate set */
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+            POW_SM(ratesArray[rate2s], 24)
+              | POW_SM(ratesArray[rate2l],  16)
+              | POW_SM(ratesArray[rateXr],  8) /* XR target power */
+              | POW_SM(ratesArray[rate1l],   0)
+        );
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+            POW_SM(ratesArray[rate11s], 24)
+              | POW_SM(ratesArray[rate11l], 16)
+              | POW_SM(ratesArray[rate5_5s], 8)
+              | POW_SM(ratesArray[rate5_5l], 0)
+        );
+    HALDEBUG(ah, HAL_DEBUG_RESET,
+       "%s AR_PHY_POWER_TX_RATE3=0x%x AR_PHY_POWER_TX_RATE4=0x%x\n",
+           __func__, OS_REG_READ(ah,AR_PHY_POWER_TX_RATE3),
+           OS_REG_READ(ah,AR_PHY_POWER_TX_RATE4));
+    }
+
+    /* Write the HT20 power per rate set */
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+        POW_SM(ratesArray[rateHt20_3], 24)
+          | POW_SM(ratesArray[rateHt20_2], 16)
+          | POW_SM(ratesArray[rateHt20_1], 8)
+          | POW_SM(ratesArray[rateHt20_0], 0)
+    );
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+        POW_SM(ratesArray[rateHt20_7], 24)
+          | POW_SM(ratesArray[rateHt20_6], 16)
+          | POW_SM(ratesArray[rateHt20_5], 8)
+          | POW_SM(ratesArray[rateHt20_4], 0)
+    );
+
+    if (IS_CHAN_HT40(chan)) {
+        /* Write the HT40 power per rate set */
+       /* Correct PAR difference between HT40 and HT20/LEGACY */
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+            POW_SM(ratesArray[rateHt40_3] + ht40PowerIncForPdadc, 24)
+              | POW_SM(ratesArray[rateHt40_2] + ht40PowerIncForPdadc, 16)
+              | POW_SM(ratesArray[rateHt40_1] + ht40PowerIncForPdadc, 8)
+              | POW_SM(ratesArray[rateHt40_0] + ht40PowerIncForPdadc, 0)
+        );
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+            POW_SM(ratesArray[rateHt40_7] + ht40PowerIncForPdadc, 24)
+              | POW_SM(ratesArray[rateHt40_6] + ht40PowerIncForPdadc, 16)
+              | POW_SM(ratesArray[rateHt40_5] + ht40PowerIncForPdadc, 8)
+              | POW_SM(ratesArray[rateHt40_4] + ht40PowerIncForPdadc, 0)
+        );
+        /* Write the Dup/Ext 40 power per rate set */
+        OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+            POW_SM(ratesArray[rateExtOfdm], 24)
+              | POW_SM(ratesArray[rateExtCck], 16)
+              | POW_SM(ratesArray[rateDupOfdm], 8)
+              | POW_SM(ratesArray[rateDupCck], 0)
+        );
+    }
+
+    /* Write the Power subtraction for dynamic chain changing, for per-packet powertx */
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+        POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+          | POW_SM(pModal->pwrDecreaseFor2Chain, 0)
+    );
+    return AH_TRUE;
+#undef POW_SM
+#undef N
+}
+
+/*
+ * Exported call to check for a recent gain reading and return
+ * the current state of the thermal calibration gain engine.
+ */
+HAL_RFGAIN
+ar5416GetRfgain(struct ath_hal *ah)
+{
+       return HAL_RFGAIN_INACTIVE;
+}
+
+/*
+ * Places all of hardware into reset
+ */
+HAL_BOOL
+ar5416Disable(struct ath_hal *ah)
+{
+       if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
+               return AH_FALSE;
+       return ar5416SetResetReg(ah, HAL_RESET_COLD);
+}
+
+/*
+ * Places the PHY and Radio chips into reset.  A full reset
+ * must be called to leave this state.  The PCI/MAC/PCU are
+ * not placed into reset as we must receive interrupt to
+ * re-enable the hardware.
+ */
+HAL_BOOL
+ar5416PhyDisable(struct ath_hal *ah)
+{
+       return ar5416SetResetReg(ah, HAL_RESET_WARM);
+}
+
+/*
+ * Write the given reset bit mask into the reset register
+ */
+HAL_BOOL
+ar5416SetResetReg(struct ath_hal *ah, uint32_t type)
+{
+       /*
+        * Set force wake
+        */
+       OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+            AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+       switch (type) {
+       case HAL_RESET_POWER_ON:
+               return ar5416SetResetPowerOn(ah);
+               break;
+       case HAL_RESET_WARM:
+       case HAL_RESET_COLD:
+               return ar5416SetReset(ah, type);
+               break;
+       default:
+               return AH_FALSE;
+       }
+}
+
+static HAL_BOOL
+ar5416SetResetPowerOn(struct ath_hal *ah)
+{
+    /* Power On Reset (Hard Reset) */
+
+    /*
+     * Set force wake
+     *
+     * If the MAC was running, previously calling
+     * reset will wake up the MAC but it may go back to sleep
+     * before we can start polling.
+     * Set force wake  stops that
+     * This must be called before initiating a hard reset.
+     */
+    OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+            AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+    /*
+     * RTC reset and clear
+     */
+    OS_REG_WRITE(ah, AR_RTC_RESET, 0);
+    OS_DELAY(20);
+    OS_REG_WRITE(ah, AR_RTC_RESET, 1);
+
+    /*
+     * Poll till RTC is ON
+     */
+    if (!ath_hal_wait(ah, AR_RTC_STATUS, AR_RTC_PM_STATUS_M, AR_RTC_STATUS_ON)) {
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC not waking up\n", __func__);
+        return AH_FALSE;
+    }
+
+    return ar5416SetReset(ah, HAL_RESET_COLD);
+}
+
+static HAL_BOOL
+ar5416SetReset(struct ath_hal *ah, int type)
+{
+    uint32_t tmpReg;
+
+    /*
+     * Force wake
+     */
+    OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+       AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+    /*
+     * Reset AHB
+     */
+    tmpReg = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
+    if (tmpReg & (AR_INTR_SYNC_LOCAL_TIMEOUT|AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+       OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+       OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF);
+    } else {
+       OS_REG_WRITE(ah, AR_RC, AR_RC_AHB);
+    }
+
+    /*
+     * Set Mac(BB,Phy) Warm Reset
+     */
+    switch (type) {
+    case HAL_RESET_WARM:
+            OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM);
+            break;
+        case HAL_RESET_COLD:
+            OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM|AR_RTC_RC_MAC_COLD);
+            break;
+        default:
+            HALASSERT(0);
+            break;
+    }
+
+    /*
+     * Clear resets and force wakeup
+     */
+    OS_REG_WRITE(ah, AR_RTC_RC, 0);
+    if (!ath_hal_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) {
+        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC stuck in MAC reset\n", __func__);
+        return AH_FALSE;
+    }
+
+    /* Clear AHB reset */
+    OS_REG_WRITE(ah, AR_RC, 0);
+
+   /* Set register and descriptor swapping on
+    * Bigendian platforms on cold reset
+    */
+#ifdef __BIG_ENDIAN__
+    if (type == HAL_RESET_COLD) {
+               uint32_t        mask;
+
+               HALDEBUG(ah, HAL_DEBUG_RESET,
+                   "%s Applying descriptor swap\n", __func__);
+
+               mask = INIT_CONFIG_STATUS | AR_CFG_SWRD | AR_CFG_SWRG;
+#ifndef AH_NEED_DESC_SWAP
+               mask |= AR_CFG_SWTD;
+#endif
+               OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));
+       }
+#endif
+
+    ar5416InitPLL(ah, AH_NULL);
+
+    return AH_TRUE;
+}
+
+#ifndef IS_5GHZ_FAST_CLOCK_EN
+#define        IS_5GHZ_FAST_CLOCK_EN(ah, chan) AH_FALSE
+#endif
+
+static void
+ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t pll;
+
+       if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+               pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
+
+               if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
+                       pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
+               } else if (chan && IS_CHAN_QUARTER_RATE(chan)) {
+                       pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
+               }
+               if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
+                       pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
+
+                       /*
+                        * PLL WAR for Merlin 2.0/2.1
+                        * When doing fast clock, set PLL to 0x142c
+                        * Else, set PLL to 0x2850 to prevent reset-to-reset variation
+                        */
+                       if (AR_SREV_MERLIN_20(ah)) {
+                               if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
+                                       pll = 0x142c;
+                               } else {
+                                       pll = 0x2850;
+                               }
+                       }
+               } else {
+                       pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
+               }
+       } else if (AR_SREV_SOWL_10_OR_LATER(ah)) {
+               pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
+
+               if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
+                       pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
+               } else if (chan && IS_CHAN_QUARTER_RATE(chan)) {
+                       pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
+               }
+               if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
+                       pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV);
+               } else {
+                       pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);
+               }
+       } else {
+               pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+
+               if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
+                       pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+               } else if (chan != AH_NULL && IS_CHAN_QUARTER_RATE(chan)) {
+                       pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
+               }
+               if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
+                       pll |= SM(0xa, AR_RTC_PLL_DIV);
+               } else {
+                       pll |= SM(0xb, AR_RTC_PLL_DIV);
+               }
+       }
+       OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
+
+       /* TODO:
+       * For multi-band owl, switch between bands by reiniting the PLL.
+       */
+
+       OS_DELAY(RTC_PLL_SETTLE_DELAY);
+
+       OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
+}
+
+/*
+ * Read EEPROM header info and program the device for correct operation
+ * given the channel value.
+ */
+static HAL_BOOL
+ar5416SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+    const HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+    const struct ar5416eeprom *eep = &ee->ee_base;
+    const MODAL_EEP_HEADER *pModal;
+    int                        i, regChainOffset;
+    uint8_t            txRxAttenLocal;    /* workaround for eeprom versions <= 14.2 */
+
+    HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
+    pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+    txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;    /* workaround for eeprom versions <= 14.2 */
+
+    OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
+    for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+          if (AR_SREV_MERLIN(ah)) {
+               if (i >= 2) break;
+          }
+                  if (AR_SREV_OWL_20_OR_LATER(ah) &&
+            (AH5416(ah)->ah_rx_chainmask == 0x5 ||
+            AH5416(ah)->ah_tx_chainmask == 0x5) && i != 0) {
+            /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
+             * only chains 0 and 2 populated
+             */
+            regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+        } else {
+            regChainOffset = i * 0x1000;
+        }
+
+        OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]);
+        OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset,
+               (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) &
+               ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+               SM(pModal->iqCalICh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+               SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+        /*
+         * Large signal upgrade.
+        * XXX update
+         */
+
+        if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) {
+            OS_REG_WRITE(ah, AR_PHY_RXGAIN + regChainOffset,
+               (OS_REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & ~AR_PHY_RXGAIN_TXRX_ATTEN) |
+                       SM(IS_EEP_MINOR_V3(ah)  ? pModal->txRxAttenCh[i] : txRxAttenLocal,
+                               AR_PHY_RXGAIN_TXRX_ATTEN));
+
+            OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+               (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+                       SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+        }
+    }
+
+    OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
+    OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
+    OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize);
+    OS_REG_WRITE(ah, AR_PHY_RF_CTL4,
+        SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+        | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+        | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+        | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+    OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
+
+    if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+       OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+           pModal->thresh62);
+       OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+           pModal->thresh62);
+    } else {
+       OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+           pModal->thresh62);
+       OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA_THRESH62,
+           pModal->thresh62);
+    }
+
+    /* Minor Version Specific application */
+    if (IS_EEP_MINOR_V2(ah)) {
+        OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,  AR_PHY_TX_FRAME_TO_DATA_START, pModal->txFrameToDataStart);
+        OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,  AR_PHY_TX_FRAME_TO_PA_ON, pModal->txFrameToPaOn);
+    }
+
+    if (IS_EEP_MINOR_V3(ah)) {
+       if (IS_CHAN_HT40(chan)) {
+               /* Overwrite switch settling with HT40 value */
+               OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
+       }
+
+        if ((AR_SREV_OWL_20_OR_LATER(ah)) &&
+            (  AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5)){
+            /* Reg Offsets are swapped for logical mapping */
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
+                       SM(pModal->bswMargin[2], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
+                       SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
+                       SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
+                       SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+        } else {
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
+                       SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
+                       SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
+                       SM(pModal->bswMargin[2],AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+               OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
+                       SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+        }
+        OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_MARGIN, pModal->bswMargin[0]);
+        OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_ATTEN, pModal->bswAtten[0]);
+    }
+    return AH_TRUE;
+}
+
+/*
+ * Helper functions common for AP/CB/XB
+ */
+
+/*
+ * ar5416SetPowerPerRateTable
+ *
+ * Sets the transmit power in the baseband for the given
+ * operating channel and mode.
+ */
+static HAL_BOOL
+ar5416SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom *pEepData,
+                           HAL_CHANNEL_INTERNAL *chan,
+                           int16_t *ratesArray, uint16_t cfgCtl,
+                           uint16_t AntennaReduction,
+                           uint16_t twiceMaxRegulatoryPower,
+                           uint16_t powerLimit)
+{
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+/* Local defines to distinguish between extension and control CTL's */
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+
+       uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+       int i;
+       int16_t  twiceLargestAntenna;
+       CAL_CTL_DATA *rep;
+       CAL_TARGET_POWER_LEG targetPowerOfdm, targetPowerCck = {0, {0, 0, 0, 0}};
+       CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}, targetPowerCckExt = {0, {0, 0, 0, 0}};
+       CAL_TARGET_POWER_HT  targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0}};
+       int16_t scaledPower, minCtlPower;
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2   /* excluding HT40, EXT-OFDM */
+#define SUB_NUM_CTL_MODES_AT_2G_40 3   /* excluding HT40, EXT-OFDM, EXT-CCK */
+       static const uint16_t ctlModesFor11a[] = {
+          CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+       };
+       static const uint16_t ctlModesFor11g[] = {
+          CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+       };
+       const uint16_t *pCtlMode;
+       uint16_t numCtlModes, ctlMode, freq;
+       CHAN_CENTERS centers;
+
+       ar5416GetChannelCenters(ah,  chan, &centers);
+
+       /* Compute TxPower reduction due to Antenna Gain */
+
+       twiceLargestAntenna = AH_MAX(AH_MAX(pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+                                       pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[1]),
+                                       pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+#if 0
+       /* Turn it back on if we need to calculate per chain antenna gain reduction */
+       /* Use only if the expected gain > 6dbi */
+       /* Chain 0 is always used */
+       twiceLargestAntenna = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[0];
+
+       /* Look at antenna gains of Chains 1 and 2 if the TX mask is set */
+       if (ahp->ah_tx_chainmask & 0x2)
+               twiceLargestAntenna = AH_MAX(twiceLargestAntenna,
+                       pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+
+       if (ahp->ah_tx_chainmask & 0x4)
+               twiceLargestAntenna = AH_MAX(twiceLargestAntenna,
+                       pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+#endif
+       twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0);
+
+       /* XXX setup for 5212 use (really used?) */
+       ath_hal_eepromSet(ah,
+           IS_CHAN_2GHZ(chan) ? AR_EEP_ANTGAINMAX_2 : AR_EEP_ANTGAINMAX_5,
+           twiceLargestAntenna);
+
+       /*
+        * scaledPower is the minimum of the user input power level and
+        * the regulatory allowed power level
+        */
+       scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna);
+
+       /* Reduce scaled Power by number of chains active to get to per chain tx power level */
+       /* TODO: better value than these? */
+       switch (owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask)) {
+       case 1:
+               break;
+       case 2:
+               scaledPower -= pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor2Chain;
+               break;
+       case 3:
+               scaledPower -= pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor3Chain;
+               break;
+       default:
+               return AH_FALSE; /* Unsupported number of chains */
+       }
+
+       scaledPower = AH_MAX(0, scaledPower);
+
+       /* Get target powers from EEPROM - our baseline for TX Power */
+       if (IS_CHAN_2GHZ(chan)) {
+               /* Setup for CTL modes */
+               numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */
+               pCtlMode = ctlModesFor11g;
+
+               ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPowerCck,
+                               AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE);
+               ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPower2G,
+                               AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE);
+               ar5416GetTargetPowers(ah,  chan, pEepData->calTargetPower2GHT20,
+                               AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE);
+
+               if (IS_CHAN_HT40(chan)) {
+                       numCtlModes = N(ctlModesFor11g);    /* All 2G CTL's */
+
+                       ar5416GetTargetPowers(ah,  chan, pEepData->calTargetPower2GHT40,
+                               AR5416_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE);
+                       /* Get target powers for extension channels */
+                       ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPowerCck,
+                               AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE);
+                       ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPower2G,
+                               AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE);
+               }
+       } else {
+               /* Setup for CTL modes */
+               numCtlModes = N(ctlModesFor11a) - SUB_NUM_CTL_MODES_AT_5G_40; /* CTL_11A, CTL_5GHT20 */
+               pCtlMode = ctlModesFor11a;
+
+               ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPower5G,
+                               AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE);
+               ar5416GetTargetPowers(ah,  chan, pEepData->calTargetPower5GHT20,
+                               AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE);
+
+               if (IS_CHAN_HT40(chan)) {
+                       numCtlModes = N(ctlModesFor11a); /* All 5G CTL's */
+
+                       ar5416GetTargetPowers(ah,  chan, pEepData->calTargetPower5GHT40,
+                               AR5416_NUM_5G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE);
+                       ar5416GetTargetPowersLeg(ah,  chan, pEepData->calTargetPower5G,
+                               AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE);
+               }
+       }
+
+       /*
+        * For MIMO, need to apply regulatory caps individually across dynamically
+        * running modes: CCK, OFDM, HT20, HT40
+        *
+        * The outer loop walks through each possible applicable runtime mode.
+        * The inner loop walks through each ctlIndex entry in EEPROM.
+        * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
+        *
+        */
+       for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+
+               HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+                                                                (pCtlMode[ctlMode] == CTL_2GHT40);
+               if (isHt40CtlMode) {
+                       freq = centers.ctl_center;
+               } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) {
+                       freq = centers.ext_center;
+               } else {
+                       freq = centers.ctl_center;
+               }
+
+               /* walk through each CTL index stored in EEPROM */
+               for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+                       uint16_t twiceMinEdgePower;
+
+                       /* compare test group from regulatory channel list with test mode from pCtlMode list */
+                       if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) ||
+                               (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+                                ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
+                               rep = &(pEepData->ctlData[i]);
+                               twiceMinEdgePower = ar5416GetMaxEdgePower(freq,
+                                                       rep->ctlEdges[owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1],
+                                                       IS_CHAN_2GHZ(chan));
+                               if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+                                       /* Find the minimum of all CTL edge powers that apply to this channel */
+                                       twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower);
+                               } else {
+                                       /* specific */
+                                       twiceMaxEdgePower = twiceMinEdgePower;
+                                       break;
+                               }
+                       }
+               }
+               minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower);
+               /* Apply ctl mode to correct target power set */
+               switch(pCtlMode[ctlMode]) {
+               case CTL_11B:
+                       for (i = 0; i < N(targetPowerCck.tPow2x); i++) {
+                               targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower);
+                       }
+                       break;
+               case CTL_11A:
+               case CTL_11G:
+                       for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) {
+                               targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower);
+                       }
+                       break;
+               case CTL_5GHT20:
+               case CTL_2GHT20:
+                       for (i = 0; i < N(targetPowerHt20.tPow2x); i++) {
+                               targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower);
+                       }
+                       break;
+               case CTL_11B_EXT:
+                       targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower);
+                       break;
+               case CTL_11A_EXT:
+               case CTL_11G_EXT:
+                       targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower);
+                       break;
+               case CTL_5GHT40:
+               case CTL_2GHT40:
+                       for (i = 0; i < N(targetPowerHt40.tPow2x); i++) {
+                               targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower);
+                       }
+                       break;
+               default:
+                       return AH_FALSE;
+                       break;
+               }
+       } /* end ctl mode checking */
+
+       /* Set rates Array from collected data */
+       ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = ratesArray[rate18mb] = ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0];
+       ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+       ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+       ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+       ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+       for (i = 0; i < N(targetPowerHt20.tPow2x); i++) {
+               ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+       }
+
+       if (IS_CHAN_2GHZ(chan)) {
+               ratesArray[rate1l]  = targetPowerCck.tPow2x[0];
+               ratesArray[rate2s] = ratesArray[rate2l]  = targetPowerCck.tPow2x[1];
+               ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+               ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+       }
+       if (IS_CHAN_HT40(chan)) {
+               for (i = 0; i < N(targetPowerHt40.tPow2x); i++) {
+                       ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
+               }
+               ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+               ratesArray[rateDupCck]  = targetPowerHt40.tPow2x[0];
+               ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+               if (IS_CHAN_2GHZ(chan)) {
+                       ratesArray[rateExtCck]  = targetPowerCckExt.tPow2x[0];
+               }
+       }
+       return AH_TRUE;
+#undef EXT_ADDITIVE
+#undef CTL_11A_EXT
+#undef CTL_11G_EXT
+#undef CTL_11B_EXT
+#undef SUB_NUM_CTL_MODES_AT_5G_40
+#undef SUB_NUM_CTL_MODES_AT_2G_40
+#undef N
+}
+
+/**************************************************************************
+ * fbin2freq
+ *
+ * Get channel value from binary representation held in eeprom
+ * RETURNS: the frequency in MHz
+ */
+static uint16_t
+fbin2freq(uint8_t fbin, HAL_BOOL is2GHz)
+{
+    /*
+     * Reserved value 0xFF provides an empty definition both as
+     * an fbin and as a frequency - do not convert
+     */
+    if (fbin == AR5416_BCHAN_UNUSED) {
+        return fbin;
+    }
+
+    return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+/*
+ * ar5416GetMaxEdgePower
+ *
+ * Find the maximum conformance test limit for the given channel and CTL info
+ */
+static uint16_t
+ar5416GetMaxEdgePower(uint16_t freq, CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz)
+{
+    uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+    int      i;
+
+    /* Get the edge power */
+    for (i = 0; (i < AR5416_NUM_BAND_EDGES) && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED) ; i++) {
+        /*
+         * If there's an exact channel match or an inband flag set
+         * on the lower channel use the given rdEdgePower
+         */
+        if (freq == fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
+            twiceMaxEdgePower = MS(pRdEdgesPower[i].tPowerFlag, CAL_CTL_EDGES_POWER);
+            break;
+        } else if ((i > 0) && (freq < fbin2freq(pRdEdgesPower[i].bChannel, is2GHz))) {
+            if (fbin2freq(pRdEdgesPower[i - 1].bChannel, is2GHz) < freq && (pRdEdgesPower[i - 1].tPowerFlag & CAL_CTL_EDGES_FLAG) != 0) {
+                twiceMaxEdgePower = MS(pRdEdgesPower[i - 1].tPowerFlag, CAL_CTL_EDGES_POWER);
+            }
+            /* Leave loop - no more affecting edges possible in this monotonic increasing list */
+            break;
+        }
+    }
+    HALASSERT(twiceMaxEdgePower > 0);
+    return twiceMaxEdgePower;
+}
+
+/**************************************************************
+ * ar5416GetTargetPowers
+ *
+ * Return the rates of target power for the given target power table
+ * channel, and number of channels
+ */
+static void
+ar5416GetTargetPowers(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan,
+                      CAL_TARGET_POWER_HT *powInfo, uint16_t numChannels,
+                      CAL_TARGET_POWER_HT *pNewPower, uint16_t numRates,
+                      HAL_BOOL isHt40Target)
+{
+    uint16_t clo, chi;
+    int i;
+    int matchIndex = -1, lowIndex = -1;
+    uint16_t freq;
+    CHAN_CENTERS centers;
+
+    ar5416GetChannelCenters(ah,  chan, &centers);
+    freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+
+    /* Copy the target powers into the temp channel list */
+    if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+        matchIndex = 0;
+    } else {
+        for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+            if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) {
+                matchIndex = i;
+                break;
+            } else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) &&
+                       (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))))
+            {
+                lowIndex = i - 1;
+                break;
+            }
+        }
+        if ((matchIndex == -1) && (lowIndex == -1)) {
+            HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)));
+            matchIndex = i - 1;
+        }
+    }
+
+    if (matchIndex != -1) {
+        OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower));
+    } else {
+        HALASSERT(lowIndex != -1);
+        /*
+         * Get the lower and upper channels, target powers,
+         * and interpolate between them.
+         */
+        clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan));
+        chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan));
+
+        for (i = 0; i < numRates; i++) {
+            pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi,
+                                   powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
+        }
+    }
+}
+/**************************************************************
+ * ar5416GetTargetPowersLeg
+ *
+ * Return the four rates of target power for the given target power table
+ * channel, and number of channels
+ */
+static void
+ar5416GetTargetPowersLeg(struct ath_hal *ah,
+                         HAL_CHANNEL_INTERNAL *chan,
+                         CAL_TARGET_POWER_LEG *powInfo, uint16_t numChannels,
+                         CAL_TARGET_POWER_LEG *pNewPower, uint16_t numRates,
+                        HAL_BOOL isExtTarget)
+{
+    uint16_t clo, chi;
+    int i;
+    int matchIndex = -1, lowIndex = -1;
+    uint16_t freq;
+    CHAN_CENTERS centers;
+
+    ar5416GetChannelCenters(ah,  chan, &centers);
+    freq = (isExtTarget) ? centers.ext_center :centers.ctl_center;
+
+    /* Copy the target powers into the temp channel list */
+    if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+        matchIndex = 0;
+    } else {
+        for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+            if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) {
+                matchIndex = i;
+                break;
+            } else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) &&
+                       (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))))
+            {
+                lowIndex = i - 1;
+                break;
+            }
+        }
+        if ((matchIndex == -1) && (lowIndex == -1)) {
+            HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)));
+            matchIndex = i - 1;
+        }
+    }
+
+    if (matchIndex != -1) {
+        OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower));
+    } else {
+        HALASSERT(lowIndex != -1);
+        /*
+         * Get the lower and upper channels, target powers,
+         * and interpolate between them.
+         */
+        clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan));
+        chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan));
+
+        for (i = 0; i < numRates; i++) {
+            pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi,
+                                   powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
+        }
+    }
+}
+
+/**************************************************************
+ * ar5416SetPowerCalTable
+ *
+ * Pull the PDADC piers from cal data and interpolate them across the given
+ * points as well as from the nearest pier(s) to get a power detector
+ * linear voltage to power level table.
+ */
+static HAL_BOOL
+ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, HAL_CHANNEL_INTERNAL *chan, int16_t *pTxPowerIndexOffset)
+{
+    CAL_DATA_PER_FREQ *pRawDataset;
+    uint8_t  *pCalBChans = AH_NULL;
+    uint16_t pdGainOverlap_t2;
+    static uint8_t  pdadcValues[AR5416_NUM_PDADC_VALUES];
+    uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+    uint16_t numPiers, i, j;
+    int16_t  tMinCalPower;
+    uint16_t numXpdGain, xpdMask;
+    uint16_t xpdGainValues[AR5416_NUM_PD_GAINS];
+    uint32_t reg32, regOffset, regChainOffset;
+
+    ath_hal_memzero(xpdGainValues, sizeof(xpdGainValues));
+
+    xpdMask = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].xpdGain;
+
+    if (IS_EEP_MINOR_V2(ah)) {
+        pdGainOverlap_t2 = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pdGainOverlap;
+    } else {
+       pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+    }
+
+    if (IS_CHAN_2GHZ(chan)) {
+        pCalBChans = pEepData->calFreqPier2G;
+        numPiers = AR5416_NUM_2G_CAL_PIERS;
+    } else {
+        pCalBChans = pEepData->calFreqPier5G;
+        numPiers = AR5416_NUM_5G_CAL_PIERS;
+    }
+
+    numXpdGain = 0;
+    /* Calculate the value of xpdgains from the xpdGain Mask */
+    for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+        if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+            if (numXpdGain >= AR5416_NUM_PD_GAINS) {
+                HALASSERT(0);
+                break;
+            }
+            xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
+            numXpdGain++;
+        }
+    }
+
+    /* Write the detector gain biases and their number */
+    OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) &
+       ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) |
+       SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) |
+       SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | SM(xpdGainValues[2],  AR_PHY_TPCRG1_PD_GAIN_3));
+
+    for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+
+            if (AR_SREV_OWL_20_OR_LATER(ah) &&
+            ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) {
+            /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
+             * only chains 0 and 2 populated
+             */
+            regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+        } else {
+            regChainOffset = i * 0x1000;
+        }
+
+        if (pEepData->baseEepHeader.txMask & (1 << i)) {
+            if (IS_CHAN_2GHZ(chan)) {
+                pRawDataset = pEepData->calPierData2G[i];
+            } else {
+                pRawDataset = pEepData->calPierData5G[i];
+            }
+
+            ar5416GetGainBoundariesAndPdadcs(ah,  chan, pRawDataset,
+                                             pCalBChans, numPiers,
+                                             pdGainOverlap_t2,
+                                             &tMinCalPower, gainBoundaries,
+                                             pdadcValues, numXpdGain);
+
+            if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) {
+                /*
+                 * Note the pdadc table may not start at 0 dBm power, could be
+                 * negative or greater than 0.  Need to offset the power
+                 * values by the amount of minPower for griffin
+                 */
+
+                OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+                     SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                     SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)  |
+                     SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)  |
+                     SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)  |
+                     SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+            }
+
+            /* Write the power values into the baseband power table */
+            regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+
+            for (j = 0; j < 32; j++) {
+                reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0)  |
+                    ((pdadcValues[4*j + 1] & 0xFF) << 8)  |
+                    ((pdadcValues[4*j + 2] & 0xFF) << 16) |
+                    ((pdadcValues[4*j + 3] & 0xFF) << 24) ;
+                OS_REG_WRITE(ah, regOffset, reg32);
+
+#ifdef PDADC_DUMP
+               ath_hal_printf(ah, "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",
+                              i,
+                              4*j, pdadcValues[4*j],
+                              4*j+1, pdadcValues[4*j + 1],
+                              4*j+2, pdadcValues[4*j + 2],
+                              4*j+3, pdadcValues[4*j + 3]);
+#endif
+                regOffset += 4;
+            }
+        }
+    }
+    *pTxPowerIndexOffset = 0;
+
+    return AH_TRUE;
+}
+
+/**************************************************************
+ * ar5416GetGainBoundariesAndPdadcs
+ *
+ * Uses the data points read from EEPROM to reconstruct the pdadc power table
+ * Called by ar5416SetPowerCalTable only.
+ */
+static void
+ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
+                                 HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet,
+                                 uint8_t * bChans,  uint16_t availPiers,
+                                 uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries,
+                                 uint8_t * pPDADCValues, uint16_t numXpdGains)
+{
+
+    int       i, j, k;
+    int16_t   ss;         /* potentially -ve index for taking care of pdGainOverlap */
+    uint16_t  idxL = 0, idxR = 0, numPiers; /* Pier indexes */
+
+    /* filled out Vpd table for all pdGains (chanL) */
+    static uint8_t   vpdTableL[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+    /* filled out Vpd table for all pdGains (chanR) */
+    static uint8_t   vpdTableR[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+    /* filled out Vpd table for all pdGains (interpolated) */
+    static uint8_t   vpdTableI[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+    uint8_t   *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+    uint8_t   minPwrT4[AR5416_NUM_PD_GAINS];
+    uint8_t   maxPwrT4[AR5416_NUM_PD_GAINS];
+    int16_t   vpdStep;
+    int16_t   tmpVal;
+    uint16_t  sizeCurrVpdTable, maxIndex, tgtIndex;
+    HAL_BOOL    match;
+    int16_t  minDelta = 0;
+    CHAN_CENTERS centers;
+
+    ar5416GetChannelCenters(ah, chan, &centers);
+
+    /* Trim numPiers for the number of populated channel Piers */
+    for (numPiers = 0; numPiers < availPiers; numPiers++) {
+        if (bChans[numPiers] == AR5416_BCHAN_UNUSED) {
+            break;
+        }
+    }
+
+    /* Find pier indexes around the current channel */
+    match = getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+                       bChans, numPiers, &idxL, &idxR);
+
+    if (match) {
+        /* Directly fill both vpd tables from the matching index */
+        for (i = 0; i < numXpdGains; i++) {
+            minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+            maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+            ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pRawDataSet[idxL].pwrPdg[i],
+                               pRawDataSet[idxL].vpdPdg[i], AR5416_PD_GAIN_ICEPTS, vpdTableI[i]);
+        }
+    } else {
+        for (i = 0; i < numXpdGains; i++) {
+            pVpdL = pRawDataSet[idxL].vpdPdg[i];
+            pPwrL = pRawDataSet[idxL].pwrPdg[i];
+            pVpdR = pRawDataSet[idxR].vpdPdg[i];
+            pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+            /* Start Vpd interpolation from the max of the minimum powers */
+            minPwrT4[i] = AH_MAX(pPwrL[0], pPwrR[0]);
+
+            /* End Vpd interpolation from the min of the max powers */
+            maxPwrT4[i] = AH_MIN(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
+            HALASSERT(maxPwrT4[i] > minPwrT4[i]);
+
+            /* Fill pier Vpds */
+            ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, AR5416_PD_GAIN_ICEPTS, vpdTableL[i]);
+            ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, AR5416_PD_GAIN_ICEPTS, vpdTableR[i]);
+
+            /* Interpolate the final vpd */
+            for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+                vpdTableI[i][j] = (uint8_t)(interpolate((uint16_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+                    bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j]));
+            }
+        }
+    }
+    *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+    k = 0; /* index for the final table */
+    for (i = 0; i < numXpdGains; i++) {
+        if (i == (numXpdGains - 1)) {
+            pPdGainBoundaries[i] = (uint16_t)(maxPwrT4[i] / 2);
+        } else {
+            pPdGainBoundaries[i] = (uint16_t)((maxPwrT4[i] + minPwrT4[i+1]) / 4);
+        }
+
+        pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+       /* NB: only applies to owl 1.0 */
+        if ((i == 0) && !AR_SREV_OWL_20_OR_LATER(ah) ) {
+           /*
+             * fix the gain delta, but get a delta that can be applied to min to
+             * keep the upper power values accurate, don't think max needs to
+             * be adjusted because should not be at that area of the table?
+            */
+            minDelta = pPdGainBoundaries[0] - 23;
+            pPdGainBoundaries[0] = 23;
+        }
+        else {
+            minDelta = 0;
+        }
+
+        /* Find starting index for this pdGain */
+        if (i == 0) {
+            ss = 0; /* for the first pdGain, start from index 0 */
+        } else {
+           /* need overlap entries extrapolated below. */
+            ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta);
+        }
+        vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+        vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+        /*
+         *-ve ss indicates need to extrapolate data below for this pdGain
+         */
+        while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+            tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+            pPDADCValues[k++] = (uint8_t)((tmpVal < 0) ? 0 : tmpVal);
+            ss++;
+        }
+
+        sizeCurrVpdTable = (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 +1);
+        tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2));
+        maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
+
+        while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+            pPDADCValues[k++] = vpdTableI[i][ss++];
+        }
+
+        vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]);
+        vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+        /*
+         * for last gain, pdGainBoundary == Pmax_t2, so will
+         * have to extrapolate
+         */
+        if (tgtIndex > maxIndex) {  /* need to extrapolate above */
+            while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+                tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+                          (ss - maxIndex +1) * vpdStep));
+                pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ? 255 : tmpVal);
+                ss++;
+            }
+        }               /* extrapolated above */
+    }                   /* for all pdGainUsed */
+
+    /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */
+    while (i < AR5416_PD_GAINS_IN_MASK) {
+        pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
+        i++;
+    }
+
+    while (k < AR5416_NUM_PDADC_VALUES) {
+        pPDADCValues[k] = pPDADCValues[k-1];
+        k++;
+    }
+    return;
+}
+
+/**************************************************************
+ * getLowerUppderIndex
+ *
+ * Return indices surrounding the value in sorted integer lists.
+ * Requirement: the input list must be monotonically increasing
+ *     and populated up to the list size
+ * Returns: match is set if an index in the array matches exactly
+ *     or a the target is before or after the range of the array.
+ */
+HAL_BOOL
+getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
+                   uint16_t *indexL, uint16_t *indexR)
+{
+    uint16_t i;
+
+    /*
+     * Check first and last elements for beyond ordered array cases.
+     */
+    if (target <= pList[0]) {
+        *indexL = *indexR = 0;
+        return AH_TRUE;
+    }
+    if (target >= pList[listSize-1]) {
+        *indexL = *indexR = (uint16_t)(listSize - 1);
+        return AH_TRUE;
+    }
+
+    /* look for value being near or between 2 values in list */
+    for (i = 0; i < listSize - 1; i++) {
+        /*
+         * If value is close to the current value of the list
+         * then target is not between values, it is one of the values
+         */
+        if (pList[i] == target) {
+            *indexL = *indexR = i;
+            return AH_TRUE;
+        }
+        /*
+         * Look for value being between current value and next value
+         * if so return these 2 values
+         */
+        if (target < pList[i + 1]) {
+            *indexL = i;
+            *indexR = (uint16_t)(i + 1);
+            return AH_FALSE;
+        }
+    }
+    HALASSERT(0);
+    return AH_FALSE;
+}
+
+/**************************************************************
+ * ar5416FillVpdTable
+ *
+ * Fill the Vpdlist for indices Pmax-Pmin
+ * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
+ */
+static HAL_BOOL
+ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
+                   uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
+{
+    uint16_t  i, k;
+    uint8_t   currPwr = pwrMin;
+    uint16_t  idxL = 0, idxR = 0;
+
+    HALASSERT(pwrMax > pwrMin);
+    for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
+        getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
+                           &(idxL), &(idxR));
+        if (idxR < 1)
+            idxR = 1;           /* extrapolate below */
+        if (idxL == numIntercepts - 1)
+            idxL = (uint16_t)(numIntercepts - 2);   /* extrapolate above */
+        if (pPwrList[idxL] == pPwrList[idxR])
+            k = pVpdList[idxL];
+        else
+            k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
+                  (pPwrList[idxR] - pPwrList[idxL]) );
+        HALASSERT(k < 256);
+        pRetVpdList[i] = (uint8_t)k;
+        currPwr += 2;               /* half dB steps */
+    }
+
+    return AH_TRUE;
+}
+
+/**************************************************************************
+ * interpolate
+ *
+ * Returns signed interpolated or the scaled up interpolated value
+ */
+static int16_t
+interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
+            int16_t targetLeft, int16_t targetRight)
+{
+    int16_t rv;
+
+    if (srcRight == srcLeft) {
+        rv = targetLeft;
+    } else {
+        rv = (int16_t)( ((target - srcLeft) * targetRight +
+              (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
+    }
+    return rv;
+}
+
+static void
+ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       uint32_t phymode;
+       HAL_HT_MACMODE macmode;         /* MAC - 20/40 mode */
+
+       if (!IS_CHAN_HT(chan))
+               return;
+
+       /* Enable 11n HT, 20 MHz */
+       phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
+               | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
+
+       /* Configure baseband for dynamic 20/40 operation */
+       if (IS_CHAN_HT40(chan)) {
+               phymode |= AR_PHY_FC_DYN2040_EN | AR_PHY_FC_SHORT_GI_40;
+
+               /* Configure control (primary) channel at +-10MHz */
+               if ((chan->channelFlags & CHANNEL_HT40PLUS))
+                       phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+#if 0
+               /* Configure 20/25 spacing */
+               if (ht->ht_extprotspacing == HAL_HT_EXTPROTSPACING_25)
+                       phymode |= AR_PHY_FC_DYN2040_EXT_CH;
+#endif
+               macmode = HAL_HT_MACMODE_2040;
+       } else
+               macmode = HAL_HT_MACMODE_20;
+       OS_REG_WRITE(ah, AR_PHY_TURBO, phymode);
+
+       /* Configure MAC for 20/40 operation */
+       ar5416Set11nMac2040(ah, macmode);
+
+       /* global transmit timeout (25 TUs default)*/
+       /* XXX - put this elsewhere??? */
+       OS_REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S) ;
+
+       /* carrier sense timeout */
+       OS_REG_SET_BIT(ah, AR_GTTM, AR_GTTM_CST_USEC);
+       OS_REG_WRITE(ah, AR_CST, 1 << AR_CST_TIMEOUT_LIMIT_S);
+}
+
+void
+ar5416GetChannelCenters(struct ath_hal *ah,
+       HAL_CHANNEL_INTERNAL *chan, CHAN_CENTERS *centers)
+{
+       centers->ctl_center = chan->channel;
+       centers->synth_center = chan->channel;
+       /*
+        * In 20/40 phy mode, the center frequency is
+        * "between" the control and extension channels.
+        */
+       if (chan->channelFlags & CHANNEL_HT40PLUS) {
+               centers->synth_center += HT40_CHANNEL_CENTER_SHIFT;
+               centers->ext_center =
+                   centers->synth_center + HT40_CHANNEL_CENTER_SHIFT;
+       } else if (chan->channelFlags & CHANNEL_HT40MINUS) {
+               centers->synth_center -= HT40_CHANNEL_CENTER_SHIFT;
+               centers->ext_center =
+                   centers->synth_center - HT40_CHANNEL_CENTER_SHIFT;
+       } else {
+               centers->ext_center = chan->channel;
+       }
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416_xmit.c      2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,698 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416_xmit.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_desc.h"
+#include "ah_internal.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+#include "ar5416/ar5416desc.h"
+
+/*
+ * Stop transmit on the specified queue
+ */
+HAL_BOOL
+ar5416StopTxDma(struct ath_hal *ah, u_int q)
+{
+#define        STOP_DMA_TIMEOUT        4000    /* us */
+#define        STOP_DMA_ITER           100     /* us */
+       u_int i;
+
+       HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
+
+       HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
+
+       OS_REG_WRITE(ah, AR_Q_TXD, 1 << q);
+       for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) {
+               if (ar5212NumTxPending(ah, q) == 0)
+                       break;
+               OS_DELAY(STOP_DMA_ITER);
+       }
+#ifdef AH_DEBUG
+       if (i == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: queue %u DMA did not stop in 400 msec\n", __func__, q);
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__,
+                   OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE),
+                   OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q)));
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n",
+                   __func__, OS_REG_READ(ah, AR_QMISC(q)),
+                   OS_REG_READ(ah, AR_QRDYTIMECFG(q)),
+                   OS_REG_READ(ah, AR_Q_RDYTIMESHDN));
+       }
+#endif /* AH_DEBUG */
+
+       /* ar5416 and up can kill packets at the PCU level */
+       if (ar5212NumTxPending(ah, q)) {
+               uint32_t j;
+
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
+                   "%s: Num of pending TX Frames %d on Q %d\n",
+                   __func__, ar5212NumTxPending(ah, q), q);
+
+               /* Kill last PCU Tx Frame */
+               /* TODO - save off and restore current values of Q1/Q2? */
+               for (j = 0; j < 2; j++) {
+                       uint32_t tsfLow = OS_REG_READ(ah, AR_TSF_L32);
+                       OS_REG_WRITE(ah, AR_QUIET2,
+                           SM(10, AR_QUIET2_QUIET_DUR));
+                       OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100);
+                       OS_REG_WRITE(ah, AR_NEXT_QUIET, tsfLow >> 10);
+                       OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
+
+                       if ((OS_REG_READ(ah, AR_TSF_L32)>>10) == (tsfLow>>10))
+                               break;
+
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: TSF moved while trying to set quiet time "
+                           "TSF: 0x%08x\n", __func__, tsfLow);
+                       HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */
+               }
+
+               OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);
+
+               /* Allow the quiet mechanism to do its work */
+               OS_DELAY(200);
+               OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
+
+               /* Verify the transmit q is empty */
+               for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) {
+                       if (ar5212NumTxPending(ah, q) == 0)
+                               break;
+                       OS_DELAY(STOP_DMA_ITER);
+               }
+               if (i == 0) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: Failed to stop Tx DMA in %d msec after killing"
+                           " last frame\n", __func__, STOP_DMA_TIMEOUT / 1000);
+               }
+               OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);
+       }
+
+       OS_REG_WRITE(ah, AR_Q_TXD, 0);
+       return (i != 0);
+#undef STOP_DMA_ITER
+#undef STOP_DMA_TIMEOUT
+}
+
+#define VALID_KEY_TYPES \
+        ((1 << HAL_KEY_TYPE_CLEAR) | (1 << HAL_KEY_TYPE_WEP)|\
+         (1 << HAL_KEY_TYPE_AES)   | (1 << HAL_KEY_TYPE_TKIP))
+#define isValidKeyType(_t)      ((1 << (_t)) & VALID_KEY_TYPES)
+
+#define set11nTries(_series, _index) \
+        (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
+
+#define set11nRate(_series, _index) \
+        (SM((_series)[_index].Rate, AR_XmitRate##_index))
+
+#define set11nPktDurRTSCTS(_series, _index) \
+        (SM((_series)[_index].PktDuration, AR_PacketDur##_index) |\
+         ((_series)[_index].RateFlags & HAL_RATESERIES_RTS_CTS   ?\
+         AR_RTSCTSQual##_index : 0))
+
+#define set11nRateFlags(_series, _index) \
+        ((_series)[_index].RateFlags & HAL_RATESERIES_2040 ? AR_2040_##_index : 0) \
+        |((_series)[_index].RateFlags & HAL_RATESERIES_HALFGI ? AR_GI##_index : 0) \
+        |SM((_series)[_index].ChSel, AR_ChainSel##_index)
+
+/*
+ * Descriptor Access Functions
+ */
+
+#define VALID_PKT_TYPES \
+        ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\
+         (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\
+         (1<<HAL_PKT_TYPE_BEACON)|(1<<HAL_PKT_TYPE_AMPDU))
+#define isValidPktType(_t)      ((1<<(_t)) & VALID_PKT_TYPES)
+#define VALID_TX_RATES \
+        ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\
+         (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\
+         (1<<0x1d)|(1<<0x18)|(1<<0x1c))
+#define isValidTxRate(_r)       ((1<<(_r)) & VALID_TX_RATES)
+
+HAL_BOOL
+ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int pktLen,
+       u_int hdrLen,
+       HAL_PKT_TYPE type,
+       u_int txPower,
+       u_int txRate0, u_int txTries0,
+       u_int keyIx,
+       u_int antMode,
+       u_int flags,
+       u_int rtsctsRate,
+       u_int rtsctsDuration,
+       u_int compicvLen,
+       u_int compivLen,
+       u_int comp)
+{
+#define        RTSCTS  (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       struct ath_hal_5416 *ahp = AH5416(ah);
+
+       (void) hdrLen;
+
+       HALASSERT(txTries0 != 0);
+       HALASSERT(isValidPktType(type));
+       HALASSERT(isValidTxRate(txRate0));
+       HALASSERT((flags & RTSCTS) != RTSCTS);
+       /* XXX validate antMode */
+
+        txPower = (txPower + AH5212(ah)->ah_txPowerIndexOffset);
+        if (txPower > 63)
+               txPower = 63;
+
+       ads->ds_ctl0 = (pktLen & AR_FrameLen)
+                    | (txPower << AR_XmitPower_S)
+                    | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
+                    | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+                    | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+                    ;
+       ads->ds_ctl1 = (type << AR_FrameType_S)
+                    | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0)
+                     ;
+       ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0)
+                    | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEn : 0)
+                    ;
+       ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S)
+                    ;
+       ads->ds_ctl4 = 0;
+       ads->ds_ctl5 = 0;
+       ads->ds_ctl6 = 0;
+       ads->ds_ctl7 = SM(ahp->ah_tx_chainmask, AR_ChainSel0)
+                    | SM(ahp->ah_tx_chainmask, AR_ChainSel1)
+                    | SM(ahp->ah_tx_chainmask, AR_ChainSel2)
+                    | SM(ahp->ah_tx_chainmask, AR_ChainSel3)
+                    ;
+       ads->ds_ctl8 = 0;
+       ads->ds_ctl9 = (txPower << 24);         /* XXX? */
+       ads->ds_ctl10 = (txPower << 24);        /* XXX? */
+       ads->ds_ctl11 = (txPower << 24);        /* XXX? */
+       if (keyIx != HAL_TXKEYIX_INVALID) {
+               /* XXX validate key index */
+               ads->ds_ctl1 |= SM(keyIx, AR_DestIdx);
+               ads->ds_ctl0 |= AR_DestIdxValid;
+               ads->ds_ctl6 |= SM(ahp->ah_keytype[keyIx], AR_EncrType);
+       }
+       if (flags & RTSCTS) {
+               if (!isValidTxRate(rtsctsRate)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: invalid rts/cts rate 0x%x\n",
+                           __func__, rtsctsRate);
+                       return AH_FALSE;
+               }
+               /* XXX validate rtsctsDuration */
+               ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0)
+                            | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0)
+                            ;
+               ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur);
+               ads->ds_ctl7 |= (rtsctsRate << AR_RTSCTSRate_S);
+       }
+       return AH_TRUE;
+#undef RTSCTS
+}
+
+HAL_BOOL
+ar5416SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int txRate1, u_int txTries1,
+       u_int txRate2, u_int txTries2,
+       u_int txRate3, u_int txTries3)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       if (txTries1) {
+               HALASSERT(isValidTxRate(txRate1));
+               ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1);
+               ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S);
+       }
+       if (txTries2) {
+               HALASSERT(isValidTxRate(txRate2));
+               ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2);
+               ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S);
+       }
+       if (txTries3) {
+               HALASSERT(isValidTxRate(txRate3));
+               ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3);
+               ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S);
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
+       const struct ath_desc *ds0)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       HALASSERT((segLen &~ AR_BufLen) == 0);
+
+       if (firstSeg) {
+               /*
+                * First descriptor, don't clobber xmit control data
+                * setup by ar5212SetupTxDesc.
+                */
+               ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
+       } else if (lastSeg) {           /* !firstSeg && lastSeg */
+               /*
+                * Last descriptor in a multi-descriptor frame,
+                * copy the multi-rate transmit parameters from
+                * the first frame for processing on completion.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 = segLen;
+#ifdef AH_NEED_DESC_SWAP
+               ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2);
+               ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3);
+#else
+               ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+               ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+#endif
+       } else {                        /* !firstSeg && !lastSeg */
+               /*
+                * Intermediate descriptor in a multi-descriptor frame.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 = segLen | AR_TxMore;
+               ads->ds_ctl2 = 0;
+               ads->ds_ctl3 = 0;
+       }
+       /* XXX only on last descriptor? */
+       OS_MEMZERO(ads->u.tx.status, sizeof(ads->u.tx.status));
+       return AH_TRUE;
+}
+
+#if 0
+
+HAL_BOOL
+ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int pktLen,
+       u_int hdrLen,
+       HAL_PKT_TYPE type,
+       u_int keyIx,
+       HAL_CIPHER cipher,
+       uint8_t delims,
+       u_int segLen,
+       HAL_BOOL firstSeg,
+       HAL_BOOL lastSeg)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
+
+       int isaggr = 0;
+
+       (void) hdrLen;
+       (void) ah;
+
+       HALASSERT((segLen &~ AR_BufLen) == 0);
+
+       HALASSERT(isValidPktType(type));
+       if (type == HAL_PKT_TYPE_AMPDU) {
+               type = HAL_PKT_TYPE_NORMAL;
+               isaggr = 1;
+       }
+
+       if (!firstSeg) {
+               ath_hal_memzero(ds->ds_hw, AR5416_DESC_TX_CTL_SZ);
+       }
+
+       ads->ds_ctl0 = (pktLen & AR_FrameLen);
+       ads->ds_ctl1 = (type << AR_FrameType_S)
+                       | (isaggr ? (AR_IsAggr | AR_MoreAggr) : 0);
+       ads->ds_ctl2 = 0;
+       ads->ds_ctl3 = 0;
+       if (keyIx != HAL_TXKEYIX_INVALID) {
+               /* XXX validate key index */
+               ads->ds_ctl1 |= SM(keyIx, AR_DestIdx);
+               ads->ds_ctl0 |= AR_DestIdxValid;
+       }
+
+       ads->ds_ctl6 = SM(keyType[cipher], AR_EncrType);
+       if (isaggr) {
+               ads->ds_ctl6 |= SM(delims, AR_PadDelim);
+       }
+
+       if (firstSeg) {
+               ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
+       } else if (lastSeg) {           /* !firstSeg && lastSeg */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 |= segLen;
+       } else {                        /* !firstSeg && !lastSeg */
+               /*
+                * Intermediate descriptor in a multi-descriptor frame.
+                */
+               ads->ds_ctl0 = 0;
+               ads->ds_ctl1 |= segLen | AR_TxMore;
+       }
+       ds_txstatus[0] = ds_txstatus[1] = 0;
+       ds_txstatus[9] &= ~AR_TxDone;
+
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+       u_int aggrLen, u_int flags, u_int txPower,
+       u_int txRate0, u_int txTries0, u_int antMode,
+       u_int rtsctsRate, u_int rtsctsDuration)
+{
+#define RTSCTS  (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       struct ath_hal_5212 *ahp = AH5212(ah);
+
+       HALASSERT(txTries0 != 0);
+       HALASSERT(isValidTxRate(txRate0));
+       HALASSERT((flags & RTSCTS) != RTSCTS);
+       /* XXX validate antMode */
+
+       txPower = (txPower + ahp->ah_txPowerIndexOffset );
+       if(txPower > 63)  txPower=63;
+
+       ads->ds_ctl0 |= (txPower << AR_XmitPower_S)
+               | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
+               | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+               | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0);
+       ads->ds_ctl1 |= (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0);
+       ads->ds_ctl2 |= SM(txTries0, AR_XmitDataTries0);
+       ads->ds_ctl3 |= (txRate0 << AR_XmitRate0_S);
+       ads->ds_ctl7 = SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel0)
+               | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel1)
+               | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel2)
+               | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel3);
+
+       /* NB: no V1 WAR */
+       ads->ds_ctl8 = 0;
+       ads->ds_ctl9 = (txPower << 24);
+       ads->ds_ctl10 = (txPower << 24);
+       ads->ds_ctl11 = (txPower << 24);
+
+       ads->ds_ctl6 &= ~(0xffff);
+       ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
+
+       if (flags & RTSCTS) {
+               /* XXX validate rtsctsDuration */
+               ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0)
+                       | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0);
+               ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur);
+       }
+
+       return AH_TRUE;
+#undef RTSCTS
+}
+
+HAL_BOOL
+ar5416SetupLastTxDesc(struct ath_hal *ah, struct ath_desc *ds,
+               const struct ath_desc *ds0)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       ads->ds_ctl1 &= ~AR_MoreAggr;
+       ads->ds_ctl6 &= ~AR_PadDelim;
+
+       /* hack to copy rate info to last desc for later processing */
+#ifdef AH_NEED_DESC_SWAP
+       ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2);
+       ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3);
+#else
+       ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+       ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+#endif
+
+       return AH_TRUE;
+}
+#endif /* 0 */
+
+#ifdef AH_NEED_DESC_SWAP
+/* Swap transmit descriptor */
+static __inline void
+ar5416SwapTxDesc(struct ath_desc *ds)
+{
+       ds->ds_data = __bswap32(ds->ds_data);
+       ds->ds_ctl0 = __bswap32(ds->ds_ctl0);
+       ds->ds_ctl1 = __bswap32(ds->ds_ctl1);
+       ds->ds_hw[0] = __bswap32(ds->ds_hw[0]);
+       ds->ds_hw[1] = __bswap32(ds->ds_hw[1]);
+       ds->ds_hw[2] = __bswap32(ds->ds_hw[2]);
+       ds->ds_hw[3] = __bswap32(ds->ds_hw[3]);
+}
+#endif
+
+/*
+ * Processing of HW TX descriptor.
+ */
+HAL_STATUS
+ar5416ProcTxDesc(struct ath_hal *ah,
+       struct ath_desc *ds, struct ath_tx_status *ts)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
+
+#ifdef AH_NEED_DESC_SWAP
+       if ((ds_txstatus[9] & __bswap32(AR_TxDone)) == 0)
+               return HAL_EINPROGRESS;
+       ar5416SwapTxDesc(ds);
+#else
+       if ((ds_txstatus[9] & AR_TxDone) == 0)
+               return HAL_EINPROGRESS;
+#endif
+
+       /* Update software copies of the HW status */
+       ts->ts_seqnum = MS(ds_txstatus[9], AR_SeqNum);
+       ts->ts_tstamp = AR_SendTimestamp(ds_txstatus);
+
+       ts->ts_status = 0;
+       if (ds_txstatus[1] & AR_ExcessiveRetries)
+               ts->ts_status |= HAL_TXERR_XRETRY;
+       if (ds_txstatus[1] & AR_Filtered)
+               ts->ts_status |= HAL_TXERR_FILT;
+       if (ds_txstatus[1] & AR_FIFOUnderrun)
+               ts->ts_status |= HAL_TXERR_FIFO;
+       if (ds_txstatus[9] & AR_TxOpExceeded)
+               ts->ts_status |= HAL_TXERR_XTXOP;
+       if (ds_txstatus[1] & AR_TxTimerExpired)
+               ts->ts_status |= HAL_TXERR_TIMER_EXPIRED;
+
+       ts->ts_flags  = 0;
+       if (ds_txstatus[0] & AR_TxBaStatus) {
+               ts->ts_flags |= HAL_TX_BA;
+               ts->ts_ba_low = AR_BaBitmapLow(ds_txstatus);
+               ts->ts_ba_high = AR_BaBitmapHigh(ds_txstatus);
+       }
+       if (ds->ds_ctl1 & AR_IsAggr)
+               ts->ts_flags |= HAL_TX_AGGR;
+       if (ds_txstatus[1] & AR_DescCfgErr)
+               ts->ts_flags |= HAL_TX_DESC_CFG_ERR;
+       if (ds_txstatus[1] & AR_TxDataUnderrun)
+               ts->ts_flags |= HAL_TX_DATA_UNDERRUN;
+       if (ds_txstatus[1] & AR_TxDelimUnderrun)
+               ts->ts_flags |= HAL_TX_DELIM_UNDERRUN;
+
+       /*
+        * Extract the transmit rate used and mark the rate as
+        * ``alternate'' if it wasn't the series 0 rate.
+        */
+       ts->ts_finaltsi =  MS(ds_txstatus[9], AR_FinalTxIdx);
+       switch (ts->ts_finaltsi) {
+       case 0:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0);
+               break;
+       case 1:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       case 2:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       case 3:
+               ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3) |
+                       HAL_TXSTAT_ALTRATE;
+               break;
+       }
+
+       ts->ts_rssi = MS(ds_txstatus[5], AR_TxRSSICombined);
+       ts->ts_rssi_ctl[0] = MS(ds_txstatus[0], AR_TxRSSIAnt00);
+       ts->ts_rssi_ctl[1] = MS(ds_txstatus[0], AR_TxRSSIAnt01);
+       ts->ts_rssi_ctl[2] = MS(ds_txstatus[0], AR_TxRSSIAnt02);
+       ts->ts_rssi_ext[0] = MS(ds_txstatus[5], AR_TxRSSIAnt10);
+       ts->ts_rssi_ext[1] = MS(ds_txstatus[5], AR_TxRSSIAnt11);
+       ts->ts_rssi_ext[2] = MS(ds_txstatus[5], AR_TxRSSIAnt12);
+       ts->ts_evm0 = AR_TxEVM0(ds_txstatus);
+       ts->ts_evm1 = AR_TxEVM1(ds_txstatus);
+       ts->ts_evm2 = AR_TxEVM2(ds_txstatus);
+
+       ts->ts_shortretry = MS(ds_txstatus[1], AR_RTSFailCnt);
+       ts->ts_longretry = MS(ds_txstatus[1], AR_DataFailCnt);
+       /*
+        * The retry count has the number of un-acked tries for the
+        * final series used.  When doing multi-rate retry we must
+        * fixup the retry count by adding in the try counts for
+        * each series that was fully-processed.  Beware that this
+        * takes values from the try counts in the final descriptor.
+        * These are not required by the hardware.  We assume they
+        * are placed there by the driver as otherwise we have no
+        * access and the driver can't do the calculation because it
+        * doesn't know the descriptor format.
+        */
+       switch (ts->ts_finaltsi) {
+       case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2);
+       case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1);
+       case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0);
+       }
+
+       /*
+        * These fields are not used. Zero these to preserve compatability
+        * with existing drivers.
+        */
+       ts->ts_virtcol = MS(ads->ds_ctl1, AR_VirtRetryCnt);
+       ts->ts_antenna = 0; /* We don't switch antennas on Owl*/
+
+       /* handle tx trigger level changes internally */
+       if ((ts->ts_status & HAL_TXERR_FIFO) ||
+           (ts->ts_flags & (HAL_TX_DATA_UNDERRUN | HAL_TX_DELIM_UNDERRUN)))
+               ar5212UpdateTxTrigLevel(ah, AH_TRUE);
+
+       return HAL_OK;
+}
+
+#if 0
+HAL_BOOL
+ar5416SetGlobalTxTimeout(struct ath_hal *ah, u_int tu)
+{
+       struct ath_hal_5416 *ahp = AH5416(ah);
+
+       if (tu > 0xFFFF) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad global tx timeout %u\n",
+                   __func__, tu);
+               /* restore default handling */
+               ahp->ah_globaltxtimeout = (u_int) -1;
+               return AH_FALSE;
+       }
+       OS_REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
+       ahp->ah_globaltxtimeout = tu;
+       return AH_TRUE;
+}
+
+u_int
+ar5416GetGlobalTxTimeout(struct ath_hal *ah)
+{
+       return MS(OS_REG_READ(ah, AR_GTXTO), AR_GTXTO_TIMEOUT_LIMIT);
+}
+
+void
+ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds,
+        u_int durUpdateEn, u_int rtsctsRate,
+       HAL_11N_RATE_SERIES series[], u_int nseries)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       HALASSERT(nseries == 4);
+       (void)nseries;
+
+
+       ads->ds_ctl2 = set11nTries(series, 0)
+                    | set11nTries(series, 1)
+                    | set11nTries(series, 2)
+                    | set11nTries(series, 3)
+                    | (durUpdateEn ? AR_DurUpdateEn : 0);
+
+       ads->ds_ctl3 = set11nRate(series, 0)
+                    | set11nRate(series, 1)
+                    | set11nRate(series, 2)
+                    | set11nRate(series, 3);
+
+       ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
+                    | set11nPktDurRTSCTS(series, 1);
+
+       ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
+                    | set11nPktDurRTSCTS(series, 3);
+
+       ads->ds_ctl7 = set11nRateFlags(series, 0)
+                    | set11nRateFlags(series, 1)
+                    | set11nRateFlags(series, 2)
+                    | set11nRateFlags(series, 3)
+                    | SM(rtsctsRate, AR_RTSCTSRate);
+
+       /*
+        * Enable RTSCTS if any of the series is flagged for RTSCTS,
+        * but only if CTS is not enabled.
+        */
+       /*
+        * FIXME : the entire RTS/CTS handling should be moved to this
+        * function (by passing the global RTS/CTS flags to this function).
+        * currently it is split between this function and the
+        * setupFiirstDescriptor. with this current implementation there
+        * is an implicit assumption that setupFirstDescriptor is called
+        * before this function.
+        */
+       if (((series[0].RateFlags & HAL_RATESERIES_RTS_CTS) ||
+            (series[1].RateFlags & HAL_RATESERIES_RTS_CTS) ||
+            (series[2].RateFlags & HAL_RATESERIES_RTS_CTS) ||
+            (series[3].RateFlags & HAL_RATESERIES_RTS_CTS) )  &&
+           (ads->ds_ctl0 & AR_CTSEnable) == 0) {
+               ads->ds_ctl0 |= AR_RTSEnable;
+               ads->ds_ctl0 &= ~AR_CTSEnable;
+       }
+}
+
+void
+ar5416Set11nAggrMiddle(struct ath_hal *ah, struct ath_desc *ds, u_int numDelims)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+       uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
+
+       ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+
+       ads->ds_ctl6 &= ~AR_PadDelim;
+       ads->ds_ctl6 |= SM(numDelims, AR_PadDelim);
+       ads->ds_ctl6 &= ~AR_AggrLen;
+
+       /*
+        * Clear the TxDone status here, may need to change
+        * func name to reflect this
+        */
+       ds_txstatus[9] &= ~AR_TxDone;
+}
+
+void
+ar5416Clr11nAggr(struct ath_hal *ah, struct ath_desc *ds)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+       ads->ds_ctl6 &= ~AR_PadDelim;
+       ads->ds_ctl6 &= ~AR_AggrLen;
+}
+
+void
+ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds,
+                                                  u_int burstDuration)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       ads->ds_ctl2 &= ~AR_BurstDur;
+       ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
+}
+#endif
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416desc.h       2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416desc.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _ATH_AR5416_DESC_H_
+#define _ATH_AR5416_DESC_H
+
+/*
+ * Hardware-specific descriptor structures.
+ */
+#include "ah_desc.h"
+
+/* XXX Need to replace this with a dynamic
+ * method of determining Owl2 if possible
+ */
+#define _get_index(_ah) ( IS_5416V1(_ah)  ? -4 : 0 )
+#define AR5416_DS_TXSTATUS(_ah, _ads) \
+       ((uint32_t*)(&(_ads)->u.tx.status[_get_index(_ah)]))
+#define AR5416_DS_TXSTATUS_CONST(_ah, _ads) \
+       ((const uint32_t*)(&(_ads)->u.tx.status[_get_index(_ah)]))
+
+#define AR5416_NUM_TX_STATUS   10 /* Number of TX status words */
+/* Clear the whole descriptor */
+#define AR5416_DESC_TX_CTL_SZ  sizeof(struct ar5416_tx_desc)
+
+struct ar5416_tx_desc { /* tx desc has 12 control words + 10 status words */
+       uint32_t        ctl2;
+       uint32_t        ctl3;
+       uint32_t        ctl4;
+       uint32_t        ctl5;
+       uint32_t        ctl6;
+       uint32_t        ctl7;
+       uint32_t        ctl8;
+       uint32_t        ctl9;
+       uint32_t        ctl10;
+       uint32_t        ctl11;
+       uint32_t        status[AR5416_NUM_TX_STATUS];
+};
+
+struct ar5416_rx_desc { /* rx desc has 2 control words + 9 status words */
+       uint32_t        status0;
+       uint32_t        status1;
+       uint32_t        status2;
+       uint32_t        status3;
+       uint32_t        status4;
+       uint32_t        status5;
+       uint32_t        status6;
+       uint32_t        status7;
+       uint32_t        status8;
+};
+
+
+struct ar5416_desc {
+       uint32_t   ds_link;    /* link pointer */
+       uint32_t   ds_data;    /* data buffer pointer */
+       uint32_t   ds_ctl0;    /* DMA control 0 */
+       uint32_t   ds_ctl1;    /* DMA control 1 */
+       union {
+               struct ar5416_tx_desc tx;
+               struct ar5416_rx_desc rx;
+       } u;
+} __packed;
+#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds))
+#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds))
+
+#define ds_ctl2     u.tx.ctl2
+#define ds_ctl3     u.tx.ctl3
+#define ds_ctl4     u.tx.ctl4
+#define ds_ctl5     u.tx.ctl5
+#define ds_ctl6     u.tx.ctl6
+#define ds_ctl7     u.tx.ctl7
+#define ds_ctl8     u.tx.ctl8
+#define ds_ctl9     u.tx.ctl9
+#define ds_ctl10    u.tx.ctl10
+#define ds_ctl11    u.tx.ctl11
+
+#define ds_rxstatus0    u.rx.status0
+#define ds_rxstatus1    u.rx.status1
+#define ds_rxstatus2    u.rx.status2
+#define ds_rxstatus3    u.rx.status3
+#define ds_rxstatus4    u.rx.status4
+#define ds_rxstatus5    u.rx.status5
+#define ds_rxstatus6    u.rx.status6
+#define ds_rxstatus7    u.rx.status7
+#define ds_rxstatus8    u.rx.status8
+
+/***********
+ * TX Desc *
+ ***********/
+
+/* ds_ctl0 */
+#define AR_FrameLen         0x00000fff
+#define AR_VirtMoreFrag     0x00001000
+#define AR_TxCtlRsvd00      0x0000e000
+#define AR_XmitPower        0x003f0000
+#define AR_XmitPower_S      16
+#define AR_RTSEnable        0x00400000
+#define AR_VEOL             0x00800000
+#define AR_ClrDestMask      0x01000000
+#define AR_TxCtlRsvd01      0x1e000000
+#define AR_TxIntrReq        0x20000000
+#define AR_DestIdxValid     0x40000000
+#define AR_CTSEnable        0x80000000
+
+/* ds_ctl1 */
+#define AR_BufLen           0x00000fff
+#define AR_TxMore           0x00001000
+#define AR_DestIdx          0x000fe000
+#define AR_DestIdx_S        13
+#define AR_FrameType        0x00f00000
+#define AR_FrameType_S      20
+#define AR_NoAck            0x01000000
+#define AR_InsertTS         0x02000000
+#define AR_CorruptFCS       0x04000000
+#define AR_ExtOnly          0x08000000
+#define AR_ExtAndCtl        0x10000000
+#define AR_MoreAggr         0x20000000
+#define AR_IsAggr           0x40000000
+#define AR_MoreRifs        0x80000000
+
+/* ds_ctl2 */
+#define AR_BurstDur         0x00007fff
+#define AR_BurstDur_S       0
+#define AR_DurUpdateEn      0x00008000
+#define AR_XmitDataTries0   0x000f0000
+#define AR_XmitDataTries0_S 16
+#define AR_XmitDataTries1   0x00f00000
+#define AR_XmitDataTries1_S 20
+#define AR_XmitDataTries2   0x0f000000
+#define AR_XmitDataTries2_S 24
+#define AR_XmitDataTries3   0xf0000000
+#define AR_XmitDataTries3_S 28
+
+/* ds_ctl3 */
+#define AR_XmitRate0        0x000000ff
+#define AR_XmitRate0_S      0
+#define AR_XmitRate1        0x0000ff00
+#define AR_XmitRate1_S      8
+#define AR_XmitRate2        0x00ff0000
+#define AR_XmitRate2_S      16
+#define AR_XmitRate3        0xff000000
+#define AR_XmitRate3_S      24
+
+/* ds_ctl4 */
+#define AR_PacketDur0       0x00007fff
+#define AR_PacketDur0_S     0
+#define AR_RTSCTSQual0      0x00008000
+#define AR_PacketDur1       0x7fff0000
+#define AR_PacketDur1_S     16
+#define AR_RTSCTSQual1      0x80000000
+
+/* ds_ctl5 */
+#define AR_PacketDur2       0x00007fff
+#define AR_PacketDur2_S     0
+#define AR_RTSCTSQual2      0x00008000
+#define AR_PacketDur3       0x7fff0000
+#define AR_PacketDur3_S     16
+#define AR_RTSCTSQual3      0x80000000
+
+/* ds_ctl6 */
+#define AR_AggrLen          0x0000ffff
+#define AR_AggrLen_S        0
+#define AR_TxCtlRsvd60      0x00030000
+#define AR_PadDelim         0x03fc0000
+#define AR_PadDelim_S       18
+#define AR_EncrType         0x0c000000
+#define AR_EncrType_S       26
+#define AR_TxCtlRsvd61      0xf0000000
+
+/* ds_ctl7 */
+#define AR_2040_0           0x00000001
+#define AR_GI0              0x00000002
+#define AR_ChainSel0        0x0000001c
+#define AR_ChainSel0_S      2
+#define AR_2040_1           0x00000020
+#define AR_GI1              0x00000040
+#define AR_ChainSel1        0x00000380
+#define AR_ChainSel1_S      7
+#define AR_2040_2           0x00000400
+#define AR_GI2              0x00000800
+#define AR_ChainSel2        0x00007000
+#define AR_ChainSel2_S      12
+#define AR_2040_3           0x00008000
+#define AR_GI3              0x00010000
+#define AR_ChainSel3        0x000e0000
+#define AR_ChainSel3_S      17
+#define AR_RTSCTSRate       0x0ff00000
+#define AR_RTSCTSRate_S     20
+#define        AR_STBC0            0x10000000
+#define        AR_STBC1            0x20000000
+#define        AR_STBC2            0x40000000
+#define        AR_STBC3            0x80000000
+
+/*************
+ * TX Status *
+ *************/
+
+/* ds_status0 */
+#define AR_TxRSSIAnt00      0x000000ff
+#define AR_TxRSSIAnt00_S    0
+#define AR_TxRSSIAnt01      0x0000ff00
+#define AR_TxRSSIAnt01_S    8
+#define AR_TxRSSIAnt02      0x00ff0000
+#define AR_TxRSSIAnt02_S    16
+#define AR_TxStatusRsvd00   0x3f000000
+#define AR_TxBaStatus       0x40000000
+#define AR_TxStatusRsvd01   0x80000000
+
+/* ds_status1 */
+#define AR_FrmXmitOK            0x00000001
+#define AR_ExcessiveRetries     0x00000002
+#define AR_FIFOUnderrun         0x00000004
+#define AR_Filtered             0x00000008
+#define AR_RTSFailCnt           0x000000f0
+#define AR_RTSFailCnt_S         4
+#define AR_DataFailCnt          0x00000f00
+#define AR_DataFailCnt_S        8
+#define AR_VirtRetryCnt         0x0000f000
+#define AR_VirtRetryCnt_S       12
+#define AR_TxDelimUnderrun      0x00010000
+#define AR_TxDelimUnderrun_S    13
+#define AR_TxDataUnderrun       0x00020000
+#define AR_TxDataUnderrun_S     14
+#define AR_DescCfgErr           0x00040000
+#define AR_DescCfgErr_S         15
+#define        AR_TxTimerExpired       0x00080000
+#define AR_TxStatusRsvd10       0xfff00000
+
+/* ds_status2 */
+#define AR_SendTimestamp(_ptr)   (_ptr)[2]
+
+/* ds_status3 */
+#define AR_BaBitmapLow(_ptr)     (_ptr)[3]
+
+/* ds_status4 */
+#define AR_BaBitmapHigh(_ptr)    (_ptr)[4]
+
+/* ds_status5 */
+#define AR_TxRSSIAnt10      0x000000ff
+#define AR_TxRSSIAnt10_S    0
+#define AR_TxRSSIAnt11      0x0000ff00
+#define AR_TxRSSIAnt11_S    8
+#define AR_TxRSSIAnt12      0x00ff0000
+#define AR_TxRSSIAnt12_S    16
+#define AR_TxRSSICombined   0xff000000
+#define AR_TxRSSICombined_S 24
+
+/* ds_status6 */
+#define AR_TxEVM0(_ptr)     (_ptr)[6]
+
+/* ds_status7 */
+#define AR_TxEVM1(_ptr)    (_ptr)[7]
+
+/* ds_status8 */
+#define AR_TxEVM2(_ptr)   (_ptr)[8]
+
+/* ds_status9 */
+#define AR_TxDone           0x00000001
+#define AR_SeqNum           0x00001ffe
+#define AR_SeqNum_S         1
+#define AR_TxStatusRsvd80   0x0001e000
+#define AR_TxOpExceeded     0x00020000
+#define AR_TxStatusRsvd81   0x001c0000
+#define AR_FinalTxIdx       0x00600000
+#define AR_FinalTxIdx_S     21
+#define AR_TxStatusRsvd82   0x01800000
+#define AR_PowerMgmt        0x02000000
+#define AR_TxStatusRsvd83   0xfc000000
+
+/***********
+ * RX Desc *
+ ***********/
+
+/* ds_ctl0 */
+#define AR_RxCTLRsvd00  0xffffffff
+
+/* ds_ctl1 */
+#define AR_BufLen       0x00000fff
+#define AR_RxCtlRsvd00  0x00001000
+#define AR_RxIntrReq    0x00002000
+#define AR_RxCtlRsvd01  0xffffc000
+
+/*************
+ * Rx Status *
+ *************/
+
+/* ds_status0 */
+#define AR_RxRSSIAnt00      0x000000ff
+#define AR_RxRSSIAnt00_S    0
+#define AR_RxRSSIAnt01      0x0000ff00
+#define AR_RxRSSIAnt01_S    8
+#define AR_RxRSSIAnt02      0x00ff0000
+#define AR_RxRSSIAnt02_S    16
+/* Rev specific */
+/* Owl 1.x only */
+#define AR_RxStatusRsvd00   0xff000000
+/* Owl 2.x only */
+#define AR_RxRate           0xff000000
+#define AR_RxRate_S         24
+
+/* ds_status1 */
+#define AR_DataLen          0x00000fff
+#define AR_RxMore           0x00001000
+#define AR_NumDelim         0x003fc000
+#define AR_NumDelim_S       14
+#define AR_RxStatusRsvd10   0xff800000
+
+/* ds_status2 */
+#define AR_RcvTimestamp     ds_rxstatus2
+
+/* ds_status3 */
+#define AR_GI               0x00000001
+#define AR_2040             0x00000002
+/* Rev specific */
+/* Owl 1.x only */
+#define AR_RxRateV1         0x000003fc
+#define AR_RxRateV1_S       2
+#define AR_Parallel40       0x00000400
+#define AR_RxStatusRsvd30   0xfffff800
+/* Owl 2.x only */
+#define AR_DupFrame        0x00000004
+#define AR_RxAntenna        0xffffff00
+#define AR_RxAntenna_S      8
+
+/* ds_status4 */
+#define AR_RxRSSIAnt10            0x000000ff
+#define AR_RxRSSIAnt10_S          0
+#define AR_RxRSSIAnt11            0x0000ff00
+#define AR_RxRSSIAnt11_S          8
+#define AR_RxRSSIAnt12            0x00ff0000
+#define AR_RxRSSIAnt12_S          16
+#define AR_RxRSSICombined         0xff000000
+#define AR_RxRSSICombined_S       24
+
+/* ds_status5 */
+#define AR_RxEVM0           ds_rxstatus5
+
+/* ds_status6 */
+#define AR_RxEVM1           ds_rxstatus6
+
+/* ds_status7 */
+#define AR_RxEVM2           ds_rxstatus7
+
+/* ds_status8 */
+#define AR_RxDone           0x00000001
+#define AR_RxFrameOK        0x00000002
+#define AR_CRCErr           0x00000004
+#define AR_DecryptCRCErr    0x00000008
+#define AR_PHYErr           0x00000010
+#define AR_MichaelErr       0x00000020
+#define AR_PreDelimCRCErr   0x00000040
+#define AR_RxStatusRsvd70   0x00000080
+#define AR_RxKeyIdxValid    0x00000100
+#define AR_KeyIdx           0x0000fe00
+#define AR_KeyIdx_S         9
+#define AR_PHYErrCode       0x0000ff00
+#define AR_PHYErrCode_S     8
+#define AR_RxMoreAggr       0x00010000
+#define AR_RxAggr           0x00020000
+#define AR_PostDelimCRCErr  0x00040000
+#define AR_RxStatusRsvd71   0x2ff80000
+#define        AR_HiRxChain        0x10000000
+#define AR_DecryptBusyErr   0x40000000
+#define AR_KeyMiss          0x80000000
+
+#define TXCTL_OFFSET(ah)       2
+#define TXCTL_NUMWORDS(ah)     (AR_SREV_5416_V20_OR_LATER(ah) ? 12 : 8)
+#define TXSTATUS_OFFSET(ah)    (AR_SREV_5416_V20_OR_LATER(ah) ? 14 : 10)
+#define TXSTATUS_NUMWORDS(ah)  10
+
+#define RXCTL_OFFSET(ah)       3
+#define RXCTL_NUMWORDS(ah)     1
+#define RXSTATUS_OFFSET(ah)    4
+#define RXSTATUS_NUMWORDS(ah)  9
+#define RXSTATUS_RATE(ah, ads) \
+       (AR_SREV_OWL_20_OR_LATER(ah) ? \
+        MS((ads)->ds_rxstatus0, AR_RxRate) : \
+        ((ads)->ds_rxstatus3 >> 2) & 0xFF)
+#define RXSTATUS_DUPLICATE(ah, ads) \
+       (AR_SREV_OWL_20_OR_LATER(ah) ?  \
+        MS((ads)->ds_rxstatus3, AR_Parallel40) : \
+        ((ads)->ds_rxstatus3 >> 10) & 0x1)
+#endif /* _ATH_AR5416_DESC_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416phy.h        2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416phy.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5416PHY_H_
+#define _DEV_ATH_AR5416PHY_H_
+
+#include "ar5212/ar5212phy.h"
+
+#define AR_PHY_CHIP_ID_REV_0    0x80        /* 5416 Rev 0 (owl 1.0) BB */
+#define AR_PHY_CHIP_ID_REV_1    0x81        /* 5416 Rev 1 (owl 2.0) BB */
+
+#define RFSILENT_BB             0x00002000      /* shush bb */
+#define AR_PHY_RESTART         0x9970      /* restart */
+#define AR_PHY_RESTART_DIV_GC   0x001C0000  /* bb_ant_fast_div_gc_limit */
+#define AR_PHY_RESTART_DIV_GC_S 18
+
+/* PLL settling times */
+#define RTC_PLL_SETTLE_DELAY           1000    /* 1 ms     */
+#define HT40_CHANNEL_CENTER_SHIFT      10      /* MHz      */
+
+#define AR_PHY_RFBUS_REQ        0x997C
+#define AR_PHY_RFBUS_REQ_EN     0x00000001
+
+#define AR_2040_MODE                0x8318
+#define AR_2040_JOINED_RX_CLEAR     0x00000001   // use ctl + ext rx_clear for cca
+
+#define AR_PHY_FC_TURBO_SHORT       0x00000002  /* Set short symbols to turbo mode setting */
+#define AR_PHY_FC_DYN2040_EN        0x00000004      /* Enable dyn 20/40 mode */
+#define AR_PHY_FC_DYN2040_PRI_ONLY  0x00000008      /* dyn 20/40 - primary only */
+#define AR_PHY_FC_DYN2040_PRI_CH    0x00000010      /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/
+#define AR_PHY_FC_DYN2040_EXT_CH    0x00000020      /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */
+#define AR_PHY_FC_HT_EN             0x00000040      /* ht enable */
+#define AR_PHY_FC_SHORT_GI_40       0x00000080      /* allow short GI for HT 40 */
+#define AR_PHY_FC_WALSH             0x00000100      /* walsh spatial spreading for 2 chains,2 streams TX */
+#define AR_PHY_FC_SINGLE_HT_LTF1    0x00000200      /* single length (4us) 1st HT long training symbol */
+
+#define AR_PHY_TIMING2      0x9810      /* Timing Control 2 */
+#define AR_PHY_TIMING2_USE_FORCE    0x00001000
+#define AR_PHY_TIMING2_FORCE_VAL    0x00000fff
+
+#define        AR_PHY_TIMING_CTRL4_CHAIN(_i) \
+       (AR_PHY_TIMING_CTRL4 + ((_i) << 12))
+#define        AR_PHY_TIMING_CTRL4_DO_CAL  0x10000         /* perform calibration */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F   /* Mask for kcos_theta-1 for q correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S   0   /* shift for Q_COFF */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0   /* Mask for sin_theta for i correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5   /* Shift for sin_theta for i correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE   0x800   /* enable IQ correction */
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000  /* Mask for max number of samples (logarithmic) */
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S   12  /* Shift for max number of samples */
+
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI   0x80000000
+#define        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER  0x40000000      /* Enable spur filter */
+#define        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK    0x20000000
+#define        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK   0x10000000
+
+#define AR_PHY_ADC_SERIAL_CTL       0x9830
+#define AR_PHY_SEL_INTERNAL_ADDAC   0x00000000
+#define AR_PHY_SEL_EXTERNAL_RADIO   0x00000001
+
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN    0x00003C00
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S  10
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN     0x0000001F
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S   0
+
+#define AR_PHY_EXT_CCA          0x99bc
+#define AR_PHY_EXT_CCA_CYCPWR_THR1      0x0000FE00
+#define AR_PHY_EXT_CCA_CYCPWR_THR1_S    9
+#define AR_PHY_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_EXT_MINCCA_PWR_S 23
+#define AR_PHY_EXT_CCA_THRESH62        0x007F0000
+#define AR_PHY_EXT_CCA_THRESH62_S      16
+#define AR9280_PHY_EXT_MINCCA_PWR       0x01FF0000
+#define AR9280_PHY_EXT_MINCCA_PWR_S     16
+
+#define AR_PHY_HALFGI           0x99D0      /* Timing control 3 */
+#define AR_PHY_HALFGI_DSC_MAN   0x0007FFF0
+#define AR_PHY_HALFGI_DSC_MAN_S 4
+#define AR_PHY_HALFGI_DSC_EXP   0x0000000F
+#define AR_PHY_HALFGI_DSC_EXP_S 0
+
+#define AR_PHY_HEAVY_CLIP_ENABLE    0x99E0
+
+#define AR_PHY_M_SLEEP      0x99f0      /* sleep control registers */
+#define AR_PHY_REFCLKDLY    0x99f4
+#define AR_PHY_REFCLKPD     0x99f8
+
+#define        AR_PHY_CALMODE          0x99f0
+/* Calibration Types */
+#define        AR_PHY_CALMODE_IQ               0x00000000
+#define        AR_PHY_CALMODE_ADC_GAIN         0x00000001
+#define        AR_PHY_CALMODE_ADC_DC_PER       0x00000002
+#define        AR_PHY_CALMODE_ADC_DC_INIT      0x00000003
+/* Calibration results */
+#define        AR_PHY_CAL_MEAS_0(_i)   (0x9c10 + ((_i) << 12))
+#define        AR_PHY_CAL_MEAS_1(_i)   (0x9c14 + ((_i) << 12))
+#define        AR_PHY_CAL_MEAS_2(_i)   (0x9c18 + ((_i) << 12))
+#define        AR_PHY_CAL_MEAS_3(_i)   (0x9c1c + ((_i) << 12))
+
+
+#define AR_PHY_CCA          0x9864
+#define AR_PHY_MINCCA_PWR   0x0FF80000
+#define AR_PHY_MINCCA_PWR_S 19
+#define AR9280_PHY_MINCCA_PWR       0x1FF00000
+#define AR9280_PHY_MINCCA_PWR_S     20
+#define AR9280_PHY_CCA_THRESH62     0x000FF000
+#define AR9280_PHY_CCA_THRESH62_S   12
+
+#define AR_PHY_CH1_CCA          0xa864
+#define AR_PHY_CH1_MINCCA_PWR   0x0FF80000
+#define AR_PHY_CH1_MINCCA_PWR_S 19
+#define AR_PHY_CCA_THRESH62     0x0007F000
+#define AR_PHY_CCA_THRESH62_S   12
+#define AR9280_PHY_CH1_MINCCA_PWR   0x1FF00000
+#define AR9280_PHY_CH1_MINCCA_PWR_S 20
+
+#define AR_PHY_CH2_CCA          0xb864
+#define AR_PHY_CH2_MINCCA_PWR   0x0FF80000
+#define AR_PHY_CH2_MINCCA_PWR_S 19
+
+#define AR_PHY_CH1_EXT_CCA          0xa9bc
+#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
+
+#define AR_PHY_CH2_EXT_CCA          0xb9bc
+#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
+
+#define AR_PHY_RX_CHAINMASK     0x99a4
+
+#define        AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
+#define        AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define        AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE    0x80000000
+#define        AR_PHY_MULTICHAIN_GAIN_CTL      0x99ac
+
+#define        AR_PHY_EXT_CCA0                 0x99b8
+#define        AR_PHY_EXT_CCA0_THRESH62        0x000000FF
+#define        AR_PHY_EXT_CCA0_THRESH62_S      0
+
+#define AR_PHY_CH1_EXT_CCA          0xa9bc
+#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
+
+#define AR_PHY_CH2_EXT_CCA          0xb9bc
+#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
+#define AR_PHY_ANALOG_SWAP      0xa268
+#define AR_PHY_SWAP_ALT_CHAIN   0x00000040
+#define AR_PHY_CAL_CHAINMASK   0xa39c
+
+#define AR_PHY_SWITCH_CHAIN_0     0x9960
+#define AR_PHY_SWITCH_COM         0x9964
+
+#define AR_PHY_RF_CTL2                  0x9824
+#define AR_PHY_TX_FRAME_TO_DATA_START  0x000000FF
+#define AR_PHY_TX_FRAME_TO_DATA_START_S        0
+#define AR_PHY_TX_FRAME_TO_PA_ON       0x0000FF00
+#define AR_PHY_TX_FRAME_TO_PA_ON_S     8
+
+#define AR_PHY_RF_CTL3                  0x9828
+#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S     16
+
+#define AR_PHY_RF_CTL4                    0x9834
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF    0xFF000000
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S  24
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF    0x00FF0000
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S  16
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON      0x0000FF00
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S    8
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON      0x000000FF
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S    0
+
+#define        AR_PHY_SYNTH_CONTROL    0x9874
+
+#define        AR_PHY_FORCE_CLKEN_CCK  0xA22C
+#define        AR_PHY_FORCE_CLKEN_CCK_MRC_MUX  0x00000040
+
+#define AR_PHY_POWER_TX_SUB     0xA3C8
+#define AR_PHY_POWER_TX_RATE5   0xA38C
+#define AR_PHY_POWER_TX_RATE6   0xA390
+#define AR_PHY_POWER_TX_RATE7   0xA3CC
+#define AR_PHY_POWER_TX_RATE8   0xA3D0
+#define AR_PHY_POWER_TX_RATE9   0xA3D4
+
+#define        AR_PHY_TPCRG1_PD_GAIN_1         0x00030000
+#define        AR_PHY_TPCRG1_PD_GAIN_1_S       16
+#define        AR_PHY_TPCRG1_PD_GAIN_2         0x000C0000
+#define        AR_PHY_TPCRG1_PD_GAIN_2_S       18
+#define        AR_PHY_TPCRG1_PD_GAIN_3         0x00300000
+#define        AR_PHY_TPCRG1_PD_GAIN_3_S       20
+
+#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
+#define AR_PHY_MASK2_M_31_45     0xa3a4
+#define AR_PHY_MASK2_M_16_30     0xa3a8
+#define AR_PHY_MASK2_M_00_15     0xa3ac
+#define AR_PHY_MASK2_P_15_01     0xa3b8
+#define AR_PHY_MASK2_P_30_16     0xa3bc
+#define AR_PHY_MASK2_P_45_31     0xa3c0
+#define AR_PHY_MASK2_P_61_45     0xa3c4
+
+#define        AR_PHY_SPUR_REG         0x994c
+#define        AR_PHY_SFCORR_EXT       0x99c0
+#define        AR_PHY_SFCORR_EXT_M1_THRESH     0x0000007F
+#define        AR_PHY_SFCORR_EXT_M1_THRESH_S   0
+#define        AR_PHY_SFCORR_EXT_M2_THRESH     0x00003F80
+#define        AR_PHY_SFCORR_EXT_M2_THRESH_S   7
+#define        AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
+#define        AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S       14
+#define        AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
+#define        AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S       21
+#define        AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
+
+/* enable vit puncture per rate, 8 bits, lsb is low rate */
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL       (0xFF << 18)
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S     18
+
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM      0x20000     /* bins move with freq offset */
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT     (0xFF << 9) /* use mask1 or mask2, one per rate */
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S   9
+#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH     0x7F
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S   0
+
+#define AR_PHY_PILOT_MASK_01_30   0xa3b0
+#define AR_PHY_PILOT_MASK_31_60   0xa3b4
+
+#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
+#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
+
+#define        AR_PHY_CL_CAL_CTL       0xA358          /* carrier leak cal control */
+#define        AR_PHY_CL_CAL_ENABLE    0x00000002
+#endif /* _DEV_ATH_AR5416PHY_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar5416reg.h        2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar5416reg.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#ifndef _DEV_ATH_AR5416REG_H
+#define        _DEV_ATH_AR5416REG_H
+
+#include "ar5212/ar5212reg.h"
+
+/*
+ * Register added starting with the AR5416
+ */
+#define        AR_MIRT                 0x0020  /* interrupt rate threshold */
+#define        AR_TIMT                 0x0028  /* Tx Interrupt mitigation threshold */
+#define        AR_RIMT                 0x002C  /* Rx Interrupt mitigation threshold */
+#define        AR_GTXTO                0x0064  /* global transmit timeout */
+#define        AR_GTTM                 0x0068  /* global transmit timeout mode */
+#define        AR_CST                  0x006C  /* carrier sense timeout */
+#define        AR_MAC_LED              0x1f04  /* LED control */
+#define        AR5416_PCIE_PM_CTRL     0x4014
+#define        AR_AHB_MODE             0x4024  /* AHB mode for dma */
+#define        AR_INTR_SYNC_CAUSE_CLR  0x4028  /* clear interrupt */
+#define        AR_INTR_SYNC_CAUSE      0x4028  /* check pending interrupts */
+#define        AR_INTR_SYNC_ENABLE     0x402c  /* enable interrupts */
+#define        AR_INTR_ASYNC_MASK      0x4030  /* asynchronous interrupt mask */
+#define        AR_INTR_SYNC_MASK       0x4034  /* synchronous interrupt mask */
+#define        AR_INTR_ASYNC_CAUSE     0x4038  /* check pending interrupts */
+#define        AR_INTR_ASYNC_ENABLE    0x403c  /* enable interrupts */
+#define        AR5416_PCIE_SERDES      0x4040
+#define        AR5416_PCIE_SERDES2     0x4044
+#define        AR_GPIO_IN              0x4048  /* GPIO input register */
+#define        AR_GPIO_INTR_OUT        0x404c  /* GPIO output register */
+#define        AR_EEPROM_STATUS_DATA   0x407c
+#define        AR_OBS                  0x4080
+#define        AR_RTC_RC               0x7000  /* reset control */
+#define        AR_RTC_PLL_CONTROL      0x7014
+#define        AR_RTC_RESET            0x7040  /* RTC reset register */
+#define        AR_RTC_STATUS           0x7044  /* system sleep status */
+#define        AR_RTC_SLEEP_CLK        0x7048
+#define        AR_RTC_FORCE_WAKE       0x704c  /* control MAC force wake */
+#define        AR_RTC_INTR_CAUSE       0x7050  /* RTC interrupt cause/clear */
+#define        AR_RTC_INTR_ENABLE      0x7054  /* RTC interrupt enable */
+#define        AR_RTC_INTR_MASK        0x7058  /* RTC interrupt mask */
+/* AR9280: rf long shift registers */
+#define        AR_AN_RF2G1_CH0         0x7810
+#define        AR_AN_RF5G1_CH0         0x7818
+#define        AR_AN_RF2G1_CH1         0x7834
+#define        AR_AN_RF5G1_CH1         0x783C
+#define        AR_AN_TOP2              0x7894
+#define        AR_AN_SYNTH9            0x7868
+#define        AR9285_AN_RF2G3         0x7828
+#define        AR9285_AN_TOP3          0x786c
+#define        AR_RESET_TSF            0x8020
+#define        AR_RXFIFO_CFG           0x8114
+#define        AR_PHY_ERR_1            0x812c
+#define        AR_PHY_ERR_MASK_1       0x8130  /* mask for AR_PHY_ERR_1 */
+#define        AR_PHY_ERR_2            0x8134
+#define        AR_PHY_ERR_MASK_2       0x8138  /* mask for AR_PHY_ERR_2 */
+#define        AR_TSFOOR_THRESHOLD     0x813c
+#define        AR_PHY_ERR_3            0x8168
+#define        AR_PHY_ERR_MASK_3       0x816c  /* mask for AR_PHY_ERR_3 */
+#define        AR_TXOP_X               0x81ec  /* txop for legacy non-qos */
+#define        AR_TXOP_0_3             0x81f0  /* txop for various tid's */
+#define        AR_TXOP_4_7             0x81f4
+#define        AR_TXOP_8_11            0x81f8
+#define        AR_TXOP_12_15           0x81fc
+/* generic timers based on tsf - all uS */
+#define        AR_NEXT_TBTT            0x8200
+#define        AR_NEXT_DBA             0x8204
+#define        AR_NEXT_SWBA            0x8208
+#define        AR_NEXT_CFP             0x8208
+#define        AR_NEXT_HCF             0x820C
+#define        AR_NEXT_TIM             0x8210
+#define        AR_NEXT_DTIM            0x8214
+#define        AR_NEXT_QUIET           0x8218
+#define        AR_NEXT_NDP             0x821C
+#define        AR5416_BEACON_PERIOD    0x8220
+#define        AR_DBA_PERIOD           0x8224
+#define        AR_SWBA_PERIOD          0x8228
+#define        AR_HCF_PERIOD           0x822C
+#define        AR_TIM_PERIOD           0x8230
+#define        AR_DTIM_PERIOD          0x8234
+#define        AR_QUIET_PERIOD         0x8238
+#define        AR_NDP_PERIOD           0x823C
+#define        AR_TIMER_MODE           0x8240
+#define        AR_SLP32_MODE           0x8244
+#define        AR_SLP32_WAKE           0x8248
+#define        AR_SLP32_INC            0x824c
+#define        AR_SLP_CNT              0x8250  /* 32kHz cycles with mac asleep */
+#define        AR_SLP_CYCLE_CNT        0x8254  /* absolute number of 32kHz cycles */
+#define        AR_SLP_MIB_CTRL         0x8258
+#define        AR_2040_MODE            0x8318
+#define        AR_EXTRCCNT             0x8328  /* extension channel rx clear count */
+#define        AR_SELFGEN_MASK         0x832c  /* rx and cal chain masks */
+#define        AR_PCU_TXBUF_CTRL       0x8340
+
+/* DMA & PCI Registers in PCI space (usable during sleep)*/
+#define        AR_RC_AHB               0x00000001      /* AHB reset */
+#define        AR_RC_APB               0x00000002      /* APB reset */
+#define        AR_RC_HOSTIF            0x00000100      /* host interface reset */
+
+#define        AR_MIRT_VAL             0x0000ffff      /* in uS */
+#define        AR_MIRT_VAL_S           16
+
+#define        AR_TIMT_LAST            0x0000ffff      /* Last packet threshold */
+#define        AR_TIMT_LAST_S          0
+#define        AR_TIMT_FIRST           0xffff0000      /* First packet threshold */
+#define        AR_TIMT_FIRST_S         16
+
+#define        AR_RIMT_LAST            0x0000ffff      /* Last packet threshold */
+#define        AR_RIMT_LAST_S          0
+#define        AR_RIMT_FIRST           0xffff0000      /* First packet threshold */
+#define        AR_RIMT_FIRST_S         16
+
+#define        AR_GTXTO_TIMEOUT_COUNTER    0x0000FFFF  // Mask for timeout counter (in TUs)
+#define        AR_GTXTO_TIMEOUT_LIMIT      0xFFFF0000  // Mask for timeout limit (in  TUs)
+#define        AR_GTXTO_TIMEOUT_LIMIT_S    16      // Shift for timeout limit
+
+#define        AR_GTTM_USEC          0x00000001 // usec strobe
+#define        AR_GTTM_IGNORE_IDLE   0x00000002 // ignore channel idle
+#define        AR_GTTM_RESET_IDLE    0x00000004 // reset counter on channel idle low
+#define        AR_GTTM_CST_USEC      0x00000008 // CST usec strobe
+
+#define        AR_CST_TIMEOUT_COUNTER    0x0000FFFF  // Mask for timeout counter (in TUs)
+#define        AR_CST_TIMEOUT_LIMIT      0xFFFF0000  // Mask for timeout limit (in  TUs)
+#define        AR_CST_TIMEOUT_LIMIT_S    16      // Shift for timeout limit
+
+/* MAC tx DMA size config  */
+#define        AR_TXCFG_DMASZ_MASK     0x00000003
+#define        AR_TXCFG_DMASZ_4B       0
+#define        AR_TXCFG_DMASZ_8B       1
+#define        AR_TXCFG_DMASZ_16B      2
+#define        AR_TXCFG_DMASZ_32B      3
+#define        AR_TXCFG_DMASZ_64B      4
+#define        AR_TXCFG_DMASZ_128B     5
+#define        AR_TXCFG_DMASZ_256B     6
+#define        AR_TXCFG_DMASZ_512B     7
+#define        AR_TXCFG_ATIM_TXPOLICY  0x00000800
+
+/* MAC rx DMA size config  */
+#define        AR_RXCFG_DMASZ_MASK     0x00000007
+#define        AR_RXCFG_DMASZ_4B       0
+#define        AR_RXCFG_DMASZ_8B       1
+#define        AR_RXCFG_DMASZ_16B      2
+#define        AR_RXCFG_DMASZ_32B      3
+#define        AR_RXCFG_DMASZ_64B      4
+#define        AR_RXCFG_DMASZ_128B     5
+#define        AR_RXCFG_DMASZ_256B     6
+#define        AR_RXCFG_DMASZ_512B     7
+
+/* MAC Led registers */
+#define        AR_MAC_LED_BLINK_SLOW   0x00000008      /* LED slowest blink rate mode */
+#define        AR_MAC_LED_BLINK_THRESH_SEL 0x00000070  /* LED blink threshold select */
+#define        AR_MAC_LED_MODE         0x00000380      /* LED mode select */
+#define        AR_MAC_LED_MODE_S       7
+#define        AR_MAC_LED_MODE_PROP    0       /* Blink prop to filtered tx/rx */
+#define        AR_MAC_LED_MODE_RPROP   1       /* Blink prop to unfiltered tx/rx */
+#define        AR_MAC_LED_MODE_SPLIT   2       /* Blink power for tx/net for rx */
+#define        AR_MAC_LED_MODE_RAND    3       /* Blink randomly */
+#define        AR_MAC_LED_MODE_POWON   5       /* Power LED on (s/w control) */
+#define        AR_MAC_LED_MODE_NETON   6       /* Network LED on (s/w control) */
+#define        AR_MAC_LED_ASSOC        0x00000c00
+#define        AR_MAC_LED_ASSOC_NONE   0x00000000 /* STA is not associated or trying */
+#define        AR_MAC_LED_ASSOC_ACTIVE 0x00000400 /* STA is associated */
+#define        AR_MAC_LED_ASSOC_PEND   0x00000800 /* STA is trying to associate */
+#define        AR_MAC_LED_ASSOC_S      10
+
+#define        AR_AHB_EXACT_WR_EN      0x00000000      /* write exact bytes */
+#define        AR_AHB_BUF_WR_EN        0x00000001      /* buffer write upto cacheline*/
+#define        AR_AHB_EXACT_RD_EN      0x00000000      /* read exact bytes */
+#define        AR_AHB_CACHELINE_RD_EN  0x00000002      /* read upto end of cacheline */
+#define        AR_AHB_PREFETCH_RD_EN   0x00000004      /* prefetch upto page boundary*/
+#define        AR_AHB_PAGE_SIZE_1K     0x00000000      /* set page-size as 1k */
+#define        AR_AHB_PAGE_SIZE_2K     0x00000008      /* set page-size as 2k */
+#define        AR_AHB_PAGE_SIZE_4K     0x00000010      /* set page-size as 4k */
+
+/* MAC PCU Registers */
+#define        AR_STA_ID1_PRESERVE_SEQNUM      0x20000000 /* Don't replace seq num */
+
+/* Extended PCU DIAG_SW control fields */
+#define        AR_DIAG_DUAL_CHAIN_INFO 0x01000000      /* dual chain channel info */
+#define        AR_DIAG_RX_ABORT        0x02000000      /* abort rx */
+#define        AR_DIAG_SATURATE_CCNT   0x04000000      /* sat. cycle cnts (no shift) */
+#define        AR_DIAG_OBS_PT_SEL2     0x08000000      /* observation point sel */
+#define        AR_DIAG_RXCLEAR_CTL_LOW 0x10000000      /* force rx_clear(ctl) low/busy */
+#define        AR_DIAG_RXCLEAR_EXT_LOW 0x20000000      /* force rx_clear(ext) low/busy */
+
+#define        AR_TXOP_X_VAL   0x000000FF
+
+#define        AR_RESET_TSF_ONCE       0x01000000      /* reset tsf once; self-clears*/
+
+/* Interrupts */
+#define        AR_ISR_TXMINTR          0x00080000      /* Maximum interrupt tx rate */
+#define        AR_ISR_RXMINTR          0x01000000      /* Maximum interrupt rx rate */
+#define        AR_ISR_TXINTM           0x40000000      /* Tx int after mitigation */
+#define        AR_ISR_RXINTM           0x80000000      /* Rx int after mitigation */
+
+#define        AR_ISR_S2_CST           0x00400000      /* Carrier sense timeout */
+#define        AR_ISR_S2_GTT           0x00800000      /* Global transmit timeout */
+#define        AR_ISR_S2_TSFOOR        0x40000000      /* RX TSF out of range */
+
+#define        AR_INTR_SPURIOUS        0xffffffff
+#define        AR_INTR_RTC_IRQ         0x00000001      /* rtc in shutdown state */
+#define        AR_INTR_MAC_IRQ         0x00000002      /* pending mac interrupt */
+#define        AR_INTR_EEP_PROT_ACCESS 0x00000004      /* eeprom protected access */
+#define        AR_INTR_MAC_AWAKE       0x00020000      /* mac is awake */
+#define        AR_INTR_MAC_ASLEEP      0x00040000      /* mac is asleep */
+
+/* Interrupt Mask Registers */
+#define        AR_IMR_TXMINTR          0x00080000      /* Maximum interrupt tx rate */
+#define        AR_IMR_RXMINTR          0x01000000      /* Maximum interrupt rx rate */
+#define        AR_IMR_TXINTM           0x40000000      /* Tx int after mitigation */
+#define        AR_IMR_RXINTM           0x80000000      /* Rx int after mitigation */
+
+#define        AR_IMR_S2_CST           0x00400000      /* Carrier sense timeout */
+#define        AR_IMR_S2_GTT           0x00800000      /* Global transmit timeout */
+
+/* synchronous interrupt signals */
+#define        AR_INTR_SYNC_RTC_IRQ            0x00000001
+#define        AR_INTR_SYNC_MAC_IRQ            0x00000002
+#define        AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS      0x00000004
+#define        AR_INTR_SYNC_APB_TIMEOUT        0x00000008
+#define        AR_INTR_SYNC_PCI_MODE_CONFLICT  0x00000010
+#define        AR_INTR_SYNC_HOST1_FATAL        0x00000020
+#define        AR_INTR_SYNC_HOST1_PERR         0x00000040
+#define        AR_INTR_SYNC_TRCV_FIFO_PERR     0x00000080
+#define        AR_INTR_SYNC_RADM_CPL_EP        0x00000100
+#define        AR_INTR_SYNC_RADM_CPL_DLLP_ABORT        0x00000200
+#define        AR_INTR_SYNC_RADM_CPL_TLP_ABORT 0x00000400
+#define        AR_INTR_SYNC_RADM_CPL_ECRC_ERR  0x00000800
+#define        AR_INTR_SYNC_RADM_CPL_TIMEOUT   0x00001000
+#define        AR_INTR_SYNC_LOCAL_TIMEOUT      0x00002000
+#define        AR_INTR_SYNC_PM_ACCESS          0x00004000
+#define        AR_INTR_SYNC_MAC_AWAKE          0x00008000
+#define        AR_INTR_SYNC_MAC_ASLEEP         0x00010000
+#define        AR_INTR_SYNC_MAC_SLEEP_ACCESS   0x00020000
+#define        AR_INTR_SYNC_ALL                0x0003FFFF
+
+/* default synchronous interrupt signals enabled */
+#define        AR_INTR_SYNC_DEFAULT \
+       (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR | \
+        AR_INTR_SYNC_RADM_CPL_EP | AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | \
+        AR_INTR_SYNC_RADM_CPL_TLP_ABORT | AR_INTR_SYNC_RADM_CPL_ECRC_ERR | \
+        AR_INTR_SYNC_RADM_CPL_TIMEOUT | AR_INTR_SYNC_LOCAL_TIMEOUT | \
+        AR_INTR_SYNC_MAC_SLEEP_ACCESS)
+
+/* RTC registers */
+#define        AR_RTC_RC_M             0x00000003
+#define        AR_RTC_RC_MAC_WARM      0x00000001
+#define        AR_RTC_RC_MAC_COLD      0x00000002
+#define        AR_RTC_PLL_DIV          0x0000001f
+#define        AR_RTC_PLL_DIV_S        0
+#define        AR_RTC_PLL_DIV2         0x00000020
+#define        AR_RTC_PLL_REFDIV_5     0x000000c0
+
+#define        AR_RTC_SOWL_PLL_DIV             0x000003ff
+#define        AR_RTC_SOWL_PLL_DIV_S           0
+#define        AR_RTC_SOWL_PLL_REFDIV          0x00003C00
+#define        AR_RTC_SOWL_PLL_REFDIV_S        10
+#define        AR_RTC_SOWL_PLL_CLKSEL          0x0000C000
+#define        AR_RTC_SOWL_PLL_CLKSEL_S        14
+
+#define        AR_RTC_RESET_EN         0x00000001      /* Reset RTC bit */
+
+#define        AR_RTC_PM_STATUS_M      0x0000000f      /* Pwr Mgmt Status */
+#define        AR_RTC_STATUS_M         0x0000003f      /* RTC Status */
+#define        AR_RTC_STATUS_SHUTDOWN  0x00000001
+#define        AR_RTC_STATUS_ON        0x00000002
+#define        AR_RTC_STATUS_SLEEP     0x00000004
+#define        AR_RTC_STATUS_WAKEUP    0x00000008
+#define        AR_RTC_STATUS_COLDRESET 0x00000010      /* Not currently used */
+#define        AR_RTC_STATUS_PLLCHANGE 0x00000020      /* Not currently used */
+
+#define        AR_RTC_SLEEP_DERIVED_CLK        0x2
+
+#define        AR_RTC_FORCE_WAKE_EN    0x00000001      /* enable force wake */
+#define        AR_RTC_FORCE_WAKE_ON_INT 0x00000002     /* auto-wake on MAC interrupt */
+
+#define        AR_RTC_PLL_CLKSEL       0x00000300
+#define        AR_RTC_PLL_CLKSEL_S     8
+
+/* AR9280: rf long shift registers */
+#define        AR_AN_RF2G1_CH0_OB      0x03800000
+#define        AR_AN_RF2G1_CH0_OB_S    23
+#define        AR_AN_RF2G1_CH0_DB      0x1C000000
+#define        AR_AN_RF2G1_CH0_DB_S    26
+
+#define        AR_AN_RF5G1_CH0_OB5     0x00070000
+#define        AR_AN_RF5G1_CH0_OB5_S   16
+#define        AR_AN_RF5G1_CH0_DB5     0x00380000
+#define        AR_AN_RF5G1_CH0_DB5_S   19
+
+#define        AR_AN_RF2G1_CH1_OB      0x03800000
+#define        AR_AN_RF2G1_CH1_OB_S    23
+#define        AR_AN_RF2G1_CH1_DB      0x1C000000
+#define        AR_AN_RF2G1_CH1_DB_S    26
+
+#define        AR_AN_RF5G1_CH1_OB5     0x00070000
+#define        AR_AN_RF5G1_CH1_OB5_S   16
+#define        AR_AN_RF5G1_CH1_DB5     0x00380000
+#define        AR_AN_RF5G1_CH1_DB5_S   19
+
+#define        AR_AN_TOP2_XPABIAS_LVL      0xC0000000
+#define        AR_AN_TOP2_XPABIAS_LVL_S    30
+#define        AR_AN_TOP2_LOCALBIAS        0x00200000
+#define        AR_AN_TOP2_LOCALBIAS_S      21
+#define        AR_AN_TOP2_PWDCLKIND        0x00400000
+#define        AR_AN_TOP2_PWDCLKIND_S      22
+
+#define        AR_AN_SYNTH9_REFDIVA    0xf8000000
+#define        AR_AN_SYNTH9_REFDIVA_S  27
+
+/* AR9285 Analog registers */
+#define        AR9285_AN_RF2G3_OB_0    0x00E00000
+#define        AR9285_AN_RF2G3_OB_0_S    21
+#define        AR9285_AN_RF2G3_OB_1    0x001C0000
+#define        AR9285_AN_RF2G3_OB_1_S    18
+#define        AR9285_AN_RF2G3_OB_2    0x00038000
+#define        AR9285_AN_RF2G3_OB_2_S    15
+#define        AR9285_AN_RF2G3_OB_3    0x00007000
+#define        AR9285_AN_RF2G3_OB_3_S    12
+#define        AR9285_AN_RF2G3_OB_4    0x00000E00
+#define        AR9285_AN_RF2G3_OB_4_S    9
+
+#define        AR9285_AN_RF2G3_DB1_0    0x000001C0
+#define        AR9285_AN_RF2G3_DB1_0_S    6
+#define        AR9285_AN_RF2G3_DB1_1    0x00000038
+#define        AR9285_AN_RF2G3_DB1_1_S    3
+#define        AR9285_AN_RF2G3_DB1_2    0x00000007
+#define        AR9285_AN_RF2G3_DB1_2_S    0
+#define        AR9285_AN_RF2G4         0x782C
+#define        AR9285_AN_RF2G4_DB1_3    0xE0000000
+#define        AR9285_AN_RF2G4_DB1_3_S    29
+#define        AR9285_AN_RF2G4_DB1_4    0x1C000000
+#define        AR9285_AN_RF2G4_DB1_4_S    26
+
+#define        AR9285_AN_RF2G4_DB2_0    0x03800000
+#define        AR9285_AN_RF2G4_DB2_0_S    23
+#define        AR9285_AN_RF2G4_DB2_1    0x00700000
+#define        AR9285_AN_RF2G4_DB2_1_S    20
+#define        AR9285_AN_RF2G4_DB2_2    0x000E0000
+#define        AR9285_AN_RF2G4_DB2_2_S    17
+#define        AR9285_AN_RF2G4_DB2_3    0x0001C000
+#define        AR9285_AN_RF2G4_DB2_3_S    14
+#define        AR9285_AN_RF2G4_DB2_4    0x00003800
+#define        AR9285_AN_RF2G4_DB2_4_S    11
+
+#define        AR9285_AN_TOP3_XPABIAS_LVL      0x0000000C
+#define        AR9285_AN_TOP3_XPABIAS_LVL_S    2
+
+/* Sleep control */
+#define        AR5416_SLEEP1_CAB_TIMEOUT       0xFFE00000      /* Cab timeout (TU) */
+#define        AR5416_SLEEP1_CAB_TIMEOUT_S     22
+
+#define        AR5416_SLEEP2_BEACON_TIMEOUT    0xFFE00000      /* Beacon timeout (TU)*/
+#define        AR5416_SLEEP2_BEACON_TIMEOUT_S  22
+
+/* Sleep Registers */
+#define        AR_SLP32_HALFCLK_LATENCY      0x000FFFFF        /* rising <-> falling edge */
+#define        AR_SLP32_ENA            0x00100000
+#define        AR_SLP32_TSF_WRITE_STATUS      0x00200000       /* tsf update in progress */
+
+#define        AR_SLP32_WAKE_XTL_TIME  0x0000FFFF      /* time to wake crystal */
+
+#define        AR_SLP32_TST_INC        0x000FFFFF
+
+#define        AR_SLP_MIB_CLEAR        0x00000001      /* clear pending */
+#define        AR_SLP_MIB_PENDING      0x00000002      /* clear counters */
+
+#define        AR_TIMER_MODE_TBTT              0x00000001
+#define        AR_TIMER_MODE_DBA               0x00000002
+#define        AR_TIMER_MODE_SWBA              0x00000004
+#define        AR_TIMER_MODE_HCF               0x00000008
+#define        AR_TIMER_MODE_TIM               0x00000010
+#define        AR_TIMER_MODE_DTIM              0x00000020
+#define        AR_TIMER_MODE_QUIET             0x00000040
+#define        AR_TIMER_MODE_NDP               0x00000080
+#define        AR_TIMER_MODE_OVERFLOW_INDEX    0x00000700
+#define        AR_TIMER_MODE_OVERFLOW_INDEX_S  8
+#define        AR_TIMER_MODE_THRESH            0xFFFFF000
+#define        AR_TIMER_MODE_THRESH_S          12
+
+/* PCU Misc modes */
+#define        AR_PCU_FORCE_BSSID_MATCH        0x00000001 /* force bssid to match */
+#define        AR_PCU_MIC_NEW_LOC_ENA          0x00000004 /* tx/rx mic keys together */
+#define        AR_PCU_TX_ADD_TSF               0x00000008 /* add tx_tsf + int_tsf */
+#define        AR_PCU_CCK_SIFS_MODE            0x00000010 /* assume 11b sifs */
+#define        AR_PCU_RX_ANT_UPDT              0x00000800 /* KC_RX_ANT_UPDATE */
+#define        AR_PCU_TXOP_TBTT_LIMIT_ENA      0x00001000 /* enforce txop / tbtt */
+#define        AR_PCU_MISS_BCN_IN_SLEEP        0x00004000 /* count bmiss's when sleeping */
+#define        AR_PCU_BUG_12306_FIX_ENA        0x00020000 /* use rx_clear to count sifs */
+#define        AR_PCU_FORCE_QUIET_COLL         0x00040000 /* kill xmit for channel change */
+#define        AR_PCU_TBTT_PROTECT             0x00200000 /* no xmit upto tbtt+20 uS */
+#define        AR_PCU_CLEAR_VMF                0x01000000 /* clear vmf mode (fast cc)*/
+#define        AR_PCU_CLEAR_BA_VALID           0x04000000 /* clear ba state */
+
+/* GPIO Interrupt */
+#define        AR_INTR_GPIO            0x3FF00000      /* gpio interrupted */
+#define        AR_INTR_GPIO_S          20
+
+#define        AR_GPIO_OUT_CTRL        0x000003FF      /* 0 = out, 1 = in */
+#define        AR_GPIO_OUT_VAL         0x000FFC00
+#define        AR_GPIO_OUT_VAL_S       10
+#define        AR_GPIO_INTR_CTRL       0x3FF00000
+#define        AR_GPIO_INTR_CTRL_S     20
+
+#define        AR_2040_JOINED_RX_CLEAR 0x00000001      /* use ctl + ext rx_clear for cca */
+
+#define        AR_PCU_TXBUF_CTRL_SIZE_MASK     0x7FF
+#define        AR_PCU_TXBUF_CTRL_USABLE_SIZE   0x700
+
+/* Eeprom defines */
+#define        AR_EEPROM_STATUS_DATA_VAL           0x0000ffff
+#define        AR_EEPROM_STATUS_DATA_VAL_S         0
+#define        AR_EEPROM_STATUS_DATA_BUSY          0x00010000
+#define        AR_EEPROM_STATUS_DATA_BUSY_ACCESS   0x00020000
+#define        AR_EEPROM_STATUS_DATA_PROT_ACCESS   0x00040000
+#define        AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000
+
+#define        AR_SREV_REVISION_OWL_10         0x08
+#define        AR_SREV_REVISION_OWL_20         0x09
+#define        AR_SREV_REVISION_OWL_22         0x0a
+
+#define        AR_RAD5133_SREV_MAJOR           0xc0    /* Fowl: 2+5G/3x3 */
+#define        AR_RAD2133_SREV_MAJOR           0xd0    /* Fowl: 2G/3x3   */
+#define        AR_RAD5122_SREV_MAJOR           0xe0    /* Fowl: 5G/2x2   */
+#define        AR_RAD2122_SREV_MAJOR           0xf0    /* Fowl: 2+5G/2x2 */
+
+/* Test macro for owl 1.0 */
+#define        IS_5416V1(_ah)  ((_ah)->ah_macRev == AR_SREV_REVISION_OWL_10)
+#define        IS_5416V2(_ah)  ((_ah)->ah_macRev >= AR_SREV_REVISION_OWL_20)
+#define        IS_5416V2_2(_ah)        ((_ah)->ah_macRev == AR_SREV_REVISION_OWL_22)
+
+/* Expanded Mac Silicon Rev (16 bits starting with Sowl) */
+#define        AR_XSREV_ID             0xFFFFFFFF      /* Chip ID */
+#define        AR_XSREV_ID_S           0
+#define        AR_XSREV_VERSION        0xFFFC0000      /* Chip version */
+#define        AR_XSREV_VERSION_S      18
+#define        AR_XSREV_TYPE           0x0003F000      /* Chip type */
+#define        AR_XSREV_TYPE_S         12
+#define        AR_XSREV_TYPE_CHAIN     0x00001000      /* Chain Mode (1:3 chains,
+                                                * 0:2 chains) */
+#define        AR_XSREV_TYPE_HOST_MODE 0x00002000      /* Host Mode (1:PCI, 0:PCIe) */
+#define        AR_XSREV_REVISION       0x00000F00
+#define        AR_XSREV_REVISION_S     8
+
+#define        AR_XSREV_VERSION_OWL_PCI        0x0D
+#define        AR_XSREV_VERSION_OWL_PCIE       0x0C
+#define        AR_XSREV_REVISION_OWL_10        0       /* Owl 1.0 */
+#define        AR_XSREV_REVISION_OWL_20        1       /* Owl 2.0/2.1 */
+#define        AR_XSREV_REVISION_OWL_22        2       /* Owl 2.2 */
+#define        AR_XSREV_VERSION_SOWL           0x40
+#define        AR_XSREV_REVISION_SOWL_10       0       /* Sowl 1.0 */
+#define        AR_XSREV_REVISION_SOWL_11       1       /* Sowl 1.1 */
+#define        AR_XSREV_VERSION_MERLIN         0x80    /* Merlin Version */
+#define        AR_XSREV_REVISION_MERLIN_10     0       /* Merlin 1.0 */
+#define        AR_XSREV_REVISION_MERLIN_20     1       /* Merlin 2.0 */
+#define        AR_XSREV_REVISION_MERLIN_21     2       /* Merlin 2.1 */
+#define        AR_XSREV_VERSION_KITE           0xC0    /* Kite Version */
+#define        AR_XSREV_REVISION_KITE_10       0       /* Kite 1.0 */
+
+#define        AR_SREV_OWL_20_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL || \
+        AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_20)
+#define        AR_SREV_OWL_22_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL || \
+        AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_22)
+
+#define        AR_SREV_SOWL(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_SOWL)
+#define        AR_SREV_SOWL_10_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL)
+#define        AR_SREV_SOWL_11(_ah) \
+       (AR_SREV_SOWL(_ah) && \
+        AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_SOWL_11)
+
+#define        AR_SREV_MERLIN(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_MERLIN)
+#define        AR_SREV_MERLIN_10_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_MERLIN)
+#define        AR_SREV_MERLIN_20(_ah) \
+       (AR_SREV_MERLIN(_ah) && \
+        AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_MERLIN_20)
+#define        AR_SREV_MERLIN_20_OR_LATER(_ah) \
+       (AR_SREV_MERLIN_20(_ah) || \
+        AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_MERLIN)
+
+#define        AR_SREV_KITE(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_KITE)
+#define        AR_SREV_KITE_10_OR_LATER(_ah) \
+       (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_KITE)
+#endif /* _DEV_ATH_AR5416REG_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar9160.ini 2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,699 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar9160.ini,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+/* Auto Generated PCI Register Writes.  Created: 05/22/08 */
+
+static const uint32_t ar9160Modes[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
+    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 },
+    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
+    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+    { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
+    { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
+    { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce },
+    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 },
+    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
+    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
+    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
+    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
+    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
+    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
+    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
+    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
+    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
+    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
+    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
+    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
+    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
+    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const uint32_t ar9160Common[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+    { 0x00007010, 0x00000020 },
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0x00000000 },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c4, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x00008300, 0x00000000 },
+    { 0x00008304, 0x00000000 },
+    { 0x00008308, 0x00000000 },
+    { 0x0000830c, 0x00000000 },
+    { 0x00008310, 0x00000000 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008318, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00000000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xad848e19 },
+    { 0x00009810, 0x7d14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x00009840, 0x206a01ae },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009854, 0x00000859 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x05100000 },
+    { 0x0000a920, 0x05100000 },
+    { 0x0000b920, 0x05100000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280b212 },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5f3ca3de },
+    { 0x00009958, 0x2108ecff },
+    { 0x00009940, 0x00750604 },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x00009970, 0x190fb515 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x201fff00 },
+    { 0x000099ac, 0x006f0000 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000200 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x0cc80caa },
+    { 0x000099fc, 0x00001042 },
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b28, 0x0000000c },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b38, 0x00000012 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b64, 0x00000021 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b8c, 0x0000002d },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009b9c, 0x00000033 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+    { 0x0000a210, 0x40806333 },
+    { 0x0000a214, 0x00106c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x018830c6 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x001a0bb5 },
+    { 0x0000a22c, 0x00000000 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000001 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000c26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x050701ce },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa33 },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x0c000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+};
+
+static const uint32_t ar9160Bank0[][2] = {
+    { 0x000098b0, 0x1e5795e5 },
+    { 0x000098e0, 0x02008020 },
+};
+
+static const uint32_t ar9160BB_RfGain[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000040, 0x00000040 },
+    { 0x00009a08, 0x00000080, 0x00000080 },
+    { 0x00009a0c, 0x000001a1, 0x00000141 },
+    { 0x00009a10, 0x000001e1, 0x00000181 },
+    { 0x00009a14, 0x00000021, 0x000001c1 },
+    { 0x00009a18, 0x00000061, 0x00000001 },
+    { 0x00009a1c, 0x00000168, 0x00000041 },
+    { 0x00009a20, 0x000001a8, 0x000001a8 },
+    { 0x00009a24, 0x000001e8, 0x000001e8 },
+    { 0x00009a28, 0x00000028, 0x00000028 },
+    { 0x00009a2c, 0x00000068, 0x00000068 },
+    { 0x00009a30, 0x00000189, 0x000000a8 },
+    { 0x00009a34, 0x000001c9, 0x00000169 },
+    { 0x00009a38, 0x00000009, 0x000001a9 },
+    { 0x00009a3c, 0x00000049, 0x000001e9 },
+    { 0x00009a40, 0x00000089, 0x00000029 },
+    { 0x00009a44, 0x00000170, 0x00000069 },
+    { 0x00009a48, 0x000001b0, 0x00000190 },
+    { 0x00009a4c, 0x000001f0, 0x000001d0 },
+    { 0x00009a50, 0x00000030, 0x00000010 },
+    { 0x00009a54, 0x00000070, 0x00000050 },
+    { 0x00009a58, 0x00000191, 0x00000090 },
+    { 0x00009a5c, 0x000001d1, 0x00000151 },
+    { 0x00009a60, 0x00000011, 0x00000191 },
+    { 0x00009a64, 0x00000051, 0x000001d1 },
+    { 0x00009a68, 0x00000091, 0x00000011 },
+    { 0x00009a6c, 0x000001b8, 0x00000051 },
+    { 0x00009a70, 0x000001f8, 0x00000198 },
+    { 0x00009a74, 0x00000038, 0x000001d8 },
+    { 0x00009a78, 0x00000078, 0x00000018 },
+    { 0x00009a7c, 0x00000199, 0x00000058 },
+    { 0x00009a80, 0x000001d9, 0x00000098 },
+    { 0x00009a84, 0x00000019, 0x00000159 },
+    { 0x00009a88, 0x00000059, 0x00000199 },
+    { 0x00009a8c, 0x00000099, 0x000001d9 },
+    { 0x00009a90, 0x000000d9, 0x00000019 },
+    { 0x00009a94, 0x000000f9, 0x00000059 },
+    { 0x00009a98, 0x000000f9, 0x00000099 },
+    { 0x00009a9c, 0x000000f9, 0x000000d9 },
+    { 0x00009aa0, 0x000000f9, 0x000000f9 },
+    { 0x00009aa4, 0x000000f9, 0x000000f9 },
+    { 0x00009aa8, 0x000000f9, 0x000000f9 },
+    { 0x00009aac, 0x000000f9, 0x000000f9 },
+    { 0x00009ab0, 0x000000f9, 0x000000f9 },
+    { 0x00009ab4, 0x000000f9, 0x000000f9 },
+    { 0x00009ab8, 0x000000f9, 0x000000f9 },
+    { 0x00009abc, 0x000000f9, 0x000000f9 },
+    { 0x00009ac0, 0x000000f9, 0x000000f9 },
+    { 0x00009ac4, 0x000000f9, 0x000000f9 },
+    { 0x00009ac8, 0x000000f9, 0x000000f9 },
+    { 0x00009acc, 0x000000f9, 0x000000f9 },
+    { 0x00009ad0, 0x000000f9, 0x000000f9 },
+    { 0x00009ad4, 0x000000f9, 0x000000f9 },
+    { 0x00009ad8, 0x000000f9, 0x000000f9 },
+    { 0x00009adc, 0x000000f9, 0x000000f9 },
+    { 0x00009ae0, 0x000000f9, 0x000000f9 },
+    { 0x00009ae4, 0x000000f9, 0x000000f9 },
+    { 0x00009ae8, 0x000000f9, 0x000000f9 },
+    { 0x00009aec, 0x000000f9, 0x000000f9 },
+    { 0x00009af0, 0x000000f9, 0x000000f9 },
+    { 0x00009af4, 0x000000f9, 0x000000f9 },
+    { 0x00009af8, 0x000000f9, 0x000000f9 },
+    { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const uint32_t ar9160Bank1[][2] = {
+    { 0x000098b0, 0x02108421 },
+    { 0x000098ec, 0x00000008 },
+};
+
+static const uint32_t ar9160Bank2[][2] = {
+    { 0x000098b0, 0x0e73ff17 },
+    { 0x000098e0, 0x00000420 },
+};
+
+static const uint32_t ar9160Bank3[][3] = {
+    { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+static const uint32_t ar9160Bank6[][3] = {
+/*    Reg      A            G            */
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x004210a2, 0x004210a2 },
+    { 0x0000989c, 0x0014008f, 0x0014008f },
+    { 0x0000989c, 0x00c40003, 0x00c40003 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000f1, 0x000000f1 },
+    { 0x0000989c, 0x00002081, 0x00002081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const uint32_t ar9160Bank6TPC[][3] = {
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x00423022, 0x00423022 },
+    { 0x0000989c, 0x2014008f, 0x2014008f },
+    { 0x0000989c, 0x00c40002, 0x00c40002 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000e1, 0x000000e1 },
+    { 0x0000989c, 0x00007080, 0x00007080 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const uint32_t ar9160Bank7[][2] = {
+    { 0x0000989c, 0x00000500 },
+    { 0x0000989c, 0x00000800 },
+    { 0x000098cc, 0x0000000e },
+};
+
+/* Auto generated PCI Register Writes for SOWL1.0 ADDAC Shift Chain */
+static const uint32_t ar9160Addac[][2] = {
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000018 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000019 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000003 },
+    {0x0000989c,  0x00000008 },
+    {0x0000989c,  0x00000000 },
+    {0x000098cc,  0x00000000 },
+};
+
+/* Auto generated PCI Register Writes for SOWL1.1 ADDAC Shift Chain */
+static const uint32_t ar9160Addac_1_1[][2] = {
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000018 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000019 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x000098cc,  0x00000000 },
+};
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ar5416/ar9160_attach.c    2009-05-15 11:11:29.000000000 +0100
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ar9160_attach.c,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#include "ar5416/ar9160.ini"
+
+static const HAL_PERCAL_DATA ar9160_iq_cal = {         /* multi sample */
+       .calName = "IQ", .calType = IQ_MISMATCH_CAL,
+       .calNumSamples  = MAX_CAL_SAMPLES,
+       .calCountMax    = PER_MIN_LOG_COUNT,
+       .calCollect     = ar5416IQCalCollect,
+       .calPostProc    = ar5416IQCalibration
+};
+static const HAL_PERCAL_DATA ar9160_adc_gain_cal = {   /* multi sample */
+       .calName = "ADC Gain", .calType = ADC_GAIN_CAL,
+       .calNumSamples  = MAX_CAL_SAMPLES,
+       .calCountMax    = PER_MIN_LOG_COUNT,
+       .calCollect     = ar5416AdcGainCalCollect,
+       .calPostProc    = ar5416AdcGainCalibration
+};
+static const HAL_PERCAL_DATA ar9160_adc_dc_cal = {     /* multi sample */
+       .calName = "ADC DC", .calType = ADC_DC_CAL,
+       .calNumSamples  = MAX_CAL_SAMPLES,
+       .calCountMax    = PER_MIN_LOG_COUNT,
+       .calCollect     = ar5416AdcDcCalCollect,
+       .calPostProc    = ar5416AdcDcCalibration
+};
+static const HAL_PERCAL_DATA ar9160_adc_init_dc_cal = {
+       .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
+       .calNumSamples  = MIN_CAL_SAMPLES,
+       .calCountMax    = INIT_LOG_COUNT,
+       .calCollect     = ar5416AdcDcCalCollect,
+       .calPostProc    = ar5416AdcDcCalibration
+};
+
+struct ath_hal *ar9160Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status);
+static void ar9160Detach(struct ath_hal *);
+static HAL_BOOL ar9160FillCapabilityInfo(struct ath_hal *ah);
+
+static void
+ar9160AniSetup(struct ath_hal *ah)
+{
+       static const struct ar5212AniParams aniparams = {
+               .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
+               .totalSizeDesired       = { -55, -55, -55, -55, -62 },
+               .coarseHigh             = { -14, -14, -14, -14, -12 },
+               .coarseLow              = { -64, -64, -64, -64, -70 },
+               .firpwr                 = { -78, -78, -78, -78, -80 },
+               .maxSpurImmunityLevel   = 2,
+               .cycPwrThr1             = { 2, 4, 6 },
+               .maxFirstepLevel        = 2,    /* levels 0..2 */
+               .firstep                = { 0, 4, 8 },
+               .ofdmTrigHigh           = 500,
+               .ofdmTrigLow            = 200,
+               .cckTrigHigh            = 200,
+               .cckTrigLow             = 100,
+               .rssiThrHigh            = 40,
+               .rssiThrLow             = 7,
+               .period                 = 100,
+       };
+       /* NB: ANI is not enabled yet */
+       ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE);
+}
+
+/*
+ * Attach for an AR9160 part.
+ */
+struct ath_hal *
+ar9160Attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+       struct ath_hal_5416 *ahp5416;
+       struct ath_hal_5212 *ahp;
+       struct ath_hal *ah;
+       uint32_t val;
+       HAL_STATUS ecode;
+       HAL_BOOL rfStatus;
+
+       HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
+           __func__, sc, (void*) st, (void*) sh);
+
+       /* NB: memory is returned zero'd */
+       ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416));
+       if (ahp5416 == AH_NULL) {
+               HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+                   "%s: cannot allocate memory for state block\n", __func__);
+               *status = HAL_ENOMEM;
+               return AH_NULL;
+       }
+       ar5416InitState(ahp5416, devid, sc, st, sh, status);
+       ahp = &ahp5416->ah_5212;
+       ah = &ahp->ah_priv.h;
+
+       /* XXX override with 9160 specific state */
+       /* override 5416 methods for our needs */
+       ah->ah_detach                   = ar9160Detach;
+
+       AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal;
+       AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal;
+       AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9160_adc_dc_cal;
+       AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9160_adc_init_dc_cal;
+       AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+
+       if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
+               /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
+                   __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
+                   __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+       /* Read Revisions from Chips before taking out of reset */
+       val = OS_REG_READ(ah, AR_SREV);
+       HALDEBUG(ah, HAL_DEBUG_ATTACH,
+           "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
+           __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
+           MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
+       /* NB: include chip type to differentiate from pre-Sowl versions */
+       AH_PRIVATE(ah)->ah_macVersion =
+           (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
+       AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
+       /* XXX extract pcie info */
+
+       /* setup common ini data; rf backends handle remainder */
+       HAL_INI_INIT(&ahp->ah_ini_modes, ar9160Modes, 6);
+       HAL_INI_INIT(&ahp->ah_ini_common, ar9160Common, 2);
+
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar9160BB_RfGain, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar9160Bank0, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar9160Bank1, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar9160Bank2, 2);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar9160Bank3, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar9160Bank6, 3);
+       HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar9160Bank7, 2);
+       if (AR_SREV_SOWL_11(ah))
+               HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac_1_1, 2);
+       else
+               HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac, 2);
+
+       if (!ar5416ChipReset(ah, AH_NULL)) {    /* reset chip */
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+               ecode = HAL_EIO;
+               goto bad;
+       }
+
+       AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
+
+       if (!ar5212ChipTest(ah)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
+                   __func__);
+               ecode = HAL_ESELFTEST;
+               goto bad;
+       }
+
+       /*
+        * Set correct Baseband to analog shift
+        * setting to access analog chips.
+        */
+       OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       /* Read Radio Chip Rev Extract */
+       AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
+       switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
+        case AR_RAD2133_SREV_MAJOR:    /* Sowl: 2G/3x3 */
+       case AR_RAD5133_SREV_MAJOR:     /* Sowl: 2+5G/3x3 */
+               break;
+       default:
+               if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
+                       AH_PRIVATE(ah)->ah_analog5GhzRev =
+                               AR_RAD5133_SREV_MAJOR;
+                       break;
+               }
+#ifdef AH_DEBUG
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: 5G Radio Chip Rev 0x%02X is not supported by "
+                   "this driver\n", __func__,
+                   AH_PRIVATE(ah)->ah_analog5GhzRev);
+               ecode = HAL_ENOTSUPP;
+               goto bad;
+#endif
+       }
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: Attaching AR2133 radio\n",
+           __func__);
+       rfStatus = ar2133RfAttach(ah, &ecode);
+       if (!rfStatus) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
+                   __func__, ecode);
+               goto bad;
+       }
+
+       ecode = ath_hal_v14EepromAttach(ah);
+       if (ecode != HAL_OK)
+               goto bad;
+
+       /*
+        * Got everything we need now to setup the capabilities.
+        */
+       if (!ar9160FillCapabilityInfo(ah)) {
+               ecode = HAL_EEREAD;
+               goto bad;
+       }
+
+       ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
+       if (ecode != HAL_OK) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: error getting mac address from EEPROM\n", __func__);
+               goto bad;
+        }
+       /* XXX How about the serial number ? */
+       /* Read Reg Domain */
+       AH_PRIVATE(ah)->ah_currentRD =
+           ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
+
+       /*
+        * ah_miscMode is populated by ar5416FillCapabilityInfo()
+        * starting from griffin. Set here to make sure that
+        * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
+        * placed into hardware.
+        */
+       if (ahp->ah_miscMode != 0)
+               OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+
+       ar9160AniSetup(ah);                     /* Anti Noise Immunity */
+       ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
+
+       return ah;
+bad:
+       if (ahp)
+               ar9160Detach((struct ath_hal *) ahp);
+       if (status)
+               *status = ecode;
+       return AH_NULL;
+}
+
+void
+ar9160Detach(struct ath_hal *ah)
+{
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
+
+       HALASSERT(ah != AH_NULL);
+       HALASSERT(ah->ah_magic == AR5416_MAGIC);
+
+       ar5416Detach(ah);
+}
+
+/*
+ * Fill all software cached or static hardware state information.
+ * Return failure if capabilities are to come from EEPROM and
+ * cannot be read.
+ */
+static HAL_BOOL
+ar9160FillCapabilityInfo(struct ath_hal *ah)
+{
+       HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+
+       if (!ar5416FillCapabilityInfo(ah))
+               return AH_FALSE;
+       pCap->halCSTSupport = AH_TRUE;
+       pCap->halRifsRxSupport = AH_TRUE;
+       pCap->halRifsTxSupport = AH_TRUE;
+       pCap->halRtsAggrLimit = 64*1024;        /* 802.11n max */
+       pCap->halExtChanDfsSupport = AH_TRUE;
+       pCap->halAutoSleepSupport = AH_FALSE;   /* XXX? */
+       return AH_TRUE;
+}
+
+static const char*
+ar9160Probe(uint16_t vendorid, uint16_t devid)
+{
+       if (vendorid == ATHEROS_VENDOR_ID && devid == AR9160_DEVID_PCI)
+               return "Atheros 9160";
+       return AH_NULL;
+}
+AH_CHIP(AR9160, ar9160Probe, ar9160Attach);
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_debug.h        2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_debug.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AH_DEBUG_H_
+#define _ATH_AH_DEBUG_H_
+/*
+ * Atheros Device Hardware Access Layer (HAL).
+ *
+ * Debug mask definitions.
+ */
+enum {
+       HAL_DEBUG_REGDOMAIN     = 0x00000001,   /* regulatory handling */
+       HAL_DEBUG_ATTACH        = 0x00000002,   /* work done in attach */
+       HAL_DEBUG_RESET         = 0x00000004,   /* reset work */
+       HAL_DEBUG_NFCAL         = 0x00000008,   /* noise floor calibration */
+       HAL_DEBUG_PERCAL        = 0x00000010,   /* periodic calibration */
+       HAL_DEBUG_ANI           = 0x00000020,   /* ANI operation */
+       HAL_DEBUG_PHYIO         = 0x00000040,   /* phy i/o operations */
+       HAL_DEBUG_REGIO         = 0x00000080,   /* register i/o operations */
+       HAL_DEBUG_RFPARAM       = 0x00000100,
+       HAL_DEBUG_TXQUEUE       = 0x00000200,   /* tx queue handling */
+       HAL_DEBUG_TX            = 0x00000400,
+       HAL_DEBUG_TXDESC        = 0x00000800,
+       HAL_DEBUG_RX            = 0x00001000,
+       HAL_DEBUG_RXDESC        = 0x00002000,
+       HAL_DEBUG_KEYCACHE      = 0x00004000,   /* keycache handling */
+       HAL_DEBUG_EEPROM        = 0x00008000,
+       HAL_DEBUG_BEACON        = 0x00010000,   /* beacon setup work */
+       HAL_DEBUG_POWER         = 0x00020000,   /* power management */
+       HAL_DEBUG_INTERRUPT     = 0x00000080,   /* interrupt handling */
+
+       HAL_DEBUG_ANY           = 0xffffffff
+};
+#endif /* _ATH_AH_DEBUG_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_devid.h        2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_devid.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+
+#ifndef _DEV_ATH_DEVID_H_
+#define _DEV_ATH_DEVID_H_
+
+#define ATHEROS_VENDOR_ID      0x168c          /* Atheros PCI vendor ID */
+/*
+ * NB: all Atheros-based devices should have a PCI vendor ID
+ *     of 0x168c, but some vendors, in their infinite wisdom
+ *     do not follow this so we must handle them specially.
+ */
+#define        ATHEROS_3COM_VENDOR_ID  0xa727          /* 3Com 3CRPAG175 vendor ID */
+#define        ATHEROS_3COM2_VENDOR_ID 0x10b7          /* 3Com 3CRDAG675 vendor ID */
+
+/* AR5210 (for reference) */
+#define AR5210_DEFAULT          0x1107          /* No eeprom HW default */
+#define AR5210_PROD             0x0007          /* Final device ID */
+#define AR5210_AP               0x0207          /* Early AP11s */
+
+/* AR5211 */
+#define AR5211_DEFAULT          0x1112          /* No eeprom HW default */
+#define AR5311_DEVID            0x0011          /* Final ar5311 devid */
+#define AR5211_DEVID            0x0012          /* Final ar5211 devid */
+#define AR5211_LEGACY           0xff12          /* Original emulation board */
+#define AR5211_FPGA11B          0xf11b          /* 11b emulation board */
+
+/* AR5212 */
+#define AR5212_DEFAULT          0x1113          /* No eeprom HW default */
+#define AR5212_DEVID            0x0013          /* Final ar5212 devid */
+#define AR5212_FPGA             0xf013          /* Emulation board */
+#define        AR5212_DEVID_IBM        0x1014          /* IBM minipci ID */
+#define AR5212_AR5312_REV2      0x0052          /* AR5312 WMAC (AP31) */
+#define AR5212_AR5312_REV7      0x0057          /* AR5312 WMAC (AP30-040) */
+#define AR5212_AR2313_REV8      0x0058          /* AR2313 WMAC (AP43-030) */
+#define AR5212_AR2315_REV6      0x0086          /* AR2315 WMAC (AP51-Light) */
+#define AR5212_AR2315_REV7      0x0087          /* AR2315 WMAC (AP51-Full) */
+#define AR5212_AR2317_REV1      0x0090          /* AR2317 WMAC (AP61-Light) */
+#define AR5212_AR2317_REV2      0x0091          /* AR2317 WMAC (AP61-Full) */
+
+/* AR5212 compatible devid's also attach to 5212 */
+#define        AR5212_DEVID_0014       0x0014
+#define        AR5212_DEVID_0015       0x0015
+#define        AR5212_DEVID_0016       0x0016
+#define        AR5212_DEVID_0017       0x0017
+#define        AR5212_DEVID_0018       0x0018
+#define        AR5212_DEVID_0019       0x0019
+#define AR5212_AR2413          0x001a          /* AR2413 aka Griffin-lite */
+#define AR5212_AR5413          0x001b          /* Eagle */
+#define AR5212_AR5424          0x001c          /* Condor (PCI express) */
+#define AR5212_AR2417          0x001d          /* Nala, PCI */
+#define AR5212_DEVID_FF19      0xff19          /* XXX PCI express */
+
+/* AR5213 */
+#define        AR5213_SREV_1_0         0x0055
+#define        AR5213_SREV_REG         0x4020
+
+/* AR5416 compatible devid's  */
+#define AR5416_DEVID_PCI       0x0023          /* AR5416 PCI (MB/CB) Owl */
+#define AR5416_DEVID_PCIE      0x0024          /* AR5416 PCI-E (XB) Owl */
+#define AR9160_DEVID_PCI       0x0027          /* AR9160 PCI Sowl */
+#define AR9280_DEVID_PCI       0x0029          /* AR9280 PCI Merlin */
+#define AR9280_DEVID_PCIE      0x002a          /* AR9280 PCI-E Merlin */
+#define AR9285_DEVID_PCIE      0x002b          /* AR9285 PCI-E Kite */
+
+#define        AR_SUBVENDOR_ID_NOG     0x0e11          /* No 11G subvendor ID */
+#define AR_SUBVENDOR_ID_NEW_A  0x7065          /* Update device to new RD */
+#endif /* _DEV_ATH_DEVID_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_eeprom.h       2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_eeprom.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AH_EEPROM_H_
+#define _ATH_AH_EEPROM_H_
+
+#define        AR_EEPROM_VER1          0x1000  /* Version 1.0; 5210 only */
+/*
+ * Version 3 EEPROMs are all 16K.
+ * 3.1 adds turbo limit, antenna gain, 16 CTL's, 11g info,
+ *     and 2.4Ghz ob/db for B & G
+ * 3.2 has more accurate pcdac intercepts and analog chip
+ *     calibration.
+ * 3.3 adds ctl in-band limit, 32 ctl's, and frequency
+ *     expansion
+ * 3.4 adds xr power, gainI, and 2.4 turbo params
+ */
+#define        AR_EEPROM_VER3          0x3000  /* Version 3.0; start of 16k EEPROM */
+#define        AR_EEPROM_VER3_1        0x3001  /* Version 3.1 */
+#define        AR_EEPROM_VER3_2        0x3002  /* Version 3.2 */
+#define        AR_EEPROM_VER3_3        0x3003  /* Version 3.3 */
+#define        AR_EEPROM_VER3_4        0x3004  /* Version 3.4 */
+#define        AR_EEPROM_VER4          0x4000  /* Version 4.x */
+#define        AR_EEPROM_VER4_0        0x4000  /* Version 4.0 */
+#define        AR_EEPROM_VER4_1        0x4001  /* Version 4.0 */
+#define        AR_EEPROM_VER4_2        0x4002  /* Version 4.0 */
+#define        AR_EEPROM_VER4_3        0x4003  /* Version 4.0 */
+#define        AR_EEPROM_VER4_6        0x4006  /* Version 4.0 */
+#define        AR_EEPROM_VER4_7        0x3007  /* Version 4.7 */
+#define        AR_EEPROM_VER4_9        0x4009  /* EEPROM EAR futureproofing */
+#define        AR_EEPROM_VER5          0x5000  /* Version 5.x */
+#define        AR_EEPROM_VER5_0        0x5000  /* Adds new 2413 cal powers and added params */
+#define        AR_EEPROM_VER5_1        0x5001  /* Adds capability values */
+#define        AR_EEPROM_VER5_3        0x5003  /* Adds spur mitigation table */
+#define        AR_EEPROM_VER5_4        0x5004
+/*
+ * Version 14 EEPROMs came in with AR5416.
+ * 14.2 adds txFrameToPaOn, txFrameToDataStart, ht40PowerInc
+ * 14.3 adds bswAtten, bswMargin, swSettle, and base OpFlags for HT20/40
+ */
+#define        AR_EEPROM_VER14         0xE000  /* Version 14.x */
+#define        AR_EEPROM_VER14_1       0xE001  /* Adds 11n support */
+#define        AR_EEPROM_VER14_2       0xE002
+#define        AR_EEPROM_VER14_3       0xE003
+#define        AR_EEPROM_VER14_7       0xE007
+#define        AR_EEPROM_VER14_9       0xE009
+#define        AR_EEPROM_VER14_16      0xE010
+#define        AR_EEPROM_VER14_17      0xE011
+#define        AR_EEPROM_VER14_19      0xE013
+
+enum {
+       AR_EEP_RFKILL,          /* use ath_hal_eepromGetFlag */
+       AR_EEP_AMODE,           /* use ath_hal_eepromGetFlag */
+       AR_EEP_BMODE,           /* use ath_hal_eepromGetFlag */
+       AR_EEP_GMODE,           /* use ath_hal_eepromGetFlag */
+       AR_EEP_TURBO5DISABLE,   /* use ath_hal_eepromGetFlag */
+       AR_EEP_TURBO2DISABLE,   /* use ath_hal_eepromGetFlag */
+       AR_EEP_ISTALON,         /* use ath_hal_eepromGetFlag */
+       AR_EEP_32KHZCRYSTAL,    /* use ath_hal_eepromGetFlag */
+       AR_EEP_MACADDR,         /* uint8_t* */
+       AR_EEP_COMPRESS,        /* use ath_hal_eepromGetFlag */
+       AR_EEP_FASTFRAME,       /* use ath_hal_eepromGetFlag */
+       AR_EEP_AES,             /* use ath_hal_eepromGetFlag */
+       AR_EEP_BURST,           /* use ath_hal_eepromGetFlag */
+       AR_EEP_MAXQCU,          /* uint16_t* */
+       AR_EEP_KCENTRIES,       /* uint16_t* */
+       AR_EEP_NFTHRESH_5,      /* int16_t* */
+       AR_EEP_NFTHRESH_2,      /* int16_t* */
+       AR_EEP_REGDMN_0,        /* uint16_t* */
+       AR_EEP_REGDMN_1,        /* uint16_t* */
+       AR_EEP_OPCAP,           /* uint16_t* */
+       AR_EEP_OPMODE,          /* uint16_t* */
+       AR_EEP_RFSILENT,        /* uint16_t* */
+       AR_EEP_OB_5,            /* uint8_t* */
+       AR_EEP_DB_5,            /* uint8_t* */
+       AR_EEP_OB_2,            /* uint8_t* */
+       AR_EEP_DB_2,            /* uint8_t* */
+       AR_EEP_TXMASK,          /* uint8_t* */
+       AR_EEP_RXMASK,          /* uint8_t* */
+       AR_EEP_RXGAIN_TYPE,     /* uint8_t* */
+       AR_EEP_TXGAIN_TYPE,     /* uint8_t* */
+       AR_EEP_OL_PWRCTRL,      /* use ath_hal_eepromGetFlag */
+       AR_EEP_FSTCLK_5G,       /* use ath_hal_eepromGetFlag */
+       AR_EEP_ANTGAINMAX_5,    /* int8_t* */
+       AR_EEP_ANTGAINMAX_2,    /* int8_t* */
+       AR_EEP_WRITEPROTECT,    /* use ath_hal_eepromGetFlag */
+};
+
+typedef struct {
+       uint16_t        rdEdge;
+       uint16_t        twice_rdEdgePower;
+       HAL_BOOL        flag;
+} RD_EDGES_POWER;
+
+/* XXX should probably be version-dependent */
+#define        SD_NO_CTL               0xf0
+#define        NO_CTL                  0xff
+#define        CTL_MODE_M              0x0f
+#define        CTL_11A                 0
+#define        CTL_11B                 1
+#define        CTL_11G                 2
+#define        CTL_TURBO               3
+#define        CTL_108G                4
+#define        CTL_2GHT20              5
+#define        CTL_5GHT20              6
+#define        CTL_2GHT40              7
+#define        CTL_5GHT40              8
+
+#define        AR_NO_SPUR              0x8000
+
+/* XXX exposed to chip code */
+#define        MAX_RATE_POWER  63
+
+HAL_STATUS     ath_hal_v1EepromAttach(struct ath_hal *ah);
+HAL_STATUS     ath_hal_legacyEepromAttach(struct ath_hal *ah);
+HAL_STATUS     ath_hal_v14EepromAttach(struct ath_hal *ah);
+HAL_STATUS     ath_hal_v4kEepromAttach(struct ath_hal *ah);
+#endif /* _ATH_AH_EEPROM_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_eeprom_v1.c    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_eeprom_v1.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_eeprom_v1.h"
+
+static HAL_STATUS
+v1EepromGet(struct ath_hal *ah, int param, void *val)
+{
+       HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint32_t sum;
+       uint16_t eeval;
+       uint8_t *macaddr;
+       int i;
+
+       switch (param) {
+        case AR_EEP_MACADDR:           /* Get MAC Address */
+               sum = 0;
+               macaddr = val;
+               for (i = 0; i < 3; i++) {
+                       if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(i), &eeval)) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "%s: cannot read EEPROM location %u\n",
+                                   __func__, i);
+                               return HAL_EEREAD;
+                       }
+                       sum += eeval;
+                       macaddr[2*i + 0] = eeval >> 8;
+                       macaddr[2*i + 1] = eeval & 0xff;
+               }
+               if (sum == 0 || sum == 0xffff*3) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n",
+                           __func__, ath_hal_ether_sprintf(macaddr));
+                       return HAL_EEBADMAC;
+               }
+               return HAL_OK;
+        case AR_EEP_REGDMN_0:
+               *(uint16_t *) val = ee->ee_regDomain[0];
+               return HAL_OK;
+        case AR_EEP_RFKILL:
+               HALASSERT(val == AH_NULL);
+               return ee->ee_rfKill ? HAL_OK : HAL_EIO;
+       case AR_EEP_WRITEPROTECT:
+               HALASSERT(val == AH_NULL);
+               return (ee->ee_protect & AR_EEPROM_PROTOTECT_WP_128_191) ?
+                   HAL_OK : HAL_EIO;
+        default:
+               HALASSERT(0);
+               return HAL_EINVAL;
+       }
+}
+
+static HAL_BOOL
+v1EepromSet(struct ath_hal *ah, int param, int v)
+{
+       return HAL_EINVAL;
+}
+
+static HAL_BOOL
+v1EepromDiag(struct ath_hal *ah, int request,
+     const void *args, uint32_t argsize, void **result, uint32_t *resultsize)
+{
+       HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       switch (request) {
+       case HAL_DIAG_EEPROM:
+               *result = ee;
+               *resultsize = sizeof(*ee);
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+static uint16_t
+v1EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
+{
+       return AR_NO_SPUR;
+}
+
+/*
+ * Reclaim any EEPROM-related storage.
+ */
+static void
+v1EepromDetach(struct ath_hal *ah)
+{
+       HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       ath_hal_free(ee);
+       AH_PRIVATE(ah)->ah_eeprom = AH_NULL;
+}
+
+HAL_STATUS
+ath_hal_v1EepromAttach(struct ath_hal *ah)
+{
+       HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t athvals[AR_EEPROM_ATHEROS_MAX];        /* XXX off stack */
+       uint16_t protect, eeprom_version, eeval;
+       uint32_t sum;
+       int i, loc;
+
+       HALASSERT(ee == AH_NULL);
+
+       if (!ath_hal_eepromRead(ah, AR_EEPROM_MAGIC, &eeval)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot read EEPROM magic number\n", __func__);
+               return HAL_EEREAD;
+       }
+       if (eeval != 0x5aa5) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: invalid EEPROM magic number 0x%x\n", __func__, eeval);
+               return HAL_EEMAGIC;
+       }
+
+       if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &protect)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot read EEPROM protection bits; read locked?\n",
+                   __func__);
+               return HAL_EEREAD;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", protect);
+       /* XXX check proper access before continuing */
+
+       if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeprom_version)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: unable to read EEPROM version\n", __func__);
+               return HAL_EEREAD;
+       }
+       if (((eeprom_version>>12) & 0xf) != 1) {
+               /*
+                * This code only groks the version 1 EEPROM layout.
+                */
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: unsupported EEPROM version 0x%x found\n",
+                   __func__, eeprom_version);
+               return HAL_EEVERSION;
+       }
+
+       /*
+        * Read the Atheros EEPROM entries and calculate the checksum.
+        */
+       sum = 0;
+       for (i = 0; i < AR_EEPROM_ATHEROS_MAX; i++) {
+               if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &athvals[i]))
+                       return HAL_EEREAD;
+               sum ^= athvals[i];
+       }
+       if (sum != 0xffff) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n",
+                   __func__, sum);
+               return HAL_EEBADSUM;
+       }
+
+       /*
+        * Valid checksum, fetch the regulatory domain and save values.
+        */
+       if (!ath_hal_eepromRead(ah, AR_EEPROM_REG_DOMAIN, &eeval)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot read regdomain from EEPROM\n", __func__);
+               return HAL_EEREAD;
+       }
+
+       ee = ath_hal_malloc(sizeof(HAL_EEPROM_v1));
+       if (ee == AH_NULL) {
+               /* XXX message */
+               return HAL_ENOMEM;
+       }
+
+       ee->ee_version          = eeprom_version;
+       ee->ee_protect          = protect;
+       ee->ee_antenna          = athvals[2];
+       ee->ee_biasCurrents     = athvals[3];
+       ee->ee_thresh62 = athvals[4] & 0xff;
+       ee->ee_xlnaOn           = (athvals[4] >> 8) & 0xff;
+       ee->ee_xpaOn            = athvals[5] & 0xff;
+       ee->ee_xpaOff           = (athvals[5] >> 8) & 0xff;
+       ee->ee_regDomain[0]     = (athvals[6] >> 8) & 0xff;
+       ee->ee_regDomain[1]     = athvals[6] & 0xff;
+       ee->ee_regDomain[2]     = (athvals[7] >> 8) & 0xff;
+       ee->ee_regDomain[3]     = athvals[7] & 0xff;
+       ee->ee_rfKill           = athvals[8] & 0x1;
+       ee->ee_devType          = (athvals[8] >> 1) & 0x7;
+
+       for (i = 0, loc = AR_EEPROM_ATHEROS_TP_SETTINGS; i < AR_CHANNELS_MAX; i++, loc += AR_TP_SETTINGS_SIZE) {
+               struct tpcMap *chan = &ee->ee_tpc[i];
+
+               /* Copy pcdac and gain_f values from EEPROM */
+               chan->pcdac[0]  = (athvals[loc] >> 10) & 0x3F;
+               chan->gainF[0]  = (athvals[loc] >> 4) & 0x3F;
+               chan->pcdac[1]  = ((athvals[loc] << 2) & 0x3C)
+                               | ((athvals[loc+1] >> 14) & 0x03);
+               chan->gainF[1]  = (athvals[loc+1] >> 8) & 0x3F;
+               chan->pcdac[2]  = (athvals[loc+1] >> 2) & 0x3F;
+               chan->gainF[2]  = ((athvals[loc+1] << 4) & 0x30)
+                               | ((athvals[loc+2] >> 12) & 0x0F);
+               chan->pcdac[3]  = (athvals[loc+2] >> 6) & 0x3F;
+               chan->gainF[3]  = athvals[loc+2] & 0x3F;
+               chan->pcdac[4]  = (athvals[loc+3] >> 10) & 0x3F;
+               chan->gainF[4]  = (athvals[loc+3] >> 4) & 0x3F;
+               chan->pcdac[5]  = ((athvals[loc+3] << 2) & 0x3C)
+                               | ((athvals[loc+4] >> 14) & 0x03);
+               chan->gainF[5]  = (athvals[loc+4] >> 8) & 0x3F;
+               chan->pcdac[6]  = (athvals[loc+4] >> 2) & 0x3F;
+               chan->gainF[6]  = ((athvals[loc+4] << 4) & 0x30)
+                               | ((athvals[loc+5] >> 12) & 0x0F);
+               chan->pcdac[7]  = (athvals[loc+5] >> 6) & 0x3F;
+               chan->gainF[7]  = athvals[loc+5] & 0x3F;
+               chan->pcdac[8]  = (athvals[loc+6] >> 10) & 0x3F;
+               chan->gainF[8]  = (athvals[loc+6] >> 4) & 0x3F;
+               chan->pcdac[9]  = ((athvals[loc+6] << 2) & 0x3C)
+                               | ((athvals[loc+7] >> 14) & 0x03);
+               chan->gainF[9]  = (athvals[loc+7] >> 8) & 0x3F;
+               chan->pcdac[10] = (athvals[loc+7] >> 2) & 0x3F;
+               chan->gainF[10] = ((athvals[loc+7] << 4) & 0x30)
+                               | ((athvals[loc+8] >> 12) & 0x0F);
+
+               /* Copy Regulatory Domain and Rate Information from EEPROM */
+               chan->rate36    = (athvals[loc+8] >> 6) & 0x3F;
+               chan->rate48    = athvals[loc+8] & 0x3F;
+               chan->rate54    = (athvals[loc+9] >> 10) & 0x3F;
+               chan->regdmn[0] = (athvals[loc+9] >> 4) & 0x3F;
+               chan->regdmn[1] = ((athvals[loc+9] << 2) & 0x3C)
+                               | ((athvals[loc+10] >> 14) & 0x03);
+               chan->regdmn[2] = (athvals[loc+10] >> 8) & 0x3F;
+               chan->regdmn[3] = (athvals[loc+10] >> 2) & 0x3F;
+       }
+
+       AH_PRIVATE(ah)->ah_eeprom = ee;
+       AH_PRIVATE(ah)->ah_eeversion = eeprom_version;
+       AH_PRIVATE(ah)->ah_eepromDetach = v1EepromDetach;
+       AH_PRIVATE(ah)->ah_eepromGet = v1EepromGet;
+       AH_PRIVATE(ah)->ah_eepromSet = v1EepromSet;
+       AH_PRIVATE(ah)->ah_getSpurChan = v1EepromGetSpurChan;
+       AH_PRIVATE(ah)->ah_eepromDiag = v1EepromDiag;
+       return HAL_OK;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_eeprom_v1.h    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_eeprom_v1.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AH_EEPROM_V1_H_
+#define _ATH_AH_EEPROM_V1_H_
+
+#include "ah_eeprom.h"
+
+/*
+ * EEPROM defines for Version 1 Crete EEPROM.
+ *
+ * The EEPROM is segmented into three sections:
+ *
+ *    PCI/Cardbus default configuration settings
+ *    Cardbus CIS tuples and vendor-specific data
+ *    Atheros-specific data
+ *
+ * EEPROM entries are read 32-bits at a time through the PCI bus
+ * interface but are all 16-bit values.
+ *
+ * Access to the Atheros-specific data is controlled by protection
+ * bits and the data is checksum'd.  The driver reads the Atheros
+ * data from the EEPROM at attach and caches it in its private state.
+ * This data includes the local regulatory domain, channel calibration
+ * settings, and phy-related configuration settings.
+ */
+#define        AR_EEPROM_MAC(i)        (0x1f-(i))/* MAC address word */
+#define        AR_EEPROM_MAGIC         0x3d    /* magic number */
+#define AR_EEPROM_PROTECT      0x3f    /* Atheros segment protect register */
+#define        AR_EEPROM_PROTOTECT_WP_128_191  0x80
+#define AR_EEPROM_REG_DOMAIN   0xbf    /* Current regulatory domain register */
+#define AR_EEPROM_ATHEROS_BASE 0xc0    /* Base of Atheros-specific data */
+#define AR_EEPROM_ATHEROS_MAX  64      /* 64x2=128 bytes of EEPROM settings */
+#define        AR_EEPROM_ATHEROS(n)    (AR_EEPROM_ATHEROS_BASE+(n))
+#define        AR_EEPROM_VERSION       AR_EEPROM_ATHEROS(1)
+#define AR_EEPROM_ATHEROS_TP_SETTINGS  0x09    /* Transmit power settings */
+#define AR_REG_DOMAINS_MAX     4       /* # of Regulatory Domains */
+#define AR_CHANNELS_MAX                5       /* # of Channel calibration groups */
+#define AR_TP_SETTINGS_SIZE    11      /* # locations/Channel group */
+#define AR_TP_SCALING_ENTRIES  11      /* # entries in transmit power dBm->pcdac */
+
+/*
+ * NB: we store the rfsilent select+polarity data packed
+ *     with the encoding used in later parts so values
+ *     returned to applications are consistent.
+ */
+#define AR_EEPROM_RFSILENT_GPIO_SEL    0x001c
+#define AR_EEPROM_RFSILENT_GPIO_SEL_S  2
+#define AR_EEPROM_RFSILENT_POLARITY    0x0002
+#define AR_EEPROM_RFSILENT_POLARITY_S  1
+
+#define AR_I2DBM(x)    ((uint8_t)((x * 2) + 3))
+
+/*
+ * Transmit power and channel calibration settings.
+ */
+struct tpcMap {
+       uint8_t         pcdac[AR_TP_SCALING_ENTRIES];
+       uint8_t         gainF[AR_TP_SCALING_ENTRIES];
+       uint8_t         rate36;
+       uint8_t         rate48;
+       uint8_t         rate54;
+       uint8_t         regdmn[AR_REG_DOMAINS_MAX];
+};
+
+/*
+ * Information retrieved from EEPROM.
+ */
+typedef struct {
+       uint16_t        ee_version;             /* Version field */
+       uint16_t        ee_protect;             /* EEPROM protect field */
+       uint16_t        ee_antenna;             /* Antenna Settings */
+       uint16_t        ee_biasCurrents;        /* OB, DB */
+       uint8_t         ee_thresh62;            /* thresh62 */
+       uint8_t         ee_xlnaOn;              /* External LNA timing */
+       uint8_t         ee_xpaOff;              /* Extern output stage timing */
+       uint8_t         ee_xpaOn;               /* Extern output stage timing */
+       uint8_t         ee_rfKill;              /* Single low bit signalling if RF Kill is implemented */
+       uint8_t         ee_devType;             /* Type: PCI, miniPCI, CB */
+       uint8_t         ee_regDomain[AR_REG_DOMAINS_MAX];
+                                               /* calibrated reg domains */
+       struct tpcMap   ee_tpc[AR_CHANNELS_MAX];
+} HAL_EEPROM_v1;
+#endif /* _ATH_AH_EEPROM_V1_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_eeprom_v14.c   2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_eeprom_v14.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include <sys/endian.h>
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_eeprom_v14.h"
+
+static HAL_STATUS
+v14EepromGet(struct ath_hal *ah, int param, void *val)
+{
+#define        CHAN_A_IDX      0
+#define        CHAN_B_IDX      1
+#define        IS_VERS(op, v)  ((pBase->version & AR5416_EEP_VER_MINOR_MASK) op (v))
+       HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const MODAL_EEP_HEADER *pModal = ee->ee_base.modalHeader;
+       const BASE_EEP_HEADER  *pBase  = &ee->ee_base.baseEepHeader;
+       uint32_t sum;
+       uint8_t *macaddr;
+       int i;
+
+       switch (param) {
+        case AR_EEP_NFTHRESH_5:
+               *(int16_t *)val = pModal[0].noiseFloorThreshCh[0];
+               return HAL_OK;
+        case AR_EEP_NFTHRESH_2:
+               *(int16_t *)val = pModal[1].noiseFloorThreshCh[0];
+               return HAL_OK;
+        case AR_EEP_MACADDR:           /* Get MAC Address */
+               sum = 0;
+               macaddr = val;
+               for (i = 0; i < 6; i++) {
+                       macaddr[i] = pBase->macAddr[i];
+                       sum += pBase->macAddr[i];
+               }
+               if (sum == 0 || sum == 0xffff*3) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n",
+                           __func__, ath_hal_ether_sprintf(macaddr));
+                       return HAL_EEBADMAC;
+               } else
+                       return HAL_OK;
+        case AR_EEP_REGDMN_0:
+               return pBase->regDmn[0];
+        case AR_EEP_REGDMN_1:
+               return pBase->regDmn[1];
+        case AR_EEP_OPCAP:
+               return pBase->deviceCap;
+        case AR_EEP_OPMODE:
+               return pBase->opCapFlags;
+        case AR_EEP_RFSILENT:
+               return pBase->rfSilent;
+       case AR_EEP_OB_5:
+               return pModal[CHAN_A_IDX].ob;
+       case AR_EEP_DB_5:
+               return pModal[CHAN_A_IDX].db;
+       case AR_EEP_OB_2:
+               return pModal[CHAN_B_IDX].ob;
+       case AR_EEP_DB_2:
+               return pModal[CHAN_B_IDX].db;
+       case AR_EEP_TXMASK:
+               return pBase->txMask;
+       case AR_EEP_RXMASK:
+               return pBase->rxMask;
+       case AR_EEP_RXGAIN_TYPE:
+               return IS_VERS(>=, AR5416_EEP_MINOR_VER_17) ?
+                   pBase->rxGainType : AR5416_EEP_RXGAIN_ORIG;
+       case AR_EEP_TXGAIN_TYPE:
+               return IS_VERS(>=, AR5416_EEP_MINOR_VER_19) ?
+                   pBase->txGainType : AR5416_EEP_TXGAIN_ORIG;
+       case AR_EEP_FSTCLK_5G:
+               return IS_VERS(>, AR5416_EEP_MINOR_VER_16) ?
+                   pBase->fastClk5g : AH_TRUE;
+       case AR_EEP_OL_PWRCTRL:
+               HALASSERT(val == AH_NULL);
+               return pBase->openLoopPwrCntl ?  HAL_OK : HAL_EIO;
+       case AR_EEP_AMODE:
+               HALASSERT(val == AH_NULL);
+               return pBase->opCapFlags & AR5416_OPFLAGS_11A ?
+                   HAL_OK : HAL_EIO;
+       case AR_EEP_BMODE:
+       case AR_EEP_GMODE:
+               HALASSERT(val == AH_NULL);
+               return pBase->opCapFlags & AR5416_OPFLAGS_11G ?
+                   HAL_OK : HAL_EIO;
+       case AR_EEP_32KHZCRYSTAL:
+       case AR_EEP_COMPRESS:
+       case AR_EEP_FASTFRAME:          /* XXX policy decision, h/w can do it */
+       case AR_EEP_WRITEPROTECT:       /* NB: no write protect bit */
+               HALASSERT(val == AH_NULL);
+               /* fall thru... */
+       case AR_EEP_MAXQCU:             /* NB: not in opCapFlags */
+       case AR_EEP_KCENTRIES:          /* NB: not in opCapFlags */
+               return HAL_EIO;
+       case AR_EEP_AES:
+       case AR_EEP_BURST:
+        case AR_EEP_RFKILL:
+       case AR_EEP_TURBO5DISABLE:
+       case AR_EEP_TURBO2DISABLE:
+               HALASSERT(val == AH_NULL);
+               return HAL_OK;
+       case AR_EEP_ANTGAINMAX_2:
+               *(int8_t *) val = ee->ee_antennaGainMax[1];
+               return HAL_OK;
+       case AR_EEP_ANTGAINMAX_5:
+               *(int8_t *) val = ee->ee_antennaGainMax[0];
+               return HAL_OK;
+        default:
+               HALASSERT(0);
+               return HAL_EINVAL;
+       }
+#undef IS_VERS
+#undef CHAN_A_IDX
+#undef CHAN_B_IDX
+}
+
+static HAL_BOOL
+v14EepromSet(struct ath_hal *ah, int param, int v)
+{
+       HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       switch (param) {
+       case AR_EEP_ANTGAINMAX_2:
+               ee->ee_antennaGainMax[1] = (int8_t) v;
+               return HAL_OK;
+       case AR_EEP_ANTGAINMAX_5:
+               ee->ee_antennaGainMax[0] = (int8_t) v;
+               return HAL_OK;
+       }
+       return HAL_EINVAL;
+}
+
+static HAL_BOOL
+v14EepromDiag(struct ath_hal *ah, int request,
+     const void *args, uint32_t argsize, void **result, uint32_t *resultsize)
+{
+       HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       switch (request) {
+       case HAL_DIAG_EEPROM:
+               *result = &ee->ee_base;
+               *resultsize = sizeof(ee->ee_base);
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+#if 0
+/* XXX conditionalize by target byte order */
+#ifndef bswap16
+static __inline__ uint16_t
+__bswap16(uint16_t _x)
+{
+       return ((uint16_t)(
+             (((const uint8_t *)(&_x))[0]    ) |
+             (((const uint8_t *)(&_x))[1]<< 8))
+       );
+}
+#endif
+#endif
+
+/* Do structure specific swaps if Eeprom format is non native to host */
+static void
+eepromSwap(struct ar5416eeprom *ee)
+{
+       uint32_t integer, i, j;
+       uint16_t word;
+       MODAL_EEP_HEADER *pModal;
+
+       /* convert Base Eep header */
+       word = __bswap16(ee->baseEepHeader.length);
+       ee->baseEepHeader.length = word;
+
+       word = __bswap16(ee->baseEepHeader.checksum);
+       ee->baseEepHeader.checksum = word;
+
+       word = __bswap16(ee->baseEepHeader.version);
+       ee->baseEepHeader.version = word;
+
+       word = __bswap16(ee->baseEepHeader.regDmn[0]);
+       ee->baseEepHeader.regDmn[0] = word;
+
+       word = __bswap16(ee->baseEepHeader.regDmn[1]);
+       ee->baseEepHeader.regDmn[1] = word;
+
+       word = __bswap16(ee->baseEepHeader.rfSilent);
+       ee->baseEepHeader.rfSilent = word;
+
+       word = __bswap16(ee->baseEepHeader.blueToothOptions);
+       ee->baseEepHeader.blueToothOptions = word;
+
+       word = __bswap16(ee->baseEepHeader.deviceCap);
+       ee->baseEepHeader.deviceCap = word;
+
+       /* convert Modal Eep header */
+       for (j = 0; j < 2; j++) {
+               pModal = &ee->modalHeader[j];
+
+               /* XXX linux/ah_osdep.h only defines __bswap32 for BE */
+               integer = __bswap32(pModal->antCtrlCommon);
+               pModal->antCtrlCommon = integer;
+
+               for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+                       integer = __bswap32(pModal->antCtrlChain[i]);
+                       pModal->antCtrlChain[i] = integer;
+               }
+
+               for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+                       word = __bswap16(pModal->spurChans[i].spurChan);
+                       pModal->spurChans[i].spurChan = word;
+               }
+       }
+}
+
+static uint16_t
+v14EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
+{
+       HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       HALASSERT(0 <= ix && ix <  AR5416_EEPROM_MODAL_SPURS);
+       return ee->ee_base.modalHeader[is2GHz].spurChans[ix].spurChan;
+}
+
+/**************************************************************************
+ * fbin2freq
+ *
+ * Get channel value from binary representation held in eeprom
+ * RETURNS: the frequency in MHz
+ */
+static uint16_t
+fbin2freq(uint8_t fbin, HAL_BOOL is2GHz)
+{
+       /*
+        * Reserved value 0xFF provides an empty definition both as
+        * an fbin and as a frequency - do not convert
+        */
+       if (fbin == AR5416_BCHAN_UNUSED)
+               return fbin;
+       return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+/*
+ * Copy EEPROM Conformance Testing Limits contents
+ * into the allocated space
+ */
+/* USE CTLS from chain zero */
+#define CTL_CHAIN      0
+
+static void
+v14EepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_v14 *ee)
+{
+       RD_EDGES_POWER *rep = ee->ee_rdEdgesPower;
+       int i, j;
+
+       HALASSERT(AR5416_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES);
+
+       for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR5416_NUM_CTLS; i++) {
+               for (j = 0; j < NUM_EDGES; j ++) {
+                       /* XXX Confirm this is the right thing to do when an invalid channel is stored */
+                       if (ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel == AR5416_BCHAN_UNUSED) {
+                               rep[j].rdEdge = 0;
+                               rep[j].twice_rdEdgePower = 0;
+                               rep[j].flag = 0;
+                       } else {
+                               rep[j].rdEdge = fbin2freq(
+                                   ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].bChannel,
+                                   (ee->ee_base.ctlIndex[i] & CTL_MODE_M) != CTL_11A);
+                               rep[j].twice_rdEdgePower = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_POWER);
+                               rep[j].flag = MS(ee->ee_base.ctlData[i].ctlEdges[CTL_CHAIN][j].tPowerFlag, CAL_CTL_EDGES_FLAG) != 0;
+                       }
+               }
+               rep += NUM_EDGES;
+       }
+       ee->ee_numCtls = i;
+       HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM,
+           "%s Numctls = %u\n",__func__,i);
+}
+
+/*
+ * Reclaim any EEPROM-related storage.
+ */
+static void
+v14EepromDetach(struct ath_hal *ah)
+{
+       HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       ath_hal_free(ee);
+       AH_PRIVATE(ah)->ah_eeprom = AH_NULL;
+}
+
+#define owl_get_eep_ver(_ee)   \
+    (((_ee)->ee_base.baseEepHeader.version >> 12) & 0xF)
+#define owl_get_eep_rev(_ee)   \
+    (((_ee)->ee_base.baseEepHeader.version) & 0xFFF)
+
+HAL_STATUS
+ath_hal_v14EepromAttach(struct ath_hal *ah)
+{
+#define        NW(a)   (sizeof(a) / sizeof(uint16_t))
+       HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint16_t *eep_data, magic;
+       HAL_BOOL need_swap;
+       u_int w, off, len;
+       uint32_t sum;
+
+       HALASSERT(ee == AH_NULL);
+
+       if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s Error reading Eeprom MAGIC\n", __func__);
+               return HAL_EEREAD;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n",
+           __func__, magic);
+       if (magic != AR5416_EEPROM_MAGIC) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n");
+               return HAL_EEMAGIC;
+       }
+
+       ee = ath_hal_malloc(sizeof(HAL_EEPROM_v14));
+       if (ee == AH_NULL) {
+               /* XXX message */
+               return HAL_ENOMEM;
+       }
+
+       eep_data = (uint16_t *)&ee->ee_base;
+       for (w = 0; w < NW(struct ar5416eeprom); w++) {
+               off = owl_eep_start_loc + w;    /* NB: AP71 starts at 0 */
+               if (!ath_hal_eepromRead(ah, off, &eep_data[w])) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s eeprom read error at offset 0x%x\n",
+                           __func__, off);
+                       return HAL_EEREAD;
+               }
+       }
+       /* Convert to eeprom native eeprom endian format */
+       if (isBigEndian()) {
+               for (w = 0; w < NW(struct ar5416eeprom); w++)
+                       eep_data[w] = __bswap16(eep_data[w]);
+       }
+
+       /*
+        * At this point, we're in the native eeprom endian format
+        * Now, determine the eeprom endian by looking at byte 26??
+        */
+       need_swap = ((ee->ee_base.baseEepHeader.eepMisc & AR5416_EEPMISC_BIG_ENDIAN) != 0) ^ isBigEndian();
+       if (need_swap) {
+               HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM,
+                   "Byte swap EEPROM contents.\n");
+               len = __bswap16(ee->ee_base.baseEepHeader.length);
+       } else {
+               len = ee->ee_base.baseEepHeader.length;
+       }
+       len = AH_MIN(len, sizeof(struct ar5416eeprom)) / sizeof(uint16_t);
+
+       /* Apply the checksum, done in native eeprom format */
+       /* XXX - Need to check to make sure checksum calculation is done
+        * in the correct endian format.  Right now, it seems it would
+        * cast the raw data to host format and do the calculation, which may
+        * not be correct as the calculation may need to be done in the native
+        * eeprom format
+        */
+       sum = 0;
+       for (w = 0; w < len; w++)
+               sum ^= eep_data[w];
+       /* Check CRC - Attach should fail on a bad checksum */
+       if (sum != 0xffff) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "Bad EEPROM checksum 0x%x (Len=%u)\n", sum, len);
+               return HAL_EEBADSUM;
+       }
+
+       if (need_swap)
+               eepromSwap(&ee->ee_base);       /* byte swap multi-byte data */
+
+       /* swap words 0+2 so version is at the front */
+       magic = eep_data[0];
+       eep_data[0] = eep_data[2];
+       eep_data[2] = magic;
+
+       HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM,
+           "%s Eeprom Version %u.%u\n", __func__,
+           owl_get_eep_ver(ee), owl_get_eep_rev(ee));
+
+       /* NB: must be after all byte swapping */
+       if (owl_get_eep_ver(ee) != AR5416_EEP_VER) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "Bad EEPROM version 0x%x\n", owl_get_eep_ver(ee));
+               return HAL_EEBADSUM;
+       }
+
+       v14EepromReadCTLInfo(ah, ee);           /* Get CTLs */
+
+       AH_PRIVATE(ah)->ah_eeprom = ee;
+       AH_PRIVATE(ah)->ah_eeversion = ee->ee_base.baseEepHeader.version;
+       AH_PRIVATE(ah)->ah_eepromDetach = v14EepromDetach;
+       AH_PRIVATE(ah)->ah_eepromGet = v14EepromGet;
+       AH_PRIVATE(ah)->ah_eepromSet = v14EepromSet;
+       AH_PRIVATE(ah)->ah_getSpurChan = v14EepromGetSpurChan;
+       AH_PRIVATE(ah)->ah_eepromDiag = v14EepromDiag;
+       return HAL_OK;
+#undef NW
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_eeprom_v14.h   2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_eeprom_v14.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _AH_EEPROM_V14_H_
+#define _AH_EEPROM_V14_H_
+
+#include "ah_eeprom.h"
+
+/* reg_off = 4 * (eep_off) */
+#define AR5416_EEPROM_S                        2
+#define AR5416_EEPROM_OFFSET           0x2000
+#define AR5416_EEPROM_START_ADDR       0x503f1200
+#define AR5416_EEPROM_MAX              0xae0 /* Ignore for the moment used only on the flash implementations */
+#define AR5416_EEPROM_MAGIC            0xa55a
+#define AR5416_EEPROM_MAGIC_OFFSET     0x0
+
+#define owl_get_ntxchains(_txchainmask) \
+    (((_txchainmask >> 2) & 1) + ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
+
+#ifdef __LINUX_ARM_ARCH__ /* AP71 */
+#define owl_eep_start_loc              0
+#else
+#define owl_eep_start_loc              256
+#endif
+
+/* End temp defines */
+
+#define AR5416_EEP_NO_BACK_VER         0x1
+#define AR5416_EEP_VER                 0xE
+#define AR5416_EEP_VER_MINOR_MASK      0xFFF
+// Adds modal params txFrameToPaOn, txFrametoDataStart, ht40PowerInc
+#define AR5416_EEP_MINOR_VER_2         0x2
+// Adds modal params bswAtten, bswMargin, swSettle and base OpFlags for HT20/40 Disable
+#define AR5416_EEP_MINOR_VER_3         0x3
+#define AR5416_EEP_MINOR_VER_7         0x7
+#define AR5416_EEP_MINOR_VER_9         0x9
+#define AR5416_EEP_MINOR_VER_16                0x10
+#define AR5416_EEP_MINOR_VER_17                0x11
+#define AR5416_EEP_MINOR_VER_19                0x13
+
+// 16-bit offset location start of calibration struct
+#define AR5416_EEP_START_LOC           256
+#define AR5416_NUM_5G_CAL_PIERS        8
+#define AR5416_NUM_2G_CAL_PIERS        4
+#define AR5416_NUM_5G_20_TARGET_POWERS  8
+#define AR5416_NUM_5G_40_TARGET_POWERS  8
+#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_NUM_2G_20_TARGET_POWERS  4
+#define AR5416_NUM_2G_40_TARGET_POWERS  4
+#define AR5416_NUM_CTLS                24
+#define AR5416_NUM_BAND_EDGES          8
+#define AR5416_NUM_PD_GAINS            4
+#define AR5416_PD_GAINS_IN_MASK        4
+#define AR5416_PD_GAIN_ICEPTS          5
+#define AR5416_EEPROM_MODAL_SPURS      5
+#define AR5416_MAX_RATE_POWER          63
+#define AR5416_NUM_PDADC_VALUES        128
+#define AR5416_NUM_RATES               16
+#define AR5416_BCHAN_UNUSED            0xFF
+#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
+#define AR5416_EEPMISC_BIG_ENDIAN      0x01
+#define FREQ2FBIN(x,y)                         ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
+#define AR5416_MAX_CHAINS              3
+#define AR5416_ANT_16S                 25
+
+#define AR5416_NUM_ANT_CHAIN_FIELDS     7
+#define AR5416_NUM_ANT_COMMON_FIELDS    4
+#define AR5416_SIZE_ANT_CHAIN_FIELD     3
+#define AR5416_SIZE_ANT_COMMON_FIELD    4
+#define AR5416_ANT_CHAIN_MASK           0x7
+#define AR5416_ANT_COMMON_MASK          0xf
+#define AR5416_CHAIN_0_IDX              0
+#define AR5416_CHAIN_1_IDX              1
+#define AR5416_CHAIN_2_IDX              2
+
+#define        AR5416_OPFLAGS_11A              0x01
+#define        AR5416_OPFLAGS_11G              0x02
+#define        AR5416_OPFLAGS_5G_HT40          0x04
+#define        AR5416_OPFLAGS_2G_HT40          0x08
+#define        AR5416_OPFLAGS_5G_HT20          0x10
+#define        AR5416_OPFLAGS_2G_HT20          0x20
+
+/* RF silent fields in EEPROM */
+#define        EEP_RFSILENT_ENABLED            0x0001  /* enabled/disabled */
+#define        EEP_RFSILENT_ENABLED_S          0
+#define        EEP_RFSILENT_POLARITY           0x0002  /* polarity */
+#define        EEP_RFSILENT_POLARITY_S         1
+#define        EEP_RFSILENT_GPIO_SEL           0x001c  /* gpio PIN */
+#define        EEP_RFSILENT_GPIO_SEL_S         2
+
+/* Rx gain type values */
+#define        AR5416_EEP_RXGAIN_23dB_BACKOFF  0
+#define        AR5416_EEP_RXGAIN_13dB_BACKOFF  1
+#define        AR5416_EEP_RXGAIN_ORIG          2
+
+/* Tx gain type values */
+#define        AR5416_EEP_TXGAIN_ORIG          0
+#define        AR5416_EEP_TXGAIN_HIGH_POWER    1
+
+typedef struct spurChanStruct {
+       uint16_t        spurChan;
+       uint8_t         spurRangeLow;
+       uint8_t         spurRangeHigh;
+} __packed SPUR_CHAN;
+
+typedef struct CalTargetPowerLegacy {
+       uint8_t         bChannel;
+       uint8_t         tPow2x[4];
+} __packed CAL_TARGET_POWER_LEG;
+
+typedef struct CalTargetPowerHt {
+       uint8_t         bChannel;
+       uint8_t         tPow2x[8];
+} __packed CAL_TARGET_POWER_HT;
+
+typedef struct CalCtlEdges {
+       uint8_t         bChannel;
+       uint8_t         tPowerFlag;     /* [0..5] tPower [6..7] flag */
+#define        CAL_CTL_EDGES_POWER     0x3f
+#define        CAL_CTL_EDGES_POWER_S   0
+#define        CAL_CTL_EDGES_FLAG      0xc0
+#define        CAL_CTL_EDGES_FLAG_S    6
+} __packed CAL_CTL_EDGES;
+
+/*
+ * NB: The format in EEPROM has words 0 and 2 swapped (i.e. version
+ * and length are swapped).  We reverse their position after reading
+ * the data into host memory so the version field is at the same
+ * offset as in previous EEPROM layouts.  This makes utilities that
+ * inspect the EEPROM contents work without looking at the PCI device
+ * id which may or may not be reliable.
+ */
+typedef struct BaseEepHeader {
+       uint16_t        version;        /* NB: length in EEPROM */
+       uint16_t        checksum;
+       uint16_t        length;         /* NB: version in EEPROM */
+       uint8_t         opCapFlags;
+       uint8_t         eepMisc;
+       uint16_t        regDmn[2];
+       uint8_t         macAddr[6];
+       uint8_t         rxMask;
+       uint8_t         txMask;
+       uint16_t        rfSilent;
+       uint16_t        blueToothOptions;
+       uint16_t        deviceCap;
+       uint32_t        binBuildNumber;
+       uint8_t         deviceType;
+       uint8_t         pwdclkind;
+       uint8_t         fastClk5g;
+       uint8_t         divChain;
+       uint8_t         rxGainType;
+       uint8_t         dacHiPwrMode;   /* use the DAC high power mode (MB91) */
+       uint8_t         openLoopPwrCntl;/* 1: use open loop power control,
+                                          0: use closed loop power control */
+       uint8_t         dacLpMode;
+       uint8_t         txGainType;     /* high power tx gain table support */
+       uint8_t         rcChainMask;    /* "1" if the card is an HB93 1x2 */
+       uint8_t         futureBase[24];
+} __packed BASE_EEP_HEADER; // 64 B
+
+typedef struct ModalEepHeader {
+       uint32_t        antCtrlChain[AR5416_MAX_CHAINS];        // 12
+       uint32_t        antCtrlCommon;                          // 4
+       int8_t          antennaGainCh[AR5416_MAX_CHAINS];       // 3
+       uint8_t         switchSettling;                         // 1
+       uint8_t         txRxAttenCh[AR5416_MAX_CHAINS];         // 3
+       uint8_t         rxTxMarginCh[AR5416_MAX_CHAINS];        // 3
+       uint8_t         adcDesiredSize;                         // 1
+       int8_t          pgaDesiredSize;                         // 1
+       uint8_t         xlnaGainCh[AR5416_MAX_CHAINS];          // 3
+       uint8_t         txEndToXpaOff;                          // 1
+       uint8_t         txEndToRxOn;                            // 1
+       uint8_t         txFrameToXpaOn;                         // 1
+       uint8_t         thresh62;                               // 1
+       uint8_t         noiseFloorThreshCh[AR5416_MAX_CHAINS];  // 3
+       uint8_t         xpdGain;                                // 1
+       uint8_t         xpd;                                    // 1
+       int8_t          iqCalICh[AR5416_MAX_CHAINS];            // 1
+       int8_t          iqCalQCh[AR5416_MAX_CHAINS];            // 1
+       uint8_t         pdGainOverlap;                          // 1
+       uint8_t         ob;                                     // 1
+       uint8_t         db;                                     // 1
+       uint8_t         xpaBiasLvl;                             // 1
+       uint8_t         pwrDecreaseFor2Chain;                   // 1
+       uint8_t         pwrDecreaseFor3Chain;                   // 1 -> 48 B
+       uint8_t         txFrameToDataStart;                     // 1
+       uint8_t         txFrameToPaOn;                          // 1
+       uint8_t         ht40PowerIncForPdadc;                   // 1
+       uint8_t         bswAtten[AR5416_MAX_CHAINS];            // 3
+       uint8_t         bswMargin[AR5416_MAX_CHAINS];           // 3
+       uint8_t         swSettleHt40;                           // 1
+       uint8_t         xatten2Db[AR5416_MAX_CHAINS];           // 3 -> New for AR9280 (0xa20c/b20c 11:6)
+       uint8_t         xatten2Margin[AR5416_MAX_CHAINS];       // 3 -> New for AR9280 (0xa20c/b20c 21:17)
+       uint8_t         ob_ch1;                         // 1 -> ob and db become chain specific from AR9280
+       uint8_t         db_ch1;                         // 1
+       uint8_t         flagBits;                       // 1
+#define        AR5416_EEP_FLAG_USEANT1         0x01    /* +1 configured antenna */
+#define        AR5416_EEP_FLAG_FORCEXPAON      0x02    /* force XPA bit for 5G */
+#define        AR5416_EEP_FLAG_LOCALBIAS       0x04    /* enable local bias */
+#define        AR5416_EEP_FLAG_FEMBANDSELECT   0x08    /* FEM band select used */
+#define        AR5416_EEP_FLAG_XLNABUFIN       0x10
+#define        AR5416_EEP_FLAG_XLNAISEL        0x60
+#define        AR5416_EEP_FLAG_XLNAISEL_S      5
+#define        AR5416_EEP_FLAG_XLNABUFMODE     0x80
+       uint8_t         miscBits;                       // [0..1]: bb_tx_dac_scale_cck
+       uint16_t        xpaBiasLvlFreq[3];              // 3
+       uint8_t         futureModal[6];                 // 6
+
+       SPUR_CHAN spurChans[AR5416_EEPROM_MODAL_SPURS]; // 20 B
+} __packed MODAL_EEP_HEADER;                           // == 100 B
+
+typedef struct calDataPerFreqOpLoop {
+       uint8_t         pwrPdg[2][5]; /* power measurement */
+       uint8_t         vpdPdg[2][5]; /* pdadc voltage at power measurement */
+       uint8_t         pcdac[2][5];  /* pcdac used for power measurement */
+       uint8_t         empty[2][5];  /* future use */
+} __packed CAL_DATA_PER_FREQ_OP_LOOP;
+
+typedef struct CalCtlData {
+       CAL_CTL_EDGES           ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __packed CAL_CTL_DATA;
+
+typedef struct calDataPerFreq {
+       uint8_t         pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+       uint8_t         vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __packed CAL_DATA_PER_FREQ;
+
+struct ar5416eeprom {
+       BASE_EEP_HEADER         baseEepHeader;         // 64 B
+       uint8_t                 custData[64];          // 64 B
+       MODAL_EEP_HEADER        modalHeader[2];        // 200 B
+       uint8_t                 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
+       uint8_t                 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
+       CAL_DATA_PER_FREQ       calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
+       CAL_DATA_PER_FREQ       calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+       CAL_TARGET_POWER_LEG    calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
+       CAL_TARGET_POWER_HT     calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
+       CAL_TARGET_POWER_HT     calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
+       CAL_TARGET_POWER_LEG    calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
+       CAL_TARGET_POWER_LEG    calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
+       CAL_TARGET_POWER_HT     calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
+       CAL_TARGET_POWER_HT     calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
+       uint8_t                 ctlIndex[AR5416_NUM_CTLS];
+       CAL_CTL_DATA            ctlData[AR5416_NUM_CTLS];
+       uint8_t                 padding;
+} __packed;
+
+typedef struct {
+       struct ar5416eeprom ee_base;
+#define NUM_EDGES       8
+       uint16_t        ee_numCtls;
+       RD_EDGES_POWER  ee_rdEdgesPower[NUM_EDGES*AR5416_NUM_CTLS];
+       /* XXX these are dynamically calculated for use by shared code */
+       int8_t          ee_antennaGainMax[2];
+} HAL_EEPROM_v14;
+#endif /* _AH_EEPROM_V14_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_eeprom_v3.c    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,1876 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_eeprom_v3.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_eeprom_v3.h"
+
+static void
+getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee,
+       uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp)
+{
+       static const uint16_t intercepts3[] =
+               { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
+       static const uint16_t intercepts3_2[] =
+               { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
+       const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ?
+               intercepts3 : intercepts3_2;
+       int i;
+
+       /* loop for the percentages in steps or 5 */
+       for (i = 0; i < NUM_INTERCEPTS; i++ )
+               *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100;
+}
+
+/*
+ * Get channel value from binary representation held in eeprom
+ */
+static uint16_t
+fbin2freq(HAL_EEPROM *ee, uint16_t fbin)
+{
+       if (fbin == CHANNEL_UNUSED)     /* reserved value, don't convert */
+               return fbin;
+       return ee->ee_version <= AR_EEPROM_VER3_2 ?
+               (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) :
+               4800 + 5*fbin;
+}
+
+static uint16_t
+fbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin)
+{
+       if (fbin == CHANNEL_UNUSED)     /* reserved value, don't convert */
+               return fbin;
+       return ee->ee_version <= AR_EEPROM_VER3_2 ?
+               2400 + fbin :
+               2300 + fbin;
+}
+
+/*
+ * Now copy EEPROM frequency pier contents into the allocated space
+ */
+static HAL_BOOL
+readEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+#define        EEREAD(_off) do {                               \
+       if (!ath_hal_eepromRead(ah, _off, &eeval))      \
+               return AH_FALSE;                        \
+} while (0)
+       uint16_t eeval, off;
+       int i;
+
+       if (ee->ee_version >= AR_EEPROM_VER4_0 &&
+           ee->ee_eepMap && !ee->ee_Amode) {
+               /*
+                * V4.0 EEPROMs with map type 1 have frequency pier
+                * data only when 11a mode is supported.
+                */
+               return AH_TRUE;
+       }
+       if (ee->ee_version >= AR_EEPROM_VER3_3) {
+               off = GROUPS_OFFSET3_3 + GROUP1_OFFSET;
+               for (i = 0; i < ee->ee_numChannels11a; i += 2) {
+                       EEREAD(off++);
+                       ee->ee_channels11a[i]   = (eeval >> 8) & FREQ_MASK_3_3;
+                       ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3;
+               }
+       } else {
+               off = GROUPS_OFFSET3_2 + GROUP1_OFFSET;
+
+               EEREAD(off++);
+               ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK;
+               ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK;
+               ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK;
+
+               EEREAD(off++);
+               ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f;
+               ee->ee_channels11a[3]  = (eeval >>  4) & FREQ_MASK;
+               ee->ee_channels11a[4]  = (eeval <<  3) & FREQ_MASK;
+
+               EEREAD(off++);
+               ee->ee_channels11a[4] |= (eeval >> 13) & 0x7;
+               ee->ee_channels11a[5]  = (eeval >>  6) & FREQ_MASK;
+               ee->ee_channels11a[6]  = (eeval <<  1) & FREQ_MASK;
+
+               EEREAD(off++);
+               ee->ee_channels11a[6] |= (eeval >> 15) & 0x1;
+               ee->ee_channels11a[7]  = (eeval >>  8) & FREQ_MASK;
+               ee->ee_channels11a[8]  = (eeval >>  1) & FREQ_MASK;
+               ee->ee_channels11a[9]  = (eeval <<  6) & FREQ_MASK;
+
+               EEREAD(off++);
+               ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f;
+       }
+
+       for (i = 0; i < ee->ee_numChannels11a; i++)
+               ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]);
+
+       return AH_TRUE;
+#undef EEREAD
+}
+
+/*
+ * Rev 4 Eeprom 5112 Power Extract Functions
+ */
+
+/*
+ * Allocate the power information based on the number of channels
+ * recorded by the calibration.  These values are then initialized.
+ */
+static HAL_BOOL
+eepromAllocExpnPower5112(struct ath_hal *ah,
+       const EEPROM_POWER_5112 *pCalDataset,
+       EEPROM_POWER_EXPN_5112 *pPowerExpn)
+{
+       uint16_t numChannels = pCalDataset->numChannels;
+       const uint16_t *pChanList = pCalDataset->pChannels;
+       void *data;
+       int i, j;
+
+       /* Allocate the channel and Power Data arrays together */
+       data = ath_hal_malloc(
+               roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) +
+               sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels);
+       if (data == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s unable to allocate raw data struct (gen3)\n", __func__);
+               return AH_FALSE;
+       }
+       pPowerExpn->pChannels = data;
+       pPowerExpn->pDataPerChannel = (void *)(((char *)data) +
+               roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)));
+
+       pPowerExpn->numChannels = numChannels;
+       for (i = 0; i < numChannels; i++) {
+               pPowerExpn->pChannels[i] =
+                       pPowerExpn->pDataPerChannel[i].channelValue =
+                               pChanList[i];
+               for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) {
+                       pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j;
+                       pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0;
+               }
+               pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4;
+               pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3;
+       }
+       return AH_TRUE;
+}
+
+/*
+ * Expand the dataSet from the calibration information into the
+ * final power structure for 5112
+ */
+static HAL_BOOL
+eepromExpandPower5112(struct ath_hal *ah,
+       const EEPROM_POWER_5112 *pCalDataset,
+       EEPROM_POWER_EXPN_5112 *pPowerExpn)
+{
+       int ii, jj, kk;
+       int16_t maxPower_t4;
+       EXPN_DATA_PER_XPD_5112 *pExpnXPD;
+       /* ptr to array of info held per channel */
+       const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh;
+       uint16_t xgainList[2], xpdMask;
+
+       pPowerExpn->xpdMask = pCalDataset->xpdMask;
+
+       xgainList[0] = 0xDEAD;
+       xgainList[1] = 0xDEAD;
+
+       kk = 0;
+       xpdMask = pPowerExpn->xpdMask;
+       for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) {
+               if (((xpdMask >> jj) & 1) > 0) {
+                       if (kk > 1) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "%s: too many xpdGains in dataset: %u\n",
+                                   __func__, kk);
+                               return AH_FALSE;
+                       }
+                       xgainList[kk++] = jj;
+               }
+       }
+
+       pPowerExpn->numChannels = pCalDataset->numChannels;
+       if (pPowerExpn->numChannels == 0) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__);
+               return AH_FALSE;
+       }
+
+       for (ii = 0; ii < pPowerExpn->numChannels; ii++) {
+               pCalCh = &pCalDataset->pDataPerChannel[ii];
+               pPowerExpn->pDataPerChannel[ii].channelValue =
+                       pCalCh->channelValue;
+               pPowerExpn->pDataPerChannel[ii].maxPower_t4 =
+                       pCalCh->maxPower_t4;
+               maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4;
+
+               for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++)
+                       pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0;
+               if (xgainList[1] == 0xDEAD) {
+                       jj = xgainList[0];
+                       pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
+                       pExpnXPD->numPcdacs = 4;
+                       pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0;
+                       pExpnXPD->pcdac[1] = (uint16_t)
+                               (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0);
+                       pExpnXPD->pcdac[2] = (uint16_t)
+                               (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0);
+                       pExpnXPD->pcdac[3] = (uint16_t)
+                               (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0);
+
+                       pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0;
+                       pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0;
+                       pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0;
+                       pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0;
+
+               } else {
+                       pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0;
+                       pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20;
+                       pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35;
+                       pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63;
+
+                       jj = xgainList[0];
+                       pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
+                       pExpnXPD->numPcdacs = 4;
+                       pExpnXPD->pcdac[1] = (uint16_t)
+                               (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0);
+                       pExpnXPD->pcdac[2] = (uint16_t)
+                               (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0);
+                       pExpnXPD->pcdac[3] = (uint16_t)
+                               (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0);
+                       pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0;
+                       pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0;
+                       pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0;
+                       pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0;
+
+                       jj = xgainList[1];
+                       pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
+                       pExpnXPD->numPcdacs = 3;
+
+                       pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3;
+                       pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3;
+                       pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3;
+               }
+       }
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+readEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+#define        EEREAD(_off) do {                               \
+       if (!ath_hal_eepromRead(ah, _off, &eeval))      \
+               return AH_FALSE;                        \
+} while (0)
+       const uint16_t dbmmask           = 0xff;
+       const uint16_t pcdac_delta_mask = 0x1f;
+       const uint16_t pcdac_mask        = 0x3f;
+       const uint16_t freqmask  = 0xff;
+
+       int i, mode, numPiers;
+       uint32_t off;
+       uint16_t eeval;
+       uint16_t freq[NUM_11A_EEPROM_CHANNELS];
+        EEPROM_POWER_5112 eePower;
+
+       HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0);
+       off = GROUPS_OFFSET3_3;
+       for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
+               numPiers = 0;
+               switch (mode) {
+               case headerInfo11A:
+                       if (!ee->ee_Amode)      /* no 11a calibration data */
+                               continue;
+                       while (numPiers < NUM_11A_EEPROM_CHANNELS) {
+                               EEREAD(off++);
+                               if ((eeval & freqmask) == 0)
+                                       break;
+                               freq[numPiers++] = fbin2freq(ee,
+                                       eeval & freqmask);
+
+                               if (((eeval >> 8) & freqmask) == 0)
+                                       break;
+                               freq[numPiers++] = fbin2freq(ee,
+                                       (eeval>>8) & freqmask);
+                       }
+                       break;
+               case headerInfo11B:
+                       if (!ee->ee_Bmode)      /* no 11b calibration data */
+                               continue;
+                       for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++)
+                               if (ee->ee_calPier11b[i] != CHANNEL_UNUSED)
+                                       freq[numPiers++] = ee->ee_calPier11b[i];
+                       break;
+               case headerInfo11G:
+                       if (!ee->ee_Gmode)      /* no 11g calibration data */
+                               continue;
+                       for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++)
+                               if (ee->ee_calPier11g[i] != CHANNEL_UNUSED)
+                                       freq[numPiers++] = ee->ee_calPier11g[i];
+                       break;
+               default:
+                       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
+                           __func__, mode);
+                       return AH_FALSE;
+               }
+
+               OS_MEMZERO(&eePower, sizeof(eePower));
+               eePower.numChannels = numPiers;
+
+               for (i = 0; i < numPiers; i++) {
+                       eePower.pChannels[i] = freq[i];
+                       eePower.pDataPerChannel[i].channelValue = freq[i];
+
+                       EEREAD(off++);
+                       eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t)
+                               ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
+                       eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t)
+                               (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
+
+                       EEREAD(off++);
+                       eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t)
+                               ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
+                       eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t)
+                               (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
+
+                       EEREAD(off++);
+                       eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t)
+                               (eeval & pcdac_delta_mask);
+                       eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t)
+                               ((eeval >> 5) & pcdac_delta_mask);
+                       eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t)
+                               ((eeval >> 10) & pcdac_delta_mask);
+
+                       EEREAD(off++);
+                       eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t)
+                               ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
+                       eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t)
+                               (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
+
+                       EEREAD(off++);
+                       eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t)
+                               ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
+                       if (ee->ee_version >= AR_EEPROM_VER4_3) {
+                               eePower.pDataPerChannel[i].maxPower_t4 =
+                                       eePower.pDataPerChannel[i].pwr4_xg0;
+                               eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t)
+                                       ((eeval >> 8) & pcdac_mask);
+                       } else {
+                               eePower.pDataPerChannel[i].maxPower_t4 = (int16_t)
+                                       (((eeval >> 8) & dbmmask) -
+                                        ((eeval >> 15) & 0x1)*256);
+                               eePower.pDataPerChannel[i].pcd1_xg0 = 1;
+                       }
+               }
+               eePower.xpdMask = ee->ee_xgain[mode];
+
+               if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: did not allocate power struct\n", __func__);
+                       return AH_FALSE;
+                }
+                if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: did not expand power struct\n", __func__);
+                       return AH_FALSE;
+               }
+       }
+       return AH_TRUE;
+#undef EEREAD
+}
+
+static void
+freeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+       int mode;
+       void *data;
+
+       for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
+               EEPROM_POWER_EXPN_5112 *pPowerExpn =
+                       &ee->ee_modePowerArray5112[mode];
+               data = pPowerExpn->pChannels;
+               if (data != AH_NULL) {
+                       pPowerExpn->pChannels = AH_NULL;
+                       ath_hal_free(data);
+               }
+       }
+}
+
+static void
+ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413,
+       uint16_t myNumRawChannels, uint16_t *pMyRawChanList)
+{
+       uint16_t i, channelValue;
+       uint32_t xpd_mask;
+       uint16_t numPdGainsUsed;
+
+       pEEPROMDataset2413->numChannels = myNumRawChannels;
+
+       xpd_mask = pEEPROMDataset2413->xpd_mask;
+       numPdGainsUsed = 0;
+       if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++;
+       if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++;
+       if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++;
+       if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++;
+
+       for (i = 0; i < myNumRawChannels; i++) {
+               channelValue = pMyRawChanList[i];
+               pEEPROMDataset2413->pChannels[i] = channelValue;
+               pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue;
+               pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed;
+       }
+}
+
+static HAL_BOOL
+ar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee,
+       EEPROM_DATA_STRUCT_2413 *pCalDataset,
+       uint32_t start_offset, uint32_t maxPiers, uint8_t mode)
+{
+#define        EEREAD(_off) do {                               \
+       if (!ath_hal_eepromRead(ah, _off, &eeval))      \
+               return AH_FALSE;                        \
+} while (0)
+       const uint16_t dbm_I_mask = 0x1F;       /* 5-bits. 1dB step. */
+       const uint16_t dbm_delta_mask = 0xF;    /* 4-bits. 0.5dB step. */
+       const uint16_t Vpd_I_mask = 0x7F;       /* 7-bits. 0-128 */
+       const uint16_t Vpd_delta_mask = 0x3F;   /* 6-bits. 0-63 */
+       const uint16_t freqmask = 0xff;
+
+       uint16_t ii, eeval;
+       uint16_t idx, numPiers;
+       uint16_t freq[NUM_11A_EEPROM_CHANNELS];
+
+       idx = start_offset;
+    for (numPiers = 0; numPiers < maxPiers;) {
+        EEREAD(idx++);
+        if ((eeval & freqmask) == 0)
+            break;
+        if (mode == headerInfo11A)
+            freq[numPiers++] = fbin2freq(ee, (eeval & freqmask));
+        else
+            freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask));
+
+        if (((eeval >> 8) & freqmask) == 0)
+            break;
+        if (mode == headerInfo11A)
+            freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask);
+        else
+            freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask);
+    }
+       ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]);
+
+       idx = start_offset + (maxPiers / 2);
+       for (ii = 0; ii < pCalDataset->numChannels; ii++) {
+               EEPROM_DATA_PER_CHANNEL_2413 *currCh =
+                       &(pCalDataset->pDataPerChannel[ii]);
+
+               if (currCh->numPdGains > 0) {
+                       /*
+                        * Read the first NUM_POINTS_OTHER_PDGAINS pwr
+                        * and Vpd values for pdgain_0
+                        */
+                       EEREAD(idx++);
+                       currCh->pwr_I[0] = eeval & dbm_I_mask;
+                       currCh->Vpd_I[0] = (eeval >> 5) & Vpd_I_mask;
+                       currCh->pwr_delta_t2[0][0] =
+                               (eeval >> 12) & dbm_delta_mask;
+
+                       EEREAD(idx++);
+                       currCh->Vpd_delta[0][0] = eeval & Vpd_delta_mask;
+                       currCh->pwr_delta_t2[1][0] =
+                               (eeval >> 6) & dbm_delta_mask;
+                       currCh->Vpd_delta[1][0] =
+                               (eeval >> 10) & Vpd_delta_mask;
+
+                       EEREAD(idx++);
+                       currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask;
+                       currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask;
+               }
+
+               if (currCh->numPdGains > 1) {
+                       /*
+                        * Read the first NUM_POINTS_OTHER_PDGAINS pwr
+                        * and Vpd values for pdgain_1
+                        */
+                       currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask;
+                       currCh->Vpd_I[1] = (eeval >> 15) & 0x1;
+
+                       EEREAD(idx++);
+                       /* upper 6 bits */
+                       currCh->Vpd_I[1] |= (eeval & 0x3F) << 1;
+                       currCh->pwr_delta_t2[0][1] =
+                               (eeval >> 6) & dbm_delta_mask;
+                       currCh->Vpd_delta[0][1] =
+                               (eeval >> 10) & Vpd_delta_mask;
+
+                       EEREAD(idx++);
+                       currCh->pwr_delta_t2[1][1] = eeval & dbm_delta_mask;
+                       currCh->Vpd_delta[1][1] = (eeval >> 4) & Vpd_delta_mask;
+                       currCh->pwr_delta_t2[2][1] =
+                               (eeval >> 10) & dbm_delta_mask;
+                       currCh->Vpd_delta[2][1] = (eeval >> 14) & 0x3;
+
+                       EEREAD(idx++);
+                       /* upper 4 bits */
+                       currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2;
+               } else if (currCh->numPdGains == 1) {
+                       /*
+                        * Read the last pwr and Vpd values for pdgain_0
+                        */
+                       currCh->pwr_delta_t2[3][0] =
+                               (eeval >> 10) & dbm_delta_mask;
+                       currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3;
+
+                       EEREAD(idx++);
+                       /* upper 4 bits */
+                       currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2;
+
+                       /* 4 words if numPdGains == 1 */
+               }
+
+               if (currCh->numPdGains > 2) {
+                       /*
+                        * Read the first NUM_POINTS_OTHER_PDGAINS pwr
+                        * and Vpd values for pdgain_2
+                        */
+                       currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask;
+                       currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask;
+
+                       EEREAD(idx++);
+                       currCh->pwr_delta_t2[0][2] =
+                               (eeval >> 0) & dbm_delta_mask;
+                       currCh->Vpd_delta[0][2] = (eeval >> 4) & Vpd_delta_mask;
+                       currCh->pwr_delta_t2[1][2] =
+                               (eeval >> 10) & dbm_delta_mask;
+                       currCh->Vpd_delta[1][2] = (eeval >> 14) & 0x3;
+
+                       EEREAD(idx++);
+                       /* upper 4 bits */
+                       currCh->Vpd_delta[1][2] |= (eeval & 0xF) << 2;
+                       currCh->pwr_delta_t2[2][2] =
+                               (eeval >> 4) & dbm_delta_mask;
+                       currCh->Vpd_delta[2][2] = (eeval >> 8) & Vpd_delta_mask;
+               } else if (currCh->numPdGains == 2) {
+                       /*
+                        * Read the last pwr and Vpd values for pdgain_1
+                        */
+                       currCh->pwr_delta_t2[3][1] =
+                               (eeval >> 4) & dbm_delta_mask;
+                       currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask;
+
+                       /* 6 words if numPdGains == 2 */
+               }
+
+               if (currCh->numPdGains > 3) {
+                       /*
+                        * Read the first NUM_POINTS_OTHER_PDGAINS pwr
+                        * and Vpd values for pdgain_3
+                        */
+                       currCh->pwr_I[3] = (eeval >> 14) & 0x3;
+
+                       EEREAD(idx++);
+                       /* upper 3 bits */
+                       currCh->pwr_I[3] |= ((eeval >> 0) & 0x7) << 2;
+                       currCh->Vpd_I[3] = (eeval >> 3) & Vpd_I_mask;
+                       currCh->pwr_delta_t2[0][3] =
+                               (eeval >> 10) & dbm_delta_mask;
+                       currCh->Vpd_delta[0][3] = (eeval >> 14) & 0x3;
+
+                       EEREAD(idx++);
+                       /* upper 4 bits */
+                       currCh->Vpd_delta[0][3] |= (eeval & 0xF) << 2;
+                       currCh->pwr_delta_t2[1][3] =
+                               (eeval >> 4) & dbm_delta_mask;
+                       currCh->Vpd_delta[1][3] = (eeval >> 8) & Vpd_delta_mask;
+                       currCh->pwr_delta_t2[2][3] = (eeval >> 14) & 0x3;
+
+                       EEREAD(idx++);
+                       /* upper 2 bits */
+                       currCh->pwr_delta_t2[2][3] |= ((eeval >> 0) & 0x3) << 2;
+                       currCh->Vpd_delta[2][3] = (eeval >> 2) & Vpd_delta_mask;
+                       currCh->pwr_delta_t2[3][3] =
+                               (eeval >> 8) & dbm_delta_mask;
+                       currCh->Vpd_delta[3][3] = (eeval >> 12) & 0xF;
+
+                       EEREAD(idx++);
+                       /* upper 2 bits */
+                       currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4;
+
+                       /* 12 words if numPdGains == 4 */
+               } else if (currCh->numPdGains == 3) {
+                       /* read the last pwr and Vpd values for pdgain_2 */
+                       currCh->pwr_delta_t2[3][2] = (eeval >> 14) & 0x3;
+
+                       EEREAD(idx++);
+                       /* upper 2 bits */
+                       currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2;
+                       currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask;
+
+                       /* 9 words if numPdGains == 3 */
+               }
+       }
+       return AH_TRUE;
+#undef EEREAD
+}
+
+static void
+ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal)
+{
+       uint16_t i, j, kk, channelValue;
+       uint16_t xpd_mask;
+       uint16_t numPdGainsUsed;
+
+       pRaw->numChannels = pCal->numChannels;
+
+       xpd_mask = pRaw->xpd_mask;
+       numPdGainsUsed = 0;
+       if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++;
+       if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++;
+       if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++;
+       if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++;
+
+       for (i = 0; i < pCal->numChannels; i++) {
+               channelValue = pCal->pChannels[i];
+
+               pRaw->pChannels[i] = channelValue;
+
+               pRaw->pDataPerChannel[i].channelValue = channelValue;
+               pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed;
+
+               kk = 0;
+               for (j = 0; j < MAX_NUM_PDGAINS_PER_CHANNEL; j++) {
+                       pRaw->pDataPerChannel[i].pDataPerPDGain[j].pd_gain = j;
+                       if ((xpd_mask >> j) & 0x1) {
+                               pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_OTHER_PDGAINS;
+                               kk++;
+                               if (kk == 1) {
+                                       /*
+                                        * lowest pd_gain corresponds
+                                        *  to highest power and thus,
+                                        *  has one more point
+                                        */
+                                       pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN;
+                               }
+                       } else {
+                               pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0;
+                       }
+               }
+       }
+}
+
+static HAL_BOOL
+ar2413EepromToRawDataset(struct ath_hal *ah,
+       EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw)
+{
+       uint16_t ii, jj, kk, ss;
+       RAW_DATA_PER_PDGAIN_2413 *pRawXPD;
+       /* ptr to array of info held per channel */
+       EEPROM_DATA_PER_CHANNEL_2413 *pCalCh;
+       uint16_t xgain_list[MAX_NUM_PDGAINS_PER_CHANNEL];
+       uint16_t xpd_mask;
+       uint32_t numPdGainsUsed;
+
+       HALASSERT(pRaw->xpd_mask == pCal->xpd_mask);
+
+       xgain_list[0] = 0xDEAD;
+       xgain_list[1] = 0xDEAD;
+       xgain_list[2] = 0xDEAD;
+       xgain_list[3] = 0xDEAD;
+
+       numPdGainsUsed = 0;
+       xpd_mask = pRaw->xpd_mask;
+       for (jj = 0; jj < MAX_NUM_PDGAINS_PER_CHANNEL; jj++) {
+               if ((xpd_mask >> (MAX_NUM_PDGAINS_PER_CHANNEL-jj-1)) & 1)
+                       xgain_list[numPdGainsUsed++] = MAX_NUM_PDGAINS_PER_CHANNEL-jj-1;
+       }
+
+       pRaw->numChannels = pCal->numChannels;
+       for (ii = 0; ii < pRaw->numChannels; ii++) {
+               pCalCh = &(pCal->pDataPerChannel[ii]);
+               pRaw->pDataPerChannel[ii].channelValue = pCalCh->channelValue;
+
+               /* numVpd has already been setup appropriately for the relevant pdGains */
+               for (jj = 0; jj < numPdGainsUsed; jj++) {
+                       /* use jj for calDataset and ss for rawDataset */
+                       ss = xgain_list[jj];
+                       pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]);
+                       HALASSERT(pRawXPD->numVpd >= 1);
+
+                       pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]);
+                       pRawXPD->Vpd[0]    = pCalCh->Vpd_I[jj];
+
+                       for (kk = 1; kk < pRawXPD->numVpd; kk++) {
+                               pRawXPD->pwr_t4[kk] = (int16_t)(pRawXPD->pwr_t4[kk-1] + 2*pCalCh->pwr_delta_t2[kk-1][jj]);
+                               pRawXPD->Vpd[kk] = (uint16_t)(pRawXPD->Vpd[kk-1] + pCalCh->Vpd_delta[kk-1][jj]);
+                       }
+                       /* loop over Vpds */
+               }
+               /* loop over pd_gains */
+       }
+       /* loop over channels */
+       return AH_TRUE;
+}
+
+static HAL_BOOL
+readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+       /* NB: index is 1 less than numPdgains */
+       static const uint16_t wordsForPdgains[] = { 4, 6, 9, 12 };
+       EEPROM_DATA_STRUCT_2413 *pCal = AH_NULL;
+       RAW_DATA_STRUCT_2413 *pRaw;
+       int numEEPROMWordsPerChannel;
+       uint32_t off;
+       HAL_BOOL ret = AH_FALSE;
+
+       HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0);
+       HALASSERT(ee->ee_eepMap == 2);
+
+       pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413));
+       if (pCal == AH_NULL)
+               goto exit;
+
+       off = ee->ee_eepMap2PowerCalStart;
+       if (ee->ee_Amode) {
+               OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
+               pCal->xpd_mask = ee->ee_xgain[headerInfo11A];
+               if (!ar2413ReadCalDataset(ah, ee, pCal, off,
+                       NUM_11A_EEPROM_CHANNELS_2413, headerInfo11A)) {
+                       goto exit;
+               }
+               pRaw = &ee->ee_rawDataset2413[headerInfo11A];
+               pRaw->xpd_mask = ee->ee_xgain[headerInfo11A];
+               ar2413SetupRawDataset(pRaw, pCal);
+               if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
+                       goto exit;
+               }
+               /* setup offsets for mode_11a next */
+               numEEPROMWordsPerChannel = wordsForPdgains[
+                       pCal->pDataPerChannel[0].numPdGains - 1];
+               off += pCal->numChannels * numEEPROMWordsPerChannel + 5;
+       }
+       if (ee->ee_Bmode) {
+               OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
+               pCal->xpd_mask = ee->ee_xgain[headerInfo11B];
+               if (!ar2413ReadCalDataset(ah, ee, pCal, off,
+                       NUM_2_4_EEPROM_CHANNELS_2413 , headerInfo11B)) {
+                       goto exit;
+               }
+               pRaw = &ee->ee_rawDataset2413[headerInfo11B];
+               pRaw->xpd_mask = ee->ee_xgain[headerInfo11B];
+               ar2413SetupRawDataset(pRaw, pCal);
+               if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
+                       goto exit;
+               }
+               /* setup offsets for mode_11g next */
+               numEEPROMWordsPerChannel = wordsForPdgains[
+                       pCal->pDataPerChannel[0].numPdGains - 1];
+               off += pCal->numChannels * numEEPROMWordsPerChannel + 2;
+       }
+       if (ee->ee_Gmode) {
+               OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
+               pCal->xpd_mask = ee->ee_xgain[headerInfo11G];
+               if (!ar2413ReadCalDataset(ah, ee, pCal, off,
+                       NUM_2_4_EEPROM_CHANNELS_2413, headerInfo11G)) {
+                       goto exit;
+               }
+               pRaw = &ee->ee_rawDataset2413[headerInfo11G];
+               pRaw->xpd_mask = ee->ee_xgain[headerInfo11G];
+               ar2413SetupRawDataset(pRaw, pCal);
+               if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
+                       goto exit;
+               }
+       }
+       ret = AH_TRUE;
+ exit:
+       if (pCal != AH_NULL)
+               ath_hal_free(pCal);
+       return ret;
+}
+
+/*
+ * Now copy EEPROM Raw Power Calibration per frequency contents
+ * into the allocated space
+ */
+static HAL_BOOL
+readEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+#define        EEREAD(_off) do {                               \
+       if (!ath_hal_eepromRead(ah, _off, &eeval))      \
+               return AH_FALSE;                        \
+} while (0)
+       uint16_t eeval, nchan;
+       uint32_t off;
+       int i, j, mode;
+
+        if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
+               return readEepromRawPowerCalInfo5112(ah, ee);
+       if (ee->ee_version >= AR_EEPROM_VER5_0 && ee->ee_eepMap == 2)
+               return readEepromRawPowerCalInfo2413(ah, ee);
+
+       /*
+        * Group 2:  read raw power data for all frequency piers
+        *
+        * NOTE: Group 2 contains the raw power calibration
+        *       information for each of the channels that
+        *       we recorded above.
+        */
+       for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
+               uint16_t *pChannels = AH_NULL;
+               DATA_PER_CHANNEL *pChannelData = AH_NULL;
+
+               off = ee->ee_version >= AR_EEPROM_VER3_3 ?
+                       GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
+               switch (mode) {
+               case headerInfo11A:
+                       off             += GROUP2_OFFSET;
+                       nchan           = ee->ee_numChannels11a;
+                       pChannelData    = ee->ee_dataPerChannel11a;
+                       pChannels       = ee->ee_channels11a;
+                       break;
+               case headerInfo11B:
+                       if (!ee->ee_Bmode)
+                               continue;
+                       off             += GROUP3_OFFSET;
+                       nchan           = ee->ee_numChannels2_4;
+                       pChannelData    = ee->ee_dataPerChannel11b;
+                       pChannels       = ee->ee_channels11b;
+                       break;
+               case headerInfo11G:
+                       if (!ee->ee_Gmode)
+                               continue;
+                       off             += GROUP4_OFFSET;
+                       nchan           = ee->ee_numChannels2_4;
+                       pChannelData    = ee->ee_dataPerChannel11g;
+                       pChannels       = ee->ee_channels11g;
+                       break;
+               default:
+                       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
+                           __func__, mode);
+                       return AH_FALSE;
+               }
+               for (i = 0; i < nchan; i++) {
+                       pChannelData->channelValue = pChannels[i];
+
+                       EEREAD(off++);
+                       pChannelData->pcdacMax     = (uint16_t)((eeval >> 10) & PCDAC_MASK);
+                       pChannelData->pcdacMin     = (uint16_t)((eeval >> 4) & PCDAC_MASK);
+                       pChannelData->PwrValues[0] = (uint16_t)((eeval << 2) & POWER_MASK);
+
+                       EEREAD(off++);
+                       pChannelData->PwrValues[0] |= (uint16_t)((eeval >> 14) & 0x3);
+                       pChannelData->PwrValues[1] = (uint16_t)((eeval >> 8) & POWER_MASK);
+                       pChannelData->PwrValues[2] = (uint16_t)((eeval >> 2) & POWER_MASK);
+                       pChannelData->PwrValues[3] = (uint16_t)((eeval << 4) & POWER_MASK);
+
+                       EEREAD(off++);
+                       pChannelData->PwrValues[3] |= (uint16_t)((eeval >> 12) & 0xf);
+                       pChannelData->PwrValues[4] = (uint16_t)((eeval >> 6) & POWER_MASK);
+                       pChannelData->PwrValues[5] = (uint16_t)(eeval  & POWER_MASK);
+
+                       EEREAD(off++);
+                       pChannelData->PwrValues[6] = (uint16_t)((eeval >> 10) & POWER_MASK);
+                       pChannelData->PwrValues[7] = (uint16_t)((eeval >> 4) & POWER_MASK);
+                       pChannelData->PwrValues[8] = (uint16_t)((eeval << 2) & POWER_MASK);
+
+                       EEREAD(off++);
+                       pChannelData->PwrValues[8] |= (uint16_t)((eeval >> 14) & 0x3);
+                       pChannelData->PwrValues[9] = (uint16_t)((eeval >> 8) & POWER_MASK);
+                       pChannelData->PwrValues[10] = (uint16_t)((eeval >> 2) & POWER_MASK);
+
+                       getPcdacInterceptsFromPcdacMinMax(ee,
+                               pChannelData->pcdacMin, pChannelData->pcdacMax,
+                               pChannelData->PcdacValues) ;
+
+                       for (j = 0; j < pChannelData->numPcdacValues; j++) {
+                               pChannelData->PwrValues[j] = (uint16_t)(
+                                       PWR_STEP * pChannelData->PwrValues[j]);
+                               /* Note these values are scaled up. */
+                       }
+                       pChannelData++;
+               }
+       }
+       return AH_TRUE;
+#undef EEREAD
+}
+
+/*
+ * Copy EEPROM Target Power Calbration per rate contents
+ * into the allocated space
+ */
+static HAL_BOOL
+readEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+#define        EEREAD(_off) do {                               \
+       if (!ath_hal_eepromRead(ah, _off, &eeval))      \
+               return AH_FALSE;                        \
+} while (0)
+       uint16_t eeval, enable24;
+       uint32_t off;
+       int i, mode, nchan;
+
+       enable24 = ee->ee_Bmode || ee->ee_Gmode;
+       for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
+               TRGT_POWER_INFO *pPowerInfo;
+               uint16_t *pNumTrgtChannels;
+
+               off = ee->ee_version >= AR_EEPROM_VER4_0 ?
+                               ee->ee_targetPowersStart - GROUP5_OFFSET :
+                     ee->ee_version >= AR_EEPROM_VER3_3 ?
+                               GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
+               switch (mode) {
+               case headerInfo11A:
+                       off += GROUP5_OFFSET;
+                       nchan = NUM_TEST_FREQUENCIES;
+                       pPowerInfo = ee->ee_trgtPwr_11a;
+                       pNumTrgtChannels = &ee->ee_numTargetPwr_11a;
+                       break;
+               case headerInfo11B:
+                       if (!enable24)
+                               continue;
+                       off += GROUP6_OFFSET;
+                       nchan = 2;
+                       pPowerInfo = ee->ee_trgtPwr_11b;
+                       pNumTrgtChannels = &ee->ee_numTargetPwr_11b;
+                       break;
+               case headerInfo11G:
+                       if (!enable24)
+                               continue;
+                       off += GROUP7_OFFSET;
+                       nchan = 3;
+                       pPowerInfo = ee->ee_trgtPwr_11g;
+                       pNumTrgtChannels = &ee->ee_numTargetPwr_11g;
+                       break;
+               default:
+                       HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
+                           __func__, mode);
+                       return AH_FALSE;
+               }
+               *pNumTrgtChannels = 0;
+               for (i = 0; i < nchan; i++) {
+                       EEREAD(off++);
+                       if (ee->ee_version >= AR_EEPROM_VER3_3) {
+                               pPowerInfo->testChannel = (eeval >> 8) & 0xff;
+                       } else {
+                               pPowerInfo->testChannel = (eeval >> 9) & 0x7f;
+                       }
+
+                       if (pPowerInfo->testChannel != 0) {
+                               /* get the channel value and read rest of info */
+                               if (mode == headerInfo11A) {
+                                       pPowerInfo->testChannel = fbin2freq(ee, pPowerInfo->testChannel);
+                               } else {
+                                       pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel);
+                               }
+
+                               if (ee->ee_version >= AR_EEPROM_VER3_3) {
+                                       pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK;
+                                       pPowerInfo->twicePwr36   = (eeval << 4) & POWER_MASK;
+                               } else {
+                                       pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK;
+                                       pPowerInfo->twicePwr36   = (eeval << 3) & POWER_MASK;
+                               }
+
+                               EEREAD(off++);
+                               if (ee->ee_version >= AR_EEPROM_VER3_3) {
+                                       pPowerInfo->twicePwr36 |= (eeval >> 12) & 0xf;
+                                       pPowerInfo->twicePwr48 = (eeval >> 6) & POWER_MASK;
+                                       pPowerInfo->twicePwr54 =  eeval & POWER_MASK;
+                               } else {
+                                       pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7;
+                                       pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK;
+                                       pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK;
+                               }
+                               (*pNumTrgtChannels)++;
+                       }
+                       pPowerInfo++;
+               }
+       }
+       return AH_TRUE;
+#undef EEREAD
+}
+
+/*
+ * Now copy EEPROM Coformance Testing Limits contents
+ * into the allocated space
+ */
+static HAL_BOOL
+readEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+#define        EEREAD(_off) do {                               \
+       if (!ath_hal_eepromRead(ah, _off, &eeval))      \
+               return AH_FALSE;                        \
+} while (0)
+       RD_EDGES_POWER *rep;
+       uint16_t eeval;
+       uint32_t off;
+       int i, j;
+
+       rep = ee->ee_rdEdgesPower;
+
+       off = GROUP8_OFFSET +
+               (ee->ee_version >= AR_EEPROM_VER4_0 ?
+                       ee->ee_targetPowersStart - GROUP5_OFFSET :
+                ee->ee_version >= AR_EEPROM_VER3_3 ?
+                       GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2);
+       for (i = 0; i < ee->ee_numCtls; i++) {
+               if (ee->ee_ctl[i] == 0) {
+                       /* Move offset and edges */
+                       off += (ee->ee_version >= AR_EEPROM_VER3_3 ? 8 : 7);
+                       rep += NUM_EDGES;
+                       continue;
+               }
+               if (ee->ee_version >= AR_EEPROM_VER3_3) {
+                       for (j = 0; j < NUM_EDGES; j += 2) {
+                               EEREAD(off++);
+                               rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3;
+                               rep[j+1].rdEdge = eeval & FREQ_MASK_3_3;
+                       }
+                       for (j = 0; j < NUM_EDGES; j += 2) {
+                               EEREAD(off++);
+                               rep[j].twice_rdEdgePower =
+                                       (eeval >> 8) & POWER_MASK;
+                               rep[j].flag = (eeval >> 14) & 1;
+                               rep[j+1].twice_rdEdgePower = eeval & POWER_MASK;
+                               rep[j+1].flag = (eeval >> 6) & 1;
+                       }
+               } else {
+                       EEREAD(off++);
+                       rep[0].rdEdge = (eeval >> 9) & FREQ_MASK;
+                       rep[1].rdEdge = (eeval >> 2) & FREQ_MASK;
+                       rep[2].rdEdge = (eeval << 5) & FREQ_MASK;
+
+                       EEREAD(off++);
+                       rep[2].rdEdge |= (eeval >> 11) & 0x1f;
+                       rep[3].rdEdge = (eeval >> 4) & FREQ_MASK;
+                       rep[4].rdEdge = (eeval << 3) & FREQ_MASK;
+
+                       EEREAD(off++);
+                       rep[4].rdEdge |= (eeval >> 13) & 0x7;
+                       rep[5].rdEdge = (eeval >> 6) & FREQ_MASK;
+                       rep[6].rdEdge = (eeval << 1) & FREQ_MASK;
+
+                       EEREAD(off++);
+                       rep[6].rdEdge |= (eeval >> 15) & 0x1;
+                       rep[7].rdEdge = (eeval >> 8) & FREQ_MASK;
+
+                       rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK;
+                       rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK;
+
+                       EEREAD(off++);
+                       rep[1].twice_rdEdgePower |= (eeval >> 12) & 0xf;
+                       rep[2].twice_rdEdgePower = (eeval >> 6) & POWER_MASK;
+                       rep[3].twice_rdEdgePower = eeval & POWER_MASK;
+
+                       EEREAD(off++);
+                       rep[4].twice_rdEdgePower = (eeval >> 10) & POWER_MASK;
+                       rep[5].twice_rdEdgePower = (eeval >> 4) & POWER_MASK;
+                       rep[6].twice_rdEdgePower = (eeval << 2) & POWER_MASK;
+
+                       EEREAD(off++);
+                       rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3;
+                       rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK;
+               }
+
+               for (j = 0; j < NUM_EDGES; j++ ) {
+                       if (rep[j].rdEdge != 0 || rep[j].twice_rdEdgePower != 0) {
+                               if ((ee->ee_ctl[i] & CTL_MODE_M) == CTL_11A ||
+                                   (ee->ee_ctl[i] & CTL_MODE_M) == CTL_TURBO) {
+                                       rep[j].rdEdge = fbin2freq(ee, rep[j].rdEdge);
+                               } else {
+                                       rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge);
+                               }
+                       }
+               }
+               rep += NUM_EDGES;
+       }
+       return AH_TRUE;
+#undef EEREAD
+}
+
+/*
+ * Read the individual header fields for a Rev 3 EEPROM
+ */
+static HAL_BOOL
+readHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+#define        EEREAD(_off) do {                               \
+       if (!ath_hal_eepromRead(ah, _off, &eeval))      \
+               return AH_FALSE;                        \
+} while (0)
+       static const uint32_t headerOffset3_0[] = {
+               0x00C2, /* 0 - Mode bits, device type, max turbo power */
+               0x00C4, /* 1 - 2.4 and 5 antenna gain */
+               0x00C5, /* 2 - Begin 11A modal section */
+               0x00D0, /* 3 - Begin 11B modal section */
+               0x00DA, /* 4 - Begin 11G modal section */
+               0x00E4  /* 5 - Begin CTL section */
+       };
+       static const uint32_t headerOffset3_3[] = {
+               0x00C2, /* 0 - Mode bits, device type, max turbo power */
+               0x00C3, /* 1 - 2.4 and 5 antenna gain */
+               0x00D4, /* 2 - Begin 11A modal section */
+               0x00F2, /* 3 - Begin 11B modal section */
+               0x010D, /* 4 - Begin 11G modal section */
+               0x0128  /* 5 - Begin CTL section */
+       };
+
+       static const uint32_t regCapOffsetPre4_0 = 0x00CF;
+       static const uint32_t regCapOffsetPost4_0 = 0x00CA;
+
+       const uint32_t *header;
+       uint32_t off;
+       uint16_t eeval;
+       int i;
+
+       /* initialize cckOfdmGainDelta for < 4.2 eeprom */
+       ee->ee_cckOfdmGainDelta = CCK_OFDM_GAIN_DELTA;
+       ee->ee_scaledCh14FilterCckDelta = TENX_CH14_FILTER_CCK_DELTA_INIT;
+
+       if (ee->ee_version >= AR_EEPROM_VER3_3) {
+               header = headerOffset3_3;
+               ee->ee_numCtls = NUM_CTLS_3_3;
+       } else {
+               header = headerOffset3_0;
+               ee->ee_numCtls = NUM_CTLS;
+       }
+       HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX);
+
+       EEREAD(header[0]);
+       ee->ee_turbo5Disable    = (eeval >> 15) & 0x01;
+       ee->ee_rfKill           = (eeval >> 14) & 0x01;
+       ee->ee_deviceType       = (eeval >> 11) & 0x07;
+       ee->ee_turbo2WMaxPower5 = (eeval >> 4) & 0x7F;
+       if (ee->ee_version >= AR_EEPROM_VER4_0)
+               ee->ee_turbo2Disable    = (eeval >> 3) & 0x01;
+       else
+               ee->ee_turbo2Disable    = 1;
+       ee->ee_Gmode            = (eeval >> 2) & 0x01;
+       ee->ee_Bmode            = (eeval >> 1) & 0x01;
+       ee->ee_Amode            = (eeval & 0x01);
+
+       off = header[1];
+       EEREAD(off++);
+       ee->ee_antennaGainMax[0] = (int8_t)((eeval >> 8) & 0xFF);
+       ee->ee_antennaGainMax[1] = (int8_t)(eeval & 0xFF);
+       if (ee->ee_version >= AR_EEPROM_VER4_0) {
+               EEREAD(off++);
+               ee->ee_eepMap            = (eeval>>14) & 0x3;
+               ee->ee_disableXr5        = (eeval>>13) & 0x1;
+               ee->ee_disableXr2        = (eeval>>12) & 0x1;
+               ee->ee_earStart          = eeval & 0xfff;
+
+               EEREAD(off++);
+               ee->ee_targetPowersStart = eeval & 0xfff;
+               ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1;
+
+               if (ee->ee_version >= AR_EEPROM_VER5_0) {
+                       off += 2;
+                       EEREAD(off);
+                       ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff;
+                       /* Properly cal'ed 5.0 devices should be non-zero */
+               }
+       }
+
+       /* Read the moded sections of the EEPROM header in the order A, B, G */
+       for (i = headerInfo11A; i <= headerInfo11G; i++) {
+               /* Set the offset via the index */
+               off = header[2 + i];
+
+               EEREAD(off++);
+               ee->ee_switchSettling[i] = (eeval >> 8) & 0x7f;
+               ee->ee_txrxAtten[i] = (eeval >> 2) & 0x3f;
+               ee->ee_antennaControl[0][i] = (eeval << 4) & 0x3f;
+
+               EEREAD(off++);
+               ee->ee_antennaControl[0][i] |= (eeval >> 12) & 0x0f;
+               ee->ee_antennaControl[1][i] = (eeval >> 6) & 0x3f;
+               ee->ee_antennaControl[2][i] = eeval & 0x3f;
+
+               EEREAD(off++);
+               ee->ee_antennaControl[3][i] = (eeval >> 10)  & 0x3f;
+               ee->ee_antennaControl[4][i] = (eeval >> 4)  & 0x3f;
+               ee->ee_antennaControl[5][i] = (eeval << 2)  & 0x3f;
+
+               EEREAD(off++);
+               ee->ee_antennaControl[5][i] |= (eeval >> 14)  & 0x03;
+               ee->ee_antennaControl[6][i] = (eeval >> 8)  & 0x3f;
+               ee->ee_antennaControl[7][i] = (eeval >> 2)  & 0x3f;
+               ee->ee_antennaControl[8][i] = (eeval << 4)  & 0x3f;
+
+               EEREAD(off++);
+               ee->ee_antennaControl[8][i] |= (eeval >> 12)  & 0x0f;
+               ee->ee_antennaControl[9][i] = (eeval >> 6)  & 0x3f;
+               ee->ee_antennaControl[10][i] = eeval & 0x3f;
+
+               EEREAD(off++);
+               ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8)  & 0xff);
+               switch (i) {
+               case headerInfo11A:
+                       ee->ee_ob4 = (eeval >> 5)  & 0x07;
+                       ee->ee_db4 = (eeval >> 2)  & 0x07;
+                       ee->ee_ob3 = (eeval << 1)  & 0x07;
+                       break;
+               case headerInfo11B:
+                       ee->ee_obFor24 = (eeval >> 4)  & 0x07;
+                       ee->ee_dbFor24 = eeval & 0x07;
+                       break;
+               case headerInfo11G:
+                       ee->ee_obFor24g = (eeval >> 4)  & 0x07;
+                       ee->ee_dbFor24g = eeval & 0x07;
+                       break;
+               }
+
+               if (i == headerInfo11A) {
+                       EEREAD(off++);
+                       ee->ee_ob3 |= (eeval >> 15)  & 0x01;
+                       ee->ee_db3 = (eeval >> 12)  & 0x07;
+                       ee->ee_ob2 = (eeval >> 9)  & 0x07;
+                       ee->ee_db2 = (eeval >> 6)  & 0x07;
+                       ee->ee_ob1 = (eeval >> 3)  & 0x07;
+                       ee->ee_db1 = eeval & 0x07;
+               }
+
+               EEREAD(off++);
+               ee->ee_txEndToXLNAOn[i] = (eeval >> 8)  & 0xff;
+               ee->ee_thresh62[i] = eeval & 0xff;
+
+               EEREAD(off++);
+               ee->ee_txEndToXPAOff[i] = (eeval >> 8)  & 0xff;
+               ee->ee_txFrameToXPAOn[i] = eeval  & 0xff;
+
+               EEREAD(off++);
+               ee->ee_pgaDesiredSize[i] = (int8_t)((eeval >> 8)  & 0xff);
+               ee->ee_noiseFloorThresh[i] = eeval  & 0xff;
+               if (ee->ee_noiseFloorThresh[i] & 0x80) {
+                       ee->ee_noiseFloorThresh[i] = 0 -
+                               ((ee->ee_noiseFloorThresh[i] ^ 0xff) + 1);
+               }
+
+               EEREAD(off++);
+               ee->ee_xlnaGain[i] = (eeval >> 5)  & 0xff;
+               ee->ee_xgain[i] = (eeval >> 1)  & 0x0f;
+               ee->ee_xpd[i] = eeval  & 0x01;
+               if (ee->ee_version >= AR_EEPROM_VER4_0) {
+                       switch (i) {
+                       case headerInfo11A:
+                               ee->ee_fixedBias5 = (eeval >> 13) & 0x1;
+                               break;
+                       case headerInfo11G:
+                               ee->ee_fixedBias2 = (eeval >> 13) & 0x1;
+                               break;
+                       }
+               }
+
+               if (ee->ee_version >= AR_EEPROM_VER3_3) {
+                       EEREAD(off++);
+                       ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F;
+                       switch (i) {
+                       case headerInfo11B:
+                               ee->ee_ob2GHz[0] = eeval & 0x7;
+                               ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
+                               break;
+                       case headerInfo11G:
+                               ee->ee_ob2GHz[1] = eeval & 0x7;
+                               ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
+                               break;
+                       case headerInfo11A:
+                               ee->ee_xrTargetPower5 = eeval & 0x3f;
+                               break;
+                       }
+               }
+               if (ee->ee_version >= AR_EEPROM_VER3_4) {
+                       ee->ee_gainI[i] = (eeval >> 13) & 0x07;
+
+                       EEREAD(off++);
+                       ee->ee_gainI[i] |= (eeval << 3) & 0x38;
+                       if (i == headerInfo11G) {
+                               ee->ee_cckOfdmPwrDelta = (eeval >> 3) & 0xFF;
+                               if (ee->ee_version >= AR_EEPROM_VER4_6)
+                                       ee->ee_scaledCh14FilterCckDelta =
+                                               (eeval >> 11) & 0x1f;
+                       }
+                       if (i == headerInfo11A &&
+                           ee->ee_version >= AR_EEPROM_VER4_0) {
+                               ee->ee_iqCalI[0] = (eeval >> 8 ) & 0x3f;
+                               ee->ee_iqCalQ[0] = (eeval >> 3 ) & 0x1f;
+                       }
+               } else {
+                       ee->ee_gainI[i] = 10;
+                       ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT;
+               }
+               if (ee->ee_version >= AR_EEPROM_VER4_0) {
+                       switch (i) {
+                       case headerInfo11B:
+                               EEREAD(off++);
+                               ee->ee_calPier11b[0] =
+                                       fbin2freq_2p4(ee, eeval&0xff);
+                               ee->ee_calPier11b[1] =
+                                       fbin2freq_2p4(ee, (eeval >> 8)&0xff);
+                               EEREAD(off++);
+                               ee->ee_calPier11b[2] =
+                                       fbin2freq_2p4(ee, eeval&0xff);
+                               if (ee->ee_version >= AR_EEPROM_VER4_1)
+                                       ee->ee_rxtxMargin[headerInfo11B] =
+                                               (eeval >> 8) & 0x3f;
+                               break;
+                       case headerInfo11G:
+                               EEREAD(off++);
+                               ee->ee_calPier11g[0] =
+                                       fbin2freq_2p4(ee, eeval & 0xff);
+                               ee->ee_calPier11g[1] =
+                                       fbin2freq_2p4(ee, (eeval >> 8) & 0xff);
+
+                               EEREAD(off++);
+                               ee->ee_turbo2WMaxPower2 = eeval & 0x7F;
+                               ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f;
+
+                               EEREAD(off++);
+                               ee->ee_calPier11g[2] =
+                                       fbin2freq_2p4(ee, eeval & 0xff);
+                               if (ee->ee_version >= AR_EEPROM_VER4_1)
+                                        ee->ee_rxtxMargin[headerInfo11G] =
+                                               (eeval >> 8) & 0x3f;
+
+                               EEREAD(off++);
+                               ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F;
+                               ee->ee_iqCalQ[1] = eeval & 0x1F;
+
+                               if (ee->ee_version >= AR_EEPROM_VER4_2) {
+                                       EEREAD(off++);
+                                       ee->ee_cckOfdmGainDelta =
+                                               (uint8_t)(eeval & 0xFF);
+                                       if (ee->ee_version >= AR_EEPROM_VER5_0) {
+                                               ee->ee_switchSettlingTurbo[1] =
+                                                       (eeval >> 8) & 0x7f;
+                                               ee->ee_txrxAttenTurbo[1] =
+                                                       (eeval >> 15) & 0x1;
+                                               EEREAD(off++);
+                                               ee->ee_txrxAttenTurbo[1] |=
+                                                       (eeval & 0x1F) << 1;
+                                               ee->ee_rxtxMarginTurbo[1] =
+                                                       (eeval >> 5) & 0x3F;
+                                               ee->ee_adcDesiredSizeTurbo[1] =
+                                                       (eeval >> 11) & 0x1F;
+                                               EEREAD(off++);
+                                               ee->ee_adcDesiredSizeTurbo[1] |=
+                                                       (eeval & 0x7) << 5;
+                                               ee->ee_pgaDesiredSizeTurbo[1] =
+                                                       (eeval >> 3) & 0xFF;
+                                       }
+                               }
+                               break;
+                       case headerInfo11A:
+                               if (ee->ee_version >= AR_EEPROM_VER4_1) {
+                                       EEREAD(off++);
+                                       ee->ee_rxtxMargin[headerInfo11A] =
+                                               eeval & 0x3f;
+                                       if (ee->ee_version >= AR_EEPROM_VER5_0) {
+                                               ee->ee_switchSettlingTurbo[0] =
+                                                       (eeval >> 6) & 0x7f;
+                                               ee->ee_txrxAttenTurbo[0] =
+                                                       (eeval >> 13) & 0x7;
+                                               EEREAD(off++);
+                                               ee->ee_txrxAttenTurbo[0] |=
+                                                       (eeval & 0x7) << 3;
+                                               ee->ee_rxtxMarginTurbo[0] =
+                                                       (eeval >> 3) & 0x3F;
+                                               ee->ee_adcDesiredSizeTurbo[0] =
+                                                       (eeval >> 9) & 0x7F;
+                                               EEREAD(off++);
+                                               ee->ee_adcDesiredSizeTurbo[0] |=
+                                                       (eeval & 0x1) << 7;
+                                               ee->ee_pgaDesiredSizeTurbo[0] =
+                                                       (eeval >> 1) & 0xFF;
+                                       }
+                               }
+                               break;
+                       }
+               }
+       }
+       if (ee->ee_version < AR_EEPROM_VER3_3) {
+               /* Version 3.1+ specific parameters */
+               EEREAD(0xec);
+               ee->ee_ob2GHz[0] = eeval & 0x7;
+               ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
+
+               EEREAD(0xed);
+               ee->ee_ob2GHz[1] = eeval & 0x7;
+               ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
+       }
+
+       /* Initialize corner cal (thermal tx gain adjust parameters) */
+       ee->ee_cornerCal.clip = 4;
+       ee->ee_cornerCal.pd90 = 1;
+       ee->ee_cornerCal.pd84 = 1;
+       ee->ee_cornerCal.gSel = 0;
+
+       /*
+       * Read the conformance test limit identifiers
+       * These are used to match regulatory domain testing needs with
+       * the RD-specific tests that have been calibrated in the EEPROM.
+       */
+       off = header[5];
+       for (i = 0; i < ee->ee_numCtls; i += 2) {
+               EEREAD(off++);
+               ee->ee_ctl[i] = (eeval >> 8) & 0xff;
+               ee->ee_ctl[i+1] = eeval & 0xff;
+       }
+
+       if (ee->ee_version < AR_EEPROM_VER5_3) {
+               /* XXX only for 5413? */
+               ee->ee_spurChans[0][1] = AR_SPUR_5413_1;
+               ee->ee_spurChans[1][1] = AR_SPUR_5413_2;
+               ee->ee_spurChans[2][1] = AR_NO_SPUR;
+               ee->ee_spurChans[0][0] = AR_NO_SPUR;
+       } else {
+               /* Read spur mitigation data */
+               for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+                       EEREAD(off);
+                       ee->ee_spurChans[i][0] = eeval;
+                       EEREAD(off+AR_EEPROM_MODAL_SPURS);
+                       ee->ee_spurChans[i][1] = eeval;
+                       off++;
+               }
+       }
+
+       /* for recent changes to NF scale */
+       if (ee->ee_version <= AR_EEPROM_VER3_2) {
+               ee->ee_noiseFloorThresh[headerInfo11A] = -54;
+               ee->ee_noiseFloorThresh[headerInfo11B] = -1;
+               ee->ee_noiseFloorThresh[headerInfo11G] = -1;
+       }
+       /* to override thresh62 for better 2.4 and 5 operation */
+       if (ee->ee_version <= AR_EEPROM_VER3_2) {
+               ee->ee_thresh62[headerInfo11A] = 15;    /* 11A */
+               ee->ee_thresh62[headerInfo11B] = 28;    /* 11B */
+               ee->ee_thresh62[headerInfo11G] = 28;    /* 11G */
+       }
+
+       /* Check for regulatory capabilities */
+       if (ee->ee_version >= AR_EEPROM_VER4_0) {
+               EEREAD(regCapOffsetPost4_0);
+       } else {
+               EEREAD(regCapOffsetPre4_0);
+       }
+
+       ee->ee_regCap = eeval;
+
+       if (ee->ee_Amode == 0) {
+               /* Check for valid Amode in upgraded h/w */
+               if (ee->ee_version >= AR_EEPROM_VER4_0) {
+                       ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A)?1:0;
+               } else {
+                       ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0;
+               }
+       }
+
+       if (ee->ee_version >= AR_EEPROM_VER5_1)
+               EEREAD(AR_EEPROM_CAPABILITIES_OFFSET);
+       else
+               eeval = 0;
+       ee->ee_opCap = eeval;
+
+       EEREAD(AR_EEPROM_REG_DOMAIN);
+       ee->ee_regdomain = eeval;
+
+       return AH_TRUE;
+#undef EEREAD
+}
+
+/*
+ * Now verify and copy EEPROM contents into the allocated space
+ */
+static HAL_BOOL
+legacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee)
+{
+       /* Read the header information here */
+       if (!readHeaderInfo(ah, ee))
+               return AH_FALSE;
+#if 0
+       /* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */
+       if (IS_5112(ah) && !ee->ee_eepMap) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: 5112 devices must have EEPROM 4.0 with the "
+                   "EEP_MAP set\n", __func__);
+               return AH_FALSE;
+       }
+#endif
+       /*
+        * Group 1: frequency pier locations readback
+        * check that the structure has been populated
+        * with enough space to hold the channels
+        *
+        * NOTE: Group 1 contains the 5 GHz channel numbers
+        *       that have dBm->pcdac calibrated information.
+        */
+       if (!readEepromFreqPierInfo(ah, ee))
+               return AH_FALSE;
+
+       /*
+        * Group 2:  readback data for all frequency piers
+        *
+        * NOTE: Group 2 contains the raw power calibration
+        *       information for each of the channels that we
+        *       recorded above.
+        */
+       if (!readEepromRawPowerCalInfo(ah, ee))
+               return AH_FALSE;
+
+       /*
+        * Group 5: target power values per rate
+        *
+        * NOTE: Group 5 contains the recorded maximum power
+        *       in dB that can be attained for the given rate.
+        */
+       /* Read the power per rate info for test channels */
+       if (!readEepromTargetPowerCalInfo(ah, ee))
+               return AH_FALSE;
+
+       /*
+        * Group 8: Conformance Test Limits information
+        *
+        * NOTE: Group 8 contains the values to limit the
+        *       maximum transmit power value based on any
+        *       band edge violations.
+        */
+       /* Read the RD edge power limits */
+       return readEepromCTLInfo(ah, ee);
+}
+
+static HAL_STATUS
+legacyEepromGet(struct ath_hal *ah, int param, void *val)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint8_t *macaddr;
+       uint16_t eeval;
+       uint32_t sum;
+       int i;
+
+       switch (param) {
+       case AR_EEP_OPCAP:
+               *(uint16_t *) val = ee->ee_opCap;
+               return HAL_OK;
+       case AR_EEP_REGDMN_0:
+               *(uint16_t *) val = ee->ee_regdomain;
+               return HAL_OK;
+       case AR_EEP_RFSILENT:
+               if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval))
+                       return HAL_EEREAD;
+               *(uint16_t *) val = eeval;
+               return HAL_OK;
+       case AR_EEP_MACADDR:
+               sum = 0;
+               macaddr = val;
+               for (i = 0; i < 3; i++) {
+                       if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) {
+                               HALDEBUG(ah, HAL_DEBUG_ANY,
+                                   "%s: cannot read EEPROM location %u\n",
+                                   __func__, i);
+                               return HAL_EEREAD;
+                       }
+                       sum += eeval;
+                       macaddr[2*i] = eeval >> 8;
+                       macaddr[2*i + 1] = eeval & 0xff;
+               }
+               if (sum == 0 || sum == 0xffff*3) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: mac address read failed: %s\n", __func__,
+                           ath_hal_ether_sprintf(macaddr));
+                       return HAL_EEBADMAC;
+               }
+               return HAL_OK;
+       case AR_EEP_RFKILL:
+               HALASSERT(val == AH_NULL);
+               return ee->ee_rfKill ? HAL_OK : HAL_EIO;
+       case AR_EEP_AMODE:
+               HALASSERT(val == AH_NULL);
+               return ee->ee_Amode ? HAL_OK : HAL_EIO;
+       case AR_EEP_BMODE:
+               HALASSERT(val == AH_NULL);
+               return ee->ee_Bmode ? HAL_OK : HAL_EIO;
+       case AR_EEP_GMODE:
+               HALASSERT(val == AH_NULL);
+               return ee->ee_Gmode ? HAL_OK : HAL_EIO;
+       case AR_EEP_TURBO5DISABLE:
+               HALASSERT(val == AH_NULL);
+               return ee->ee_turbo5Disable ? HAL_OK : HAL_EIO;
+       case AR_EEP_TURBO2DISABLE:
+               HALASSERT(val == AH_NULL);
+               return ee->ee_turbo2Disable ? HAL_OK : HAL_EIO;
+       case AR_EEP_ISTALON:            /* Talon detect */
+               HALASSERT(val == AH_NULL);
+               return (ee->ee_version >= AR_EEPROM_VER5_4 &&
+                   ath_hal_eepromRead(ah, 0x0b, &eeval) && eeval == 1) ?
+                       HAL_OK : HAL_EIO;
+       case AR_EEP_32KHZCRYSTAL:
+               HALASSERT(val == AH_NULL);
+               return ee->ee_exist32kHzCrystal ? HAL_OK : HAL_EIO;
+       case AR_EEP_COMPRESS:
+               HALASSERT(val == AH_NULL);
+               return (ee->ee_opCap & AR_EEPROM_EEPCAP_COMPRESS_DIS) == 0 ?
+                   HAL_OK : HAL_EIO;
+       case AR_EEP_FASTFRAME:
+               HALASSERT(val == AH_NULL);
+               return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ?
+                   HAL_OK : HAL_EIO;
+       case AR_EEP_AES:
+               HALASSERT(val == AH_NULL);
+               return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ?
+                   HAL_OK : HAL_EIO;
+       case AR_EEP_BURST:
+               HALASSERT(val == AH_NULL);
+               return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ?
+                   HAL_OK : HAL_EIO;
+       case AR_EEP_MAXQCU:
+               if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) {
+                       *(uint16_t *) val =
+                           MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU);
+                       return HAL_OK;
+               } else
+                       return HAL_EIO;
+       case AR_EEP_KCENTRIES:
+               if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) {
+                       *(uint16_t *) val =
+                           1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES);
+                       return HAL_OK;
+               } else
+                       return HAL_EIO;
+       case AR_EEP_ANTGAINMAX_5:
+               *(int8_t *) val = ee->ee_antennaGainMax[0];
+               return HAL_OK;
+       case AR_EEP_ANTGAINMAX_2:
+               *(int8_t *) val = ee->ee_antennaGainMax[1];
+               return HAL_OK;
+       case AR_EEP_WRITEPROTECT:
+               HALASSERT(val == AH_NULL);
+               return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ?
+                   HAL_OK : HAL_EIO;
+       }
+       return HAL_EINVAL;
+}
+
+static HAL_BOOL
+legacyEepromSet(struct ath_hal *ah, int param, int v)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       switch (param) {
+       case AR_EEP_AMODE:
+               ee->ee_Amode = v;
+               return HAL_OK;
+       case AR_EEP_BMODE:
+               ee->ee_Bmode = v;
+               return HAL_OK;
+       case AR_EEP_GMODE:
+               ee->ee_Gmode = v;
+               return HAL_OK;
+       case AR_EEP_TURBO5DISABLE:
+               ee->ee_turbo5Disable = v;
+               return HAL_OK;
+       case AR_EEP_TURBO2DISABLE:
+               ee->ee_turbo2Disable = v;
+               return HAL_OK;
+       case AR_EEP_COMPRESS:
+               if (v)
+                       ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS;
+               else
+                       ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS;
+               return HAL_OK;
+       case AR_EEP_FASTFRAME:
+               if (v)
+                       ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS;
+               else
+                       ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS;
+               return HAL_OK;
+       case AR_EEP_AES:
+               if (v)
+                       ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS;
+               else
+                       ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS;
+               return HAL_OK;
+       case AR_EEP_BURST:
+               if (v)
+                       ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS;
+               else
+                       ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS;
+               return HAL_OK;
+       }
+       return HAL_EINVAL;
+}
+
+static HAL_BOOL
+legacyEepromDiag(struct ath_hal *ah, int request,
+     const void *args, uint32_t argsize, void **result, uint32_t *resultsize)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       const EEPROM_POWER_EXPN_5112 *pe;
+
+       switch (request) {
+       case HAL_DIAG_EEPROM:
+               *result = ee;
+               *resultsize = sizeof(*ee);
+               return AH_TRUE;
+       case HAL_DIAG_EEPROM_EXP_11A:
+       case HAL_DIAG_EEPROM_EXP_11B:
+       case HAL_DIAG_EEPROM_EXP_11G:
+               pe = &ee->ee_modePowerArray5112[
+                   request - HAL_DIAG_EEPROM_EXP_11A];
+               *result = pe->pChannels;
+               *resultsize = (*result == AH_NULL) ? 0 :
+                       roundup(sizeof(uint16_t) * pe->numChannels,
+                               sizeof(uint32_t)) +
+                       sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels;
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+static uint16_t
+legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+       HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS);
+       return ee->ee_spurChans[ix][is2GHz];
+}
+
+/*
+ * Reclaim any EEPROM-related storage.
+ */
+static void
+legacyEepromDetach(struct ath_hal *ah)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+
+        if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
+               return freeEepromRawPowerCalInfo5112(ah, ee);
+       ath_hal_free(ee);
+       AH_PRIVATE(ah)->ah_eeprom = AH_NULL;
+}
+
+/*
+ * These are not valid 2.4 channels, either we change 'em
+ * or we need to change the coding to accept them.
+ */
+static const uint16_t channels11b[] = { 2412, 2447, 2484 };
+static const uint16_t channels11g[] = { 2312, 2412, 2484 };
+
+HAL_STATUS
+ath_hal_legacyEepromAttach(struct ath_hal *ah)
+{
+       HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
+       uint32_t sum, eepMax;
+       uint16_t eeversion, eeprotect, eeval;
+       u_int i;
+
+       HALASSERT(ee == AH_NULL);
+
+       if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeversion)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: unable to read EEPROM version\n", __func__);
+               return HAL_EEREAD;
+       }
+       if (eeversion < AR_EEPROM_VER3) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version "
+                   "%u (0x%x) found\n", __func__, eeversion, eeversion);
+               return HAL_EEVERSION;
+       }
+
+       if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &eeprotect)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read EEPROM protection "
+                   "bits; read locked?\n", __func__);
+               return HAL_EEREAD;
+       }
+       HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect);
+       /* XXX check proper access before continuing */
+
+       /*
+        * Read the Atheros EEPROM entries and calculate the checksum.
+        */
+       if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) {
+               HALDEBUG(ah, HAL_DEBUG_ANY,
+                   "%s: cannot read EEPROM upper size\n" , __func__);
+               return HAL_EEREAD;
+       }
+       if (eeval != 0) {
+               eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) <<
+                       AR_EEPROM_SIZE_ENDLOC_SHIFT;
+               if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) {
+                       HALDEBUG(ah, HAL_DEBUG_ANY,
+                           "%s: cannot read EEPROM lower size\n" , __func__);
+                       return HAL_EEREAD;
+               }
+               eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE;
+       } else
+               eepMax = AR_EEPROM_ATHEROS_MAX;
+       sum = 0;
+       for (i = 0; i < eepMax; i++) {
+               if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) {
+                       return HAL_EEREAD;
+               }
+               sum ^= eeval;
+       }
+       if (sum != 0xffff) {
+               HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n",
+                   __func__, sum);
+               return HAL_EEBADSUM;
+       }
+
+       ee = ath_hal_malloc(sizeof(HAL_EEPROM));
+       if (ee == AH_NULL) {
+               /* XXX message */
+               return HAL_ENOMEM;
+       }
+
+       ee->ee_protect = eeprotect;
+       ee->ee_version = eeversion;
+
+       ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS;
+       ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS;
+
+       for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++)
+               ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES;
+
+       /* the channel list for 2.4 is fixed, fill this in here */
+       for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) {
+               ee->ee_channels11b[i] = channels11b[i];
+               /* XXX 5211 requires a hack though we don't support 11g */
+               if (ah->ah_magic == 0x19570405)
+                       ee->ee_channels11g[i] = channels11b[i];
+               else
+                       ee->ee_channels11g[i] = channels11g[i];
+               ee->ee_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES;
+               ee->ee_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES;
+       }
+
+       if (!legacyEepromReadContents(ah, ee)) {
+               /* XXX message */
+               ath_hal_free(ee);
+               return HAL_EEREAD;      /* XXX */
+       }
+
+       AH_PRIVATE(ah)->ah_eeprom = ee;
+       AH_PRIVATE(ah)->ah_eeversion = eeversion;
+       AH_PRIVATE(ah)->ah_eepromDetach = legacyEepromDetach;
+       AH_PRIVATE(ah)->ah_eepromGet = legacyEepromGet;
+       AH_PRIVATE(ah)->ah_eepromSet = legacyEepromSet;
+       AH_PRIVATE(ah)->ah_getSpurChan = legacyEepromGetSpurChan;
+       AH_PRIVATE(ah)->ah_eepromDiag = legacyEepromDiag;
+       return HAL_OK;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_eeprom_v3.h    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_eeprom_v3.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AH_EEPROM_V3_H_
+#define _ATH_AH_EEPROM_V3_H_
+
+#include "ah_eeprom.h"
+
+/* EEPROM defines for Version 2 & 3 AR5211 chips */
+#define        AR_EEPROM_RFSILENT      0x0f    /* RF Silent/Clock Run Enable */
+#define        AR_EEPROM_MAC(i)        (0x1d+(i)) /* MAC address word */
+#define        AR_EEPROM_MAGIC         0x3d    /* magic number */
+#define        AR_EEPROM_PROTECT       0x3f    /* EEPROM protect bits */
+#define        AR_EEPROM_PROTECT_PCIE  0x01    /* EEPROM protect bits for Condor/Swan*/
+#define        AR_EEPROM_REG_DOMAIN    0xbf    /* current regulatory domain */
+#define        AR_EEPROM_ATHEROS_BASE  0xc0    /* Base of Atheros-specific data */
+#define        AR_EEPROM_ATHEROS(i)    (AR_EEPROM_ATHEROS_BASE+(i))
+#define        AR_EEPROM_ATHEROS_MAX   (0x400-AR_EEPROM_ATHEROS_BASE)
+#define        AR_EEPROM_VERSION       AR_EEPROM_ATHEROS(1)
+
+/* FLASH(EEPROM) Defines for AR531X chips */
+#define AR_EEPROM_SIZE_LOWER    0x1b    /* size info -- lower */
+#define AR_EEPROM_SIZE_UPPER    0x1c    /* size info -- upper */
+#define AR_EEPROM_SIZE_UPPER_MASK 0xfff0
+#define AR_EEPROM_SIZE_UPPER_SHIFT 4
+#define        AR_EEPROM_SIZE_ENDLOC_SHIFT 12
+#define AR_EEPROM_ATHEROS_MAX_LOC 0x400
+#define AR_EEPROM_ATHEROS_MAX_OFF (AR_EEPROM_ATHEROS_MAX_LOC-AR_EEPROM_ATHEROS_BASE)
+
+/* regulatory capabilities offsets */
+#define AR_EEPROM_REG_CAPABILITIES_OFFSET              0xCA
+#define AR_EEPROM_REG_CAPABILITIES_OFFSET_PRE4_0       0xCF /* prior to 4.0 */
+
+/* regulatory capabilities */
+#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND      0x0040
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN       0x0080
+#define AR_EEPROM_EEREGCAP_EN_KK_U2            0x0100
+#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND       0x0200
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD                0x0400
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A       0x0800
+
+/* regulatory capabilities prior to eeprom version 4.0 */
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0        0x8000
+
+/*
+ * AR2413 (includes AR5413)
+ */
+#define AR_EEPROM_SERIAL_NUM_OFFSET     0xB0    /* EEPROM serial number */
+#define AR_EEPROM_SERIAL_NUM_SIZE       12      /* EEPROM serial number size */
+#define AR_EEPROM_CAPABILITIES_OFFSET   0xC9    /* EEPROM Location of capabilities */
+
+#define AR_EEPROM_EEPCAP_COMPRESS_DIS  0x0001
+#define AR_EEPROM_EEPCAP_AES_DIS       0x0002
+#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004
+#define AR_EEPROM_EEPCAP_BURST_DIS     0x0008
+#define AR_EEPROM_EEPCAP_MAXQCU                0x01F0
+#define AR_EEPROM_EEPCAP_MAXQCU_S      4
+#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200
+#define AR_EEPROM_EEPCAP_KC_ENTRIES    0xF000
+#define AR_EEPROM_EEPCAP_KC_ENTRIES_S  12
+
+/* XXX used to index various EEPROM-derived data structures */
+enum {
+       headerInfo11A   = 0,
+       headerInfo11B   = 1,
+       headerInfo11G   = 2,
+};
+
+#define GROUPS_OFFSET3_2       0x100   /* groups offset for ver3.2 and earlier */
+#define GROUPS_OFFSET3_3       0x150   /* groups offset for ver3.3 */
+/* relative offset of GROUPi to GROUPS_OFFSET */
+#define GROUP1_OFFSET          0x0
+#define GROUP2_OFFSET          0x5
+#define GROUP3_OFFSET          0x37
+#define GROUP4_OFFSET          0x46
+#define GROUP5_OFFSET          0x55
+#define GROUP6_OFFSET          0x65
+#define GROUP7_OFFSET          0x69
+#define GROUP8_OFFSET          0x6f
+
+/* RF silent fields in EEPROM */
+#define AR_EEPROM_RFSILENT_GPIO_SEL    0x001c
+#define AR_EEPROM_RFSILENT_GPIO_SEL_S  2
+#define AR_EEPROM_RFSILENT_POLARITY    0x0002
+#define AR_EEPROM_RFSILENT_POLARITY_S  1
+
+/* Protect Bits RP is read protect, WP is write protect */
+#define        AR_EEPROM_PROTECT_RP_0_31       0x0001
+#define        AR_EEPROM_PROTECT_WP_0_31       0x0002
+#define        AR_EEPROM_PROTECT_RP_32_63      0x0004
+#define        AR_EEPROM_PROTECT_WP_32_63      0x0008
+#define        AR_EEPROM_PROTECT_RP_64_127     0x0010
+#define        AR_EEPROM_PROTECT_WP_64_127     0x0020
+#define        AR_EEPROM_PROTECT_RP_128_191    0x0040
+#define        AR_EEPROM_PROTECT_WP_128_191    0x0080
+#define        AR_EEPROM_PROTECT_RP_192_207    0x0100
+#define        AR_EEPROM_PROTECT_WP_192_207    0x0200
+#define        AR_EEPROM_PROTECT_RP_208_223    0x0400
+#define        AR_EEPROM_PROTECT_WP_208_223    0x0800
+#define        AR_EEPROM_PROTECT_RP_224_239    0x1000
+#define        AR_EEPROM_PROTECT_WP_224_239    0x2000
+#define        AR_EEPROM_PROTECT_RP_240_255    0x4000
+#define        AR_EEPROM_PROTECT_WP_240_255    0x8000
+
+#define        AR_EEPROM_MODAL_SPURS           5
+#define        AR_SPUR_5413_1                  1640    /* Freq 2464 */
+#define        AR_SPUR_5413_2                  1200    /* Freq 2420 */
+
+/*
+ * EEPROM fixed point conversion scale factors.
+ * NB: if you change one be sure to keep the other in sync.
+ */
+#define EEP_SCALE      100             /* conversion scale to avoid fp arith */
+#define EEP_DELTA      10              /* SCALE/10, to avoid arith divide */
+
+#define PWR_MIN                0
+#define PWR_MAX                3150            /* 31.5 * SCALE */
+#define PWR_STEP       50              /* 0.5 * SCALE */
+/* Keep 2 above defines together */
+
+#define NUM_11A_EEPROM_CHANNELS        10
+#define NUM_2_4_EEPROM_CHANNELS        3
+#define NUM_PCDAC_VALUES       11
+#define NUM_TEST_FREQUENCIES   8
+#define NUM_EDGES              8
+#define NUM_INTERCEPTS         11
+#define FREQ_MASK              0x7f
+#define FREQ_MASK_3_3          0xff    /* expanded in version 3.3 */
+#define PCDAC_MASK             0x3f
+#define POWER_MASK             0x3f
+#define        NON_EDGE_FLAG_MASK      0x40
+#define CHANNEL_POWER_INFO     8
+#define OBDB_UNSET             0xffff
+#define        CHANNEL_UNUSED          0xff
+#define        SCALE_OC_DELTA(_x)      (((_x) * 2) / 10)
+
+/* Used during pcdac table construction */
+#define PCDAC_START    1
+#define PCDAC_STOP     63
+#define PCDAC_STEP     1
+#define PWR_TABLE_SIZE 64
+#define        MAX_RATE_POWER  63
+
+/* Used during power/rate table construction */
+#define NUM_CTLS       16
+#define        NUM_CTLS_3_3    32              /* expanded in version 3.3 */
+#define        NUM_CTLS_MAX    NUM_CTLS_3_3
+
+typedef struct fullPcdacStruct {
+       uint16_t        channelValue;
+       uint16_t        pcdacMin;
+       uint16_t        pcdacMax;
+       uint16_t        numPcdacValues;
+       uint16_t        PcdacValues[64];
+       /* power is 32bit since in dest it is scaled */
+       int16_t         PwrValues[64];
+} FULL_PCDAC_STRUCT;
+
+typedef struct dataPerChannel {
+       uint16_t        channelValue;
+       uint16_t        pcdacMin;
+       uint16_t        pcdacMax;
+       uint16_t        numPcdacValues;
+       uint16_t        PcdacValues[NUM_PCDAC_VALUES];
+       /* NB: power is 32bit since in dest it is scaled */
+       int16_t         PwrValues[NUM_PCDAC_VALUES];
+} DATA_PER_CHANNEL;
+
+/* points to the appropriate pcdac structs in the above struct based on mode */
+typedef struct pcdacsEeprom {
+       const uint16_t  *pChannelList;
+       uint16_t        numChannels;
+       const DATA_PER_CHANNEL *pDataPerChannel;
+} PCDACS_EEPROM;
+
+typedef struct trgtPowerInfo {
+       uint16_t        twicePwr54;
+       uint16_t        twicePwr48;
+       uint16_t        twicePwr36;
+       uint16_t        twicePwr6_24;
+       uint16_t        testChannel;
+} TRGT_POWER_INFO;
+
+typedef struct trgtPowerAllModes {
+       uint16_t        numTargetPwr_11a;
+       TRGT_POWER_INFO trgtPwr_11a[NUM_TEST_FREQUENCIES];
+       uint16_t        numTargetPwr_11g;
+       TRGT_POWER_INFO trgtPwr_11g[3];
+       uint16_t        numTargetPwr_11b;
+       TRGT_POWER_INFO trgtPwr_11b[2];
+} TRGT_POWER_ALL_MODES;
+
+typedef struct cornerCalInfo {
+       uint16_t        gSel;
+       uint16_t        pd84;
+       uint16_t        pd90;
+       uint16_t        clip;
+} CORNER_CAL_INFO;
+
+/*
+ * EEPROM version 4 definitions
+ */
+#define NUM_XPD_PER_CHANNEL      4
+#define NUM_POINTS_XPD0          4
+#define NUM_POINTS_XPD3          3
+#define IDEAL_10dB_INTERCEPT_2G  35
+#define IDEAL_10dB_INTERCEPT_5G  55
+
+#define        TENX_OFDM_CCK_DELTA_INIT        15              /* power 1.5 dbm */
+#define        TENX_CH14_FILTER_CCK_DELTA_INIT 15              /* power 1.5 dbm */
+#define        CCK_OFDM_GAIN_DELTA             15
+
+#define NUM_TARGET_POWER_LOCATIONS_11B  4
+#define NUM_TARGET_POWER_LOCATIONS_11G  6
+
+
+typedef struct {
+       uint16_t        xpd_gain;
+       uint16_t        numPcdacs;
+       uint16_t        pcdac[NUM_POINTS_XPD0];
+       int16_t         pwr_t4[NUM_POINTS_XPD0];        /* or gainF */
+} EXPN_DATA_PER_XPD_5112;
+
+typedef struct {
+       uint16_t        channelValue;
+       int16_t         maxPower_t4;
+       EXPN_DATA_PER_XPD_5112  pDataPerXPD[NUM_XPD_PER_CHANNEL];
+} EXPN_DATA_PER_CHANNEL_5112;
+
+typedef struct {
+       uint16_t        *pChannels;
+       uint16_t        numChannels;
+       uint16_t        xpdMask;        /* mask of permitted xpd_gains */
+       EXPN_DATA_PER_CHANNEL_5112 *pDataPerChannel;
+} EEPROM_POWER_EXPN_5112;
+
+typedef struct {
+       uint16_t        channelValue;
+       uint16_t        pcd1_xg0;
+       int16_t         pwr1_xg0;
+       uint16_t        pcd2_delta_xg0;
+       int16_t         pwr2_xg0;
+       uint16_t        pcd3_delta_xg0;
+       int16_t         pwr3_xg0;
+       uint16_t        pcd4_delta_xg0;
+       int16_t         pwr4_xg0;
+       int16_t         maxPower_t4;
+       int16_t         pwr1_xg3;       /* pcdac = 20 */
+       int16_t         pwr2_xg3;       /* pcdac = 35 */
+       int16_t         pwr3_xg3;       /* pcdac = 63 */
+       /* XXX - Should be pwr1_xg2, etc to agree with documentation */
+} EEPROM_DATA_PER_CHANNEL_5112;
+
+typedef struct {
+       uint16_t        pChannels[NUM_11A_EEPROM_CHANNELS];
+       uint16_t        numChannels;
+       uint16_t        xpdMask;        /* mask of permitted xpd_gains */
+       EEPROM_DATA_PER_CHANNEL_5112 pDataPerChannel[NUM_11A_EEPROM_CHANNELS];
+} EEPROM_POWER_5112;
+
+/*
+ * EEPROM version 5 definitions (Griffin, et. al.).
+ */
+#define NUM_2_4_EEPROM_CHANNELS_2413   4
+#define NUM_11A_EEPROM_CHANNELS_2413    10
+#define PWR_TABLE_SIZE_2413            128
+
+/* Used during pdadc construction */
+#define        MAX_NUM_PDGAINS_PER_CHANNEL     4
+#define        NUM_PDGAINS_PER_CHANNEL         2
+#define        NUM_POINTS_LAST_PDGAIN          5
+#define        NUM_POINTS_OTHER_PDGAINS        4
+#define        XPD_GAIN1_GEN5                  3
+#define        XPD_GAIN2_GEN5                  1
+#define        MAX_PWR_RANGE_IN_HALF_DB        64
+#define        PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB     4
+
+typedef struct {
+       uint16_t        pd_gain;
+       uint16_t        numVpd;
+       uint16_t        Vpd[NUM_POINTS_LAST_PDGAIN];
+       int16_t         pwr_t4[NUM_POINTS_LAST_PDGAIN]; /* or gainF */
+} RAW_DATA_PER_PDGAIN_2413;
+
+typedef struct {
+       uint16_t        channelValue;
+       int16_t         maxPower_t4;
+       uint16_t        numPdGains;     /* # Pd Gains per channel */
+       RAW_DATA_PER_PDGAIN_2413 pDataPerPDGain[MAX_NUM_PDGAINS_PER_CHANNEL];
+} RAW_DATA_PER_CHANNEL_2413;
+
+/* XXX: assumes NUM_11A_EEPROM_CHANNELS_2413 >= NUM_2_4_EEPROM_CHANNELS_2413 ??? */
+typedef struct {
+       uint16_t        pChannels[NUM_11A_EEPROM_CHANNELS_2413];
+       uint16_t        numChannels;
+       uint16_t        xpd_mask;       /* mask of permitted xpd_gains */
+       RAW_DATA_PER_CHANNEL_2413 pDataPerChannel[NUM_11A_EEPROM_CHANNELS_2413];
+} RAW_DATA_STRUCT_2413;
+
+typedef struct {
+       uint16_t        channelValue;
+       uint16_t        numPdGains;
+       uint16_t        Vpd_I[MAX_NUM_PDGAINS_PER_CHANNEL];
+       int16_t         pwr_I[MAX_NUM_PDGAINS_PER_CHANNEL];
+       uint16_t        Vpd_delta[NUM_POINTS_LAST_PDGAIN]
+                               [MAX_NUM_PDGAINS_PER_CHANNEL];
+       int16_t         pwr_delta_t2[NUM_POINTS_LAST_PDGAIN]
+                               [MAX_NUM_PDGAINS_PER_CHANNEL];
+       int16_t         maxPower_t4;
+} EEPROM_DATA_PER_CHANNEL_2413;
+
+typedef struct {
+       uint16_t        pChannels[NUM_11A_EEPROM_CHANNELS_2413];
+       uint16_t        numChannels;
+       uint16_t        xpd_mask;       /* mask of permitted xpd_gains */
+       EEPROM_DATA_PER_CHANNEL_2413 pDataPerChannel[NUM_11A_EEPROM_CHANNELS_2413];
+} EEPROM_DATA_STRUCT_2413;
+
+/*
+ * Information retrieved from EEPROM.
+ */
+typedef struct {
+       uint16_t        ee_version;             /* Version field */
+       uint16_t        ee_protect;             /* EEPROM protect field */
+       uint16_t        ee_regdomain;           /* Regulatory domain */
+
+       /* General Device Parameters */
+       uint16_t        ee_turbo5Disable;
+       uint16_t        ee_turbo2Disable;
+       uint16_t        ee_rfKill;
+       uint16_t        ee_deviceType;
+       uint16_t        ee_turbo2WMaxPower5;
+       uint16_t        ee_turbo2WMaxPower2;
+       uint16_t        ee_xrTargetPower5;
+       uint16_t        ee_xrTargetPower2;
+       uint16_t        ee_Amode;
+       uint16_t        ee_regCap;
+       uint16_t        ee_Bmode;
+       uint16_t        ee_Gmode;
+       int8_t          ee_antennaGainMax[2];
+       uint16_t        ee_xtnd5GSupport;
+       uint8_t         ee_cckOfdmPwrDelta;
+       uint8_t         ee_exist32kHzCrystal;
+       uint16_t        ee_targetPowersStart;
+       uint16_t        ee_fixedBias5;
+       uint16_t        ee_fixedBias2;
+       uint16_t        ee_cckOfdmGainDelta;
+       uint16_t        ee_scaledCh14FilterCckDelta;
+       uint16_t        ee_eepMap;
+       uint16_t        ee_earStart;
+
+       /* 5 GHz / 2.4 GHz CKK / 2.4 GHz OFDM common parameters */
+       uint16_t        ee_switchSettling[3];
+       uint16_t        ee_txrxAtten[3];
+       uint16_t        ee_txEndToXLNAOn[3];
+       uint16_t        ee_thresh62[3];
+       uint16_t        ee_txEndToXPAOff[3];
+       uint16_t        ee_txFrameToXPAOn[3];
+       int8_t          ee_adcDesiredSize[3];    /* 8-bit signed value */
+       int8_t          ee_pgaDesiredSize[3];    /* 8-bit signed value */
+       int16_t         ee_noiseFloorThresh[3];
+       uint16_t        ee_xlnaGain[3];
+       uint16_t        ee_xgain[3];
+       uint16_t        ee_xpd[3];
+       uint16_t        ee_antennaControl[11][3];
+       uint16_t        ee_falseDetectBackoff[3];
+       uint16_t        ee_gainI[3];
+       uint16_t        ee_rxtxMargin[3];
+
+       /* new parameters added for the AR2413 */
+       HAL_BOOL        ee_disableXr5;
+       HAL_BOOL        ee_disableXr2;
+       uint16_t        ee_eepMap2PowerCalStart;
+       uint16_t        ee_capField;
+
+       uint16_t        ee_switchSettlingTurbo[2];
+       uint16_t        ee_txrxAttenTurbo[2];
+       int8_t          ee_adcDesiredSizeTurbo[2];
+       int8_t          ee_pgaDesiredSizeTurbo[2];
+       uint16_t        ee_rxtxMarginTurbo[2];
+
+       /* 5 GHz parameters */
+       uint16_t        ee_ob1;
+       uint16_t        ee_db1;
+       uint16_t        ee_ob2;
+       uint16_t        ee_db2;
+       uint16_t        ee_ob3;
+       uint16_t        ee_db3;
+       uint16_t        ee_ob4;
+       uint16_t        ee_db4;
+
+       /* 2.4 GHz parameters */
+       uint16_t        ee_obFor24;
+       uint16_t        ee_dbFor24;
+       uint16_t        ee_obFor24g;
+       uint16_t        ee_dbFor24g;
+       uint16_t        ee_ob2GHz[2];
+       uint16_t        ee_db2GHz[2];
+       uint16_t        ee_numCtls;
+       uint16_t        ee_ctl[NUM_CTLS_MAX];
+       uint16_t        ee_iqCalI[2];
+       uint16_t        ee_iqCalQ[2];
+       uint16_t        ee_calPier11g[NUM_2_4_EEPROM_CHANNELS];
+       uint16_t        ee_calPier11b[NUM_2_4_EEPROM_CHANNELS];
+
+       /* corner calibration information */
+       CORNER_CAL_INFO ee_cornerCal;
+
+       uint16_t        ee_opCap;
+
+       /* 11a info */
+       uint16_t        ee_channels11a[NUM_11A_EEPROM_CHANNELS];
+       uint16_t        ee_numChannels11a;
+       DATA_PER_CHANNEL ee_dataPerChannel11a[NUM_11A_EEPROM_CHANNELS];
+
+       uint16_t        ee_numChannels2_4;
+       uint16_t        ee_channels11g[NUM_2_4_EEPROM_CHANNELS];
+       uint16_t        ee_channels11b[NUM_2_4_EEPROM_CHANNELS];
+       uint16_t        ee_spurChans[AR_EEPROM_MODAL_SPURS][2];
+
+       /* 11g info */
+       DATA_PER_CHANNEL ee_dataPerChannel11g[NUM_2_4_EEPROM_CHANNELS];
+
+       /* 11b info */
+       DATA_PER_CHANNEL ee_dataPerChannel11b[NUM_2_4_EEPROM_CHANNELS];
+
+       TRGT_POWER_ALL_MODES ee_tpow;
+
+       RD_EDGES_POWER  ee_rdEdgesPower[NUM_EDGES*NUM_CTLS_MAX];
+
+       union {
+               EEPROM_POWER_EXPN_5112  eu_modePowerArray5112[3];
+               RAW_DATA_STRUCT_2413    eu_rawDataset2413[3];
+       } ee_u;
+} HAL_EEPROM;
+
+/* write-around defines */
+#define        ee_numTargetPwr_11a     ee_tpow.numTargetPwr_11a
+#define        ee_trgtPwr_11a          ee_tpow.trgtPwr_11a
+#define        ee_numTargetPwr_11g     ee_tpow.numTargetPwr_11g
+#define        ee_trgtPwr_11g          ee_tpow.trgtPwr_11g
+#define        ee_numTargetPwr_11b     ee_tpow.numTargetPwr_11b
+#define        ee_trgtPwr_11b          ee_tpow.trgtPwr_11b
+#define        ee_modePowerArray5112   ee_u.eu_modePowerArray5112
+#define        ee_rawDataset2413       ee_u.eu_rawDataset2413
+#endif /* _ATH_AH_EEPROM_V3_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_internal.h     2009-04-17 13:29:53.000000000 +0100
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_internal.h,v 1.2 2009/03/23 17:17:07 sborrill Exp $
+ */
+#ifndef _ATH_AH_INTERAL_H_
+#define _ATH_AH_INTERAL_H_
+/*
+ * Atheros Device Hardware Access Layer (HAL).
+ *
+ * Internal definitions.
+ */
+#define        AH_NULL 0
+#define        AH_MIN(a,b)     ((a)<(b)?(a):(b))
+#define        AH_MAX(a,b)     ((a)>(b)?(a):(b))
+
+#ifndef NBBY
+#define        NBBY    8                       /* number of bits/byte */
+#endif
+
+#ifndef roundup
+#define        roundup(x, y)   ((((x)+((y)-1))/(y))*(y))  /* to any y */
+#endif
+#ifndef howmany
+#define        howmany(x, y)   (((x)+((y)-1))/(y))
+#endif
+
+#ifndef offsetof
+#define        offsetof(type, field)   ((size_t)(&((type *)0)->field))
+#endif
+
+/*
+ * Remove const in a way that keeps the compiler happy.
+ * This works for gcc but may require other magic for
+ * other compilers (not sure where this should reside).
+ * Note that uintptr_t is C99.
+ */
+#ifndef __DECONST
+#define        __DECONST(type, var)    ((type)(unsigned long)(const void *)(var))
+#endif
+
+typedef struct {
+       uint16_t        start;          /* first register */
+       uint16_t        end;            /* ending register or zero */
+} HAL_REGRANGE;
+
+/*
+ * Transmit power scale factor.
+ *
+ * NB: This is not public because we want to discourage the use of
+ *     scaling; folks should use the tx power limit interface.
+ */
+typedef enum {
+       HAL_TP_SCALE_MAX        = 0,            /* no scaling (default) */
+       HAL_TP_SCALE_50         = 1,            /* 50% of max (-3 dBm) */
+       HAL_TP_SCALE_25         = 2,            /* 25% of max (-6 dBm) */
+       HAL_TP_SCALE_12         = 3,            /* 12% of max (-9 dBm) */
+       HAL_TP_SCALE_MIN        = 4,            /* min, but still on */
+} HAL_TP_SCALE;
+
+typedef enum {
+       HAL_CAP_RADAR           = 0,            /* Radar capability */
+       HAL_CAP_AR              = 1,            /* AR capability */
+} HAL_PHYDIAG_CAPS;
+
+/*
+ * Each chip or class of chips registers to offer support.
+ */
+struct ath_hal_chip {
+       const char      *name;
+       const char      *(*probe)(uint16_t vendorid, uint16_t devid);
+       struct ath_hal  *(*attach)(uint16_t devid, HAL_SOFTC,
+                           HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS *error);
+};
+#ifndef AH_CHIP
+#define        AH_CHIP(_name, _probe, _attach)                         \
+static struct ath_hal_chip name##_chip = {                     \
+       .name           = #_name,                               \
+       .probe          = _probe,                               \
+       .attach         = _attach                               \
+};                                                             \
+OS_DATA_SET(ah_chips, name##_chip)
+#endif
+
+/*
+ * Each RF backend registers to offer support; this is mostly
+ * used by multi-chip 5212 solutions.  Single-chip solutions
+ * have a fixed idea about which RF to use.
+ */
+struct ath_hal_rf {
+       const char      *name;
+       HAL_BOOL        (*probe)(struct ath_hal *ah);
+       HAL_BOOL        (*attach)(struct ath_hal *ah, HAL_STATUS *ecode);
+};
+#ifndef AH_RF
+#define        AH_RF(_name, _probe, _attach)                           \
+static struct ath_hal_rf _name##_rf = {                                \
+       .name           = __STRING(_name),                      \
+       .probe          = _probe,                               \
+       .attach         = _attach                               \
+};                                                             \
+OS_DATA_SET(ah_rfs, _name##_rf)
+#endif
+
+struct ath_hal_rf *ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode);
+
+/*
+ * Internal form of a HAL_CHANNEL.  Note that the structure
+ * must be defined such that you can cast references to a
+ * HAL_CHANNEL so don't shuffle the first two members.
+ */
+typedef struct {
+       uint32_t        channelFlags;
+       uint16_t        channel;        /* NB: must be first for casting */
+       uint8_t         privFlags;
+       int8_t          maxRegTxPower;
+       int8_t          maxTxPower;
+       int8_t          minTxPower;     /* as above... */
+
+       HAL_BOOL        bssSendHere;
+       uint8_t         gainI;
+       HAL_BOOL        iqCalValid;
+       uint8_t         calValid;               /* bitmask of cal types */
+       int8_t          iCoff;
+       int8_t          qCoff;
+       int16_t         rawNoiseFloor;
+       int16_t         noiseFloorAdjust;
+       int8_t          antennaMax;
+       uint32_t        regDmnFlags;            /* Flags for channel use in reg */
+       uint32_t        conformanceTestLimit;   /* conformance test limit from reg domain */
+       uint16_t        mainSpur;               /* cached spur value for this cahnnel */
+} HAL_CHANNEL_INTERNAL;
+
+typedef struct {
+       uint32_t        halChanSpreadSupport            : 1,
+                       halSleepAfterBeaconBroken       : 1,
+                       halCompressSupport              : 1,
+                       halBurstSupport                 : 1,
+                       halFastFramesSupport            : 1,
+                       halChapTuningSupport            : 1,
+                       halTurboGSupport                : 1,
+                       halTurboPrimeSupport            : 1,
+                       halMicAesCcmSupport             : 1,
+                       halMicCkipSupport               : 1,
+                       halMicTkipSupport               : 1,
+                       halTkipMicTxRxKeySupport        : 1,
+                       halCipherAesCcmSupport          : 1,
+                       halCipherCkipSupport            : 1,
+                       halCipherTkipSupport            : 1,
+                       halPSPollBroken                 : 1,
+                       halVEOLSupport                  : 1,
+                       halBssIdMaskSupport             : 1,
+                       halMcastKeySrchSupport          : 1,
+                       halTsfAddSupport                : 1,
+                       halChanHalfRate                 : 1,
+                       halChanQuarterRate              : 1,
+                       halHTSupport                    : 1,
+                       halRfSilentSupport              : 1,
+                       halHwPhyCounterSupport          : 1,
+                       halWowSupport                   : 1,
+                       halWowMatchPatternExact         : 1,
+                       halAutoSleepSupport             : 1,
+                       halFastCCSupport                : 1,
+                       halBtCoexSupport                : 1;
+       uint32_t        halRxStbcSupport                : 1,
+                       halTxStbcSupport                : 1,
+                       halGTTSupport                   : 1,
+                       halCSTSupport                   : 1,
+                       halRifsRxSupport                : 1,
+                       halRifsTxSupport                : 1,
+                       halExtChanDfsSupport            : 1,
+                       halForcePpmSupport              : 1,
+                       halEnhancedPmSupport            : 1,
+                       halMbssidAggrSupport            : 1;
+       uint32_t        halWirelessModes;
+       uint16_t        halTotalQueues;
+       uint16_t        halKeyCacheSize;
+       uint16_t        halLow5GhzChan, halHigh5GhzChan;
+       uint16_t        halLow2GhzChan, halHigh2GhzChan;
+       int             halTstampPrecision;
+       int             halRtsAggrLimit;
+       uint8_t         halTxChainMask;
+       uint8_t         halRxChainMask;
+       uint8_t         halNumGpioPins;
+       uint8_t         halNumAntCfg2GHz;
+       uint8_t         halNumAntCfg5GHz;
+} HAL_CAPABILITIES;
+
+/*
+ * The ``private area'' follows immediately after the ``public area''
+ * in the data structure returned by ath_hal_attach.  Private data are
+ * used by device-independent code such as the regulatory domain support.
+ * In general, code within the HAL should never depend on data in the
+ * public area.  Instead any public data needed internally should be
+ * shadowed here.
+ *
+ * When declaring a device-specific ath_hal data structure this structure
+ * is assumed to at the front; e.g.
+ *
+ *     struct ath_hal_5212 {
+ *             struct ath_hal_private  ah_priv;
+ *             ...
+ *     };
+ *
+ * It might be better to manage the method pointers in this structure
+ * using an indirect pointer to a read-only data structure but this would
+ * disallow class-style method overriding.
+ */
+struct ath_hal_private {
+       struct ath_hal  h;                      /* public area */
+
+       /* NB: all methods go first to simplify initialization */
+       HAL_BOOL        (*ah_getChannelEdges)(struct ath_hal*,
+                               uint16_t channelFlags,
+                               uint16_t *lowChannel, uint16_t *highChannel);
+       u_int           (*ah_getWirelessModes)(struct ath_hal*);
+       HAL_BOOL        (*ah_eepromRead)(struct ath_hal *, u_int off,
+                               uint16_t *data);
+       HAL_BOOL        (*ah_eepromWrite)(struct ath_hal *, u_int off,
+                               uint16_t data);
+       HAL_BOOL        (*ah_gpioCfgOutput)(struct ath_hal *, uint32_t gpio);
+       HAL_BOOL        (*ah_gpioCfgInput)(struct ath_hal *, uint32_t gpio);
+       uint32_t        (*ah_gpioGet)(struct ath_hal *, uint32_t gpio);
+       HAL_BOOL        (*ah_gpioSet)(struct ath_hal *,
+                               uint32_t gpio, uint32_t val);
+       void            (*ah_gpioSetIntr)(struct ath_hal*, u_int, uint32_t);
+       HAL_BOOL        (*ah_getChipPowerLimits)(struct ath_hal *,
+                               HAL_CHANNEL *, uint32_t);
+       int16_t         (*ah_getNfAdjust)(struct ath_hal *,
+                               const HAL_CHANNEL_INTERNAL*);
+       void            (*ah_getNoiseFloor)(struct ath_hal *,
+                               int16_t nfarray[]);
+
+       void            *ah_eeprom;             /* opaque EEPROM state */
+       uint16_t        ah_eeversion;           /* EEPROM version */
+       void            (*ah_eepromDetach)(struct ath_hal *);
+       HAL_STATUS      (*ah_eepromGet)(struct ath_hal *, int, void *);
+       HAL_BOOL        (*ah_eepromSet)(struct ath_hal *, int, int);
+       uint16_t        (*ah_getSpurChan)(struct ath_hal *, int, HAL_BOOL);
+       HAL_BOOL        (*ah_eepromDiag)(struct ath_hal *, int request,
+                           const void *args, uint32_t argsize,
+                           void **result, uint32_t *resultsize);
+
+       /*
+        * Device revision information.
+        */
+       uint16_t        ah_devid;               /* PCI device ID */
+       uint16_t        ah_subvendorid;         /* PCI subvendor ID */
+       uint32_t        ah_macVersion;          /* MAC version id */
+       uint16_t        ah_macRev;              /* MAC revision */
+       uint16_t        ah_phyRev;              /* PHY revision */
+       uint16_t        ah_analog5GhzRev;       /* 2GHz radio revision */
+       uint16_t        ah_analog2GhzRev;       /* 5GHz radio revision */
+
+
+       HAL_OPMODE      ah_opmode;              /* operating mode from reset */
+       HAL_CAPABILITIES ah_caps;               /* device capabilities */
+       uint32_t        ah_diagreg;             /* user-specified AR_DIAG_SW */
+       int16_t         ah_powerLimit;          /* tx power cap */
+       uint16_t        ah_maxPowerLevel;       /* calculated max tx power */
+       u_int           ah_tpScale;             /* tx power scale factor */
+       uint32_t        ah_11nCompat;           /* 11n compat controls */
+
+       /*
+        * State for regulatory domain handling.
+        */
+       HAL_REG_DOMAIN  ah_currentRD;           /* Current regulatory domain */
+       HAL_CTRY_CODE   ah_countryCode;         /* current country code */
+       HAL_CHANNEL_INTERNAL ah_channels[256];  /* calculated channel list */
+       u_int           ah_nchan;               /* valid channels in list */
+       HAL_CHANNEL_INTERNAL *ah_curchan;       /* current channel */
+
+       uint8_t         ah_coverageClass;       /* coverage class */
+       HAL_BOOL        ah_regdomainUpdate;     /* regdomain is updated? */
+       /*
+        * RF Silent handling; setup according to the EEPROM.
+        */
+       uint16_t        ah_rfsilent;            /* GPIO pin + polarity */
+       HAL_BOOL        ah_rfkillEnabled;       /* enable/disable RfKill */
+       /*
+        * Diagnostic support for discriminating HIUERR reports.
+        */
+       uint32_t        ah_fatalState[6];       /* AR_ISR+shadow regs */
+       int             ah_rxornIsFatal;        /* how to treat HAL_INT_RXORN */
+};
+
+#define        AH_PRIVATE(_ah) ((struct ath_hal_private *)(_ah))
+
+#define        ath_hal_getChannelEdges(_ah, _cf, _lc, _hc) \
+       AH_PRIVATE(_ah)->ah_getChannelEdges(_ah, _cf, _lc, _hc)
+#define        ath_hal_getWirelessModes(_ah) \
+       AH_PRIVATE(_ah)->ah_getWirelessModes(_ah)
+#define        ath_hal_eepromRead(_ah, _off, _data) \
+       AH_PRIVATE(_ah)->ah_eepromRead(_ah, _off, _data)
+#define        ath_hal_eepromWrite(_ah, _off, _data) \
+       AH_PRIVATE(_ah)->ah_eepromWrite(_ah, _off, _data)
+#define        ath_hal_gpioCfgOutput(_ah, _gpio) \
+       AH_PRIVATE(_ah)->ah_gpioCfgOutput(_ah, _gpio)
+#define        ath_hal_gpioCfgInput(_ah, _gpio) \
+       AH_PRIVATE(_ah)->ah_gpioCfgInput(_ah, _gpio)
+#define        ath_hal_gpioGet(_ah, _gpio) \
+       AH_PRIVATE(_ah)->ah_gpioGet(_ah, _gpio)
+#define        ath_hal_gpioSet(_ah, _gpio, _val) \
+       AH_PRIVATE(_ah)->ah_gpioGet(_ah, _gpio, _val)
+#define        ath_hal_gpioSetIntr(_ah, _gpio, _ilevel) \
+       AH_PRIVATE(_ah)->ah_gpioSetIntr(_ah, _gpio, _ilevel)
+#define        ath_hal_getpowerlimits(_ah, _chans, _nchan) \
+       AH_PRIVATE(_ah)->ah_getChipPowerLimits(_ah, _chans, _nchan)
+#define ath_hal_getNfAdjust(_ah, _c) \
+       AH_PRIVATE(_ah)->ah_getNfAdjust(_ah, _c)
+#define        ath_hal_getNoiseFloor(_ah, _nfArray) \
+       AH_PRIVATE(_ah)->ah_getNoiseFloor(_ah, _nfArray)
+
+#define        ath_hal_eepromDetach(_ah) \
+       AH_PRIVATE(_ah)->ah_eepromDetach(_ah)
+#define        ath_hal_eepromGet(_ah, _param, _val) \
+       AH_PRIVATE(_ah)->ah_eepromGet(_ah, _param, _val)
+#define        ath_hal_eepromSet(_ah, _param, _val) \
+       AH_PRIVATE(_ah)->ah_eepromSet(_ah, _param, _val)
+#define        ath_hal_eepromGetFlag(_ah, _param) \
+       (AH_PRIVATE(_ah)->ah_eepromGet(_ah, _param, AH_NULL) == HAL_OK)
+#define ath_hal_getSpurChan(_ah, _ix, _is2G) \
+       AH_PRIVATE(_ah)->ah_getSpurChan(_ah, _ix, _is2G)
+#define        ath_hal_eepromDiag(_ah, _request, _a, _asize, _r, _rsize) \
+       AH_PRIVATE(_ah)->ah_eepromDiag(_ah, _request, _a, _asize,  _r, _rsize)
+
+#if !defined(_NET_IF_IEEE80211_H_) && !defined(_NET80211__IEEE80211_H_)
+/*
+ * Stuff that would naturally come from _ieee80211.h
+ */
+#define        IEEE80211_ADDR_LEN              6
+
+#define        IEEE80211_WEP_KEYLEN                    5       /* 40bit */
+#define        IEEE80211_WEP_IVLEN                     3       /* 24bit */
+#define        IEEE80211_WEP_KIDLEN                    1       /* 1 octet */
+#define        IEEE80211_WEP_CRCLEN                    4       /* CRC-32 */
+
+#define        IEEE80211_CRC_LEN                       4
+
+#define        IEEE80211_MTU                           1500
+#define        IEEE80211_MAX_LEN                       (2300 + IEEE80211_CRC_LEN + \
+    (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN))
+
+enum {
+       IEEE80211_T_DS,                 /* direct sequence spread spectrum */
+       IEEE80211_T_FH,                 /* frequency hopping */
+       IEEE80211_T_OFDM,               /* frequency division multiplexing */
+       IEEE80211_T_TURBO,              /* high rate DS */
+       IEEE80211_T_HT,                 /* HT - full GI */
+};
+#define        IEEE80211_T_CCK IEEE80211_T_DS  /* more common nomenclatur */
+#endif /* _NET_IF_IEEE80211_H_ */
+
+/* NB: these are defined privately until XR support is announced */
+enum {
+       ATHEROS_T_XR    = IEEE80211_T_HT+1,     /* extended range */
+};
+
+#define HAL_TXQ_USE_LOCKOUT_BKOFF_DIS  0x00000001
+
+#define INIT_AIFS              2
+#define INIT_CWMIN             15
+#define INIT_CWMIN_11B         31
+#define INIT_CWMAX             1023
+#define INIT_SH_RETRY          10
+#define INIT_LG_RETRY          10
+#define INIT_SSH_RETRY         32
+#define INIT_SLG_RETRY         32
+
+typedef struct {
+       uint32_t        tqi_ver;                /* HAL TXQ verson */
+       HAL_TX_QUEUE    tqi_type;               /* hw queue type*/
+       HAL_TX_QUEUE_SUBTYPE tqi_subtype;       /* queue subtype, if applicable */
+       HAL_TX_QUEUE_FLAGS tqi_qflags;          /* queue flags */
+       uint32_t        tqi_priority;
+       uint32_t        tqi_aifs;               /* aifs */
+       uint32_t        tqi_cwmin;              /* cwMin */
+       uint32_t        tqi_cwmax;              /* cwMax */
+       uint16_t        tqi_shretry;            /* frame short retry limit */
+       uint16_t        tqi_lgretry;            /* frame long retry limit */
+       uint32_t        tqi_cbrPeriod;
+       uint32_t        tqi_cbrOverflowLimit;
+       uint32_t        tqi_burstTime;
+       uint32_t        tqi_readyTime;
+       uint32_t        tqi_physCompBuf;
+       uint32_t        tqi_intFlags;           /* flags for internal use */
+} HAL_TX_QUEUE_INFO;
+
+extern HAL_BOOL ath_hal_setTxQProps(struct ath_hal *ah,
+               HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo);
+extern HAL_BOOL ath_hal_getTxQProps(struct ath_hal *ah,
+               HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi);
+
+typedef enum {
+       HAL_ANI_PRESENT,                        /* is ANI support present */
+       HAL_ANI_NOISE_IMMUNITY_LEVEL,           /* set level */
+       HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,     /* enable/disable */
+       HAL_ANI_CCK_WEAK_SIGNAL_THR,            /* enable/disable */
+       HAL_ANI_FIRSTEP_LEVEL,                  /* set level */
+       HAL_ANI_SPUR_IMMUNITY_LEVEL,            /* set level */
+       HAL_ANI_MODE = 6,       /* 0 => manual, 1 => auto (XXX do not change) */
+       HAL_ANI_PHYERR_RESET,                   /* reset phy error stats */
+} HAL_ANI_CMD;
+
+#define        HAL_SPUR_VAL_MASK               0x3FFF
+#define        HAL_SPUR_CHAN_WIDTH             87
+#define        HAL_BIN_WIDTH_BASE_100HZ        3125
+#define        HAL_BIN_WIDTH_TURBO_100HZ       6250
+#define        HAL_MAX_BINS_ALLOWED            28
+
+/*
+ * A    = 5GHZ|OFDM
+ * T    = 5GHZ|OFDM|TURBO
+ *
+ * IS_CHAN_A(T) will return TRUE.  This is probably
+ * not the default behavior we want.  We should migrate to a better mask --
+ * perhaps CHANNEL_ALL.
+ *
+ * For now, IS_CHAN_G() masks itself with CHANNEL_108G.
+ *
+ */
+
+#define        IS_CHAN_A(_c)   (((_c)->channelFlags & CHANNEL_A) == CHANNEL_A)
+#define        IS_CHAN_B(_c)   (((_c)->channelFlags & CHANNEL_B) == CHANNEL_B)
+#define        IS_CHAN_G(_c)   (((_c)->channelFlags & (CHANNEL_108G|CHANNEL_G)) == CHANNEL_G)
+#define        IS_CHAN_108G(_c)(((_c)->channelFlags & CHANNEL_108G) == CHANNEL_108G)
+#define        IS_CHAN_T(_c)   (((_c)->channelFlags & CHANNEL_T) == CHANNEL_T)
+#define        IS_CHAN_PUREG(_c) \
+       (((_c)->channelFlags & CHANNEL_PUREG) == CHANNEL_PUREG)
+
+#define        IS_CHAN_TURBO(_c)       (((_c)->channelFlags & CHANNEL_TURBO) != 0)
+#define        IS_CHAN_CCK(_c)         (((_c)->channelFlags & CHANNEL_CCK) != 0)
+#define        IS_CHAN_OFDM(_c)        (((_c)->channelFlags & CHANNEL_OFDM) != 0)
+#define        IS_CHAN_5GHZ(_c)        (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
+#define        IS_CHAN_2GHZ(_c)        (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
+#define        IS_CHAN_PASSIVE(_c)     (((_c)->channelFlags & CHANNEL_PASSIVE) != 0)
+#define        IS_CHAN_HALF_RATE(_c)   (((_c)->channelFlags & CHANNEL_HALF) != 0)
+#define        IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
+
+#define        IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990)
+
+#define        CHANNEL_HT40            (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)
+#define        CHANNEL_HT              (CHANNEL_HT20 | CHANNEL_HT40)
+#define        IS_CHAN_HT(_c)          (((_c)->channelFlags & CHANNEL_HT) != 0)
+#define        IS_CHAN_HT20(_c)        (((_c)->channelFlags & CHANNEL_HT) == CHANNEL_HT20)
+#define        IS_CHAN_HT40(_c)        (((_c)->channelFlags & CHANNEL_HT40) != 0)
+
+/*
+ * Deduce if the host cpu has big- or litt-endian byte order.
+ */
+static __inline__ int
+isBigEndian(void)
+{
+       union {
+               int32_t i;
+               char c[4];
+       } u;
+       u.i = 1;
+       return (u.c[0] == 0);
+}
+
+/* unalligned little endian access */
+#define LE_READ_2(p)                                                   \
+       ((uint16_t)                                                     \
+        ((((const uint8_t *)(p))[0]    ) | (((const uint8_t *)(p))[1]<< 8)))
+#define LE_READ_4(p)                                                   \
+       ((uint32_t)                                                     \
+        ((((const uint8_t *)(p))[0]    ) | (((const uint8_t *)(p))[1]<< 8) |\
+         (((const uint8_t *)(p))[2]<<16) | (((const uint8_t *)(p))[3]<<24)))
+
+/*
+ * Register manipulation macros that expect bit field defines
+ * to follow the convention that an _S suffix is appended for
+ * a shift count, while the field mask has no suffix.
+ */
+#define        SM(_v, _f)      (((_v) << _f##_S) & (_f))
+#define        MS(_v, _f)      (((_v) & (_f)) >> _f##_S)
+#define        OS_REG_RMW_FIELD(_a, _r, _f, _v) \
+       OS_REG_WRITE(_a, _r, \
+               (OS_REG_READ(_a, _r) &~ (_f)) | (((_v) << _f##_S) & (_f)))
+#define        OS_REG_SET_BIT(_a, _r, _f) \
+       OS_REG_WRITE(_a, _r, OS_REG_READ(_a, _r) | (_f))
+#define        OS_REG_CLR_BIT(_a, _r, _f) \
+       OS_REG_WRITE(_a, _r, OS_REG_READ(_a, _r) &~ (_f))
+
+/*
+ * Regulatory domain support.
+ */
+
+/*
+ * Return the max allowed antenna gain based on the current
+ * regulatory domain.
+ */
+extern u_int ath_hal_getantennareduction(struct ath_hal *,
+               HAL_CHANNEL *, u_int twiceGain);
+/*
+ * Return the test group for the specific channel based on
+ * the current regulator domain.
+ */
+extern u_int ath_hal_getctl(struct ath_hal *, HAL_CHANNEL *);
+/*
+ * Return whether or not a noise floor check is required
+ * based on the current regulatory domain for the specified
+ * channel.
+ */
+extern u_int ath_hal_getnfcheckrequired(struct ath_hal *, HAL_CHANNEL *);
+
+/*
+ * Map a public channel definition to the corresponding
+ * internal data structure.  This implicitly specifies
+ * whether or not the specified channel is ok to use
+ * based on the current regulatory domain constraints.
+ */
+extern HAL_CHANNEL_INTERNAL *ath_hal_checkchannel(struct ath_hal *,
+               const HAL_CHANNEL *);
+
+/* system-configurable parameters */
+extern int ath_hal_dma_beacon_response_time;   /* in TU's */
+extern int ath_hal_sw_beacon_response_time;    /* in TU's */
+extern int ath_hal_additional_swba_backoff;    /* in TU's */
+
+/* wait for the register contents to have the specified value */
+extern HAL_BOOL ath_hal_wait(struct ath_hal *, u_int reg,
+               uint32_t mask, uint32_t val);
+
+/* return the first n bits in val reversed */
+extern uint32_t ath_hal_reverseBits(uint32_t val, uint32_t n);
+
+/* printf interfaces */
+extern void ath_hal_printf(struct ath_hal *, const char*, ...);
+extern void ath_hal_vprintf(struct ath_hal *, const char*, va_list);
+extern const char* ath_hal_ether_sprintf(const uint8_t *mac);
+
+/* allocate and free memory */
+extern void *ath_hal_malloc(size_t);
+extern void ath_hal_free(void *);
+
+/* common debugging interfaces */
+#ifdef AH_DEBUG
+#include "ah_debug.h"
+extern int ath_hal_debug;
+extern void HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...);
+#else
+#define HALDEBUG(_ah, __m, _fmt, ...)
+#endif /* AH_DEBUG */
+
+/*
+ * Register logging definitions shared with ardecode.
+ */
+#include "ah_decode.h"
+
+/*
+ * Common assertion interface.  Note: it is a bad idea to generate
+ * an assertion failure for any recoverable event.  Instead catch
+ * the violation and, if possible, fix it up or recover from it; either
+ * with an error return value or a diagnostic messages.  System software
+ * does not panic unless the situation is hopeless.
+ */
+#ifdef AH_ASSERT
+extern void ath_hal_assert_failed(const char* filename,
+               int lineno, const char* msg);
+
+#define        HALASSERT(_x) do {                                      \
+       if (!(_x)) {                                            \
+               ath_hal_assert_failed(__FILE__, __LINE__, #_x); \
+       }                                                       \
+} while (0)
+#else
+#define        HALASSERT(_x)
+#endif /* AH_ASSERT */
+
+/*
+ * Convert between microseconds and core system clocks.
+ */
+extern u_int ath_hal_mac_clks(struct ath_hal *ah, u_int usecs);
+extern u_int ath_hal_mac_usec(struct ath_hal *ah, u_int clks);
+
+/*
+ * Generic get/set capability support.  Each chip overrides
+ * this routine to support chip-specific capabilities.
+ */
+extern HAL_STATUS ath_hal_getcapability(struct ath_hal *ah,
+               HAL_CAPABILITY_TYPE type, uint32_t capability,
+               uint32_t *result);
+extern HAL_BOOL ath_hal_setcapability(struct ath_hal *ah,
+               HAL_CAPABILITY_TYPE type, uint32_t capability,
+               uint32_t setting, HAL_STATUS *status);
+
+/*
+ * Diagnostic interface.  This is an open-ended interface that
+ * is opaque to applications.  Diagnostic programs use this to
+ * retrieve internal data structures, etc.  There is no guarantee
+ * that calling conventions for calls other than HAL_DIAG_REVS
+ * are stable between HAL releases; a diagnostic application must
+ * use the HAL revision information to deal with ABI/API differences.
+ *
+ * NB: do not renumber these, certain codes are publicly used.
+ */
+enum {
+       HAL_DIAG_REVS           = 0,    /* MAC/PHY/Radio revs */
+       HAL_DIAG_EEPROM         = 1,    /* EEPROM contents */
+       HAL_DIAG_EEPROM_EXP_11A = 2,    /* EEPROM 5112 power exp for 11a */
+       HAL_DIAG_EEPROM_EXP_11B = 3,    /* EEPROM 5112 power exp for 11b */
+       HAL_DIAG_EEPROM_EXP_11G = 4,    /* EEPROM 5112 power exp for 11g */
+       HAL_DIAG_ANI_CURRENT    = 5,    /* ANI current channel state */
+       HAL_DIAG_ANI_OFDM       = 6,    /* ANI OFDM timing error stats */
+       HAL_DIAG_ANI_CCK        = 7,    /* ANI CCK timing error stats */
+       HAL_DIAG_ANI_STATS      = 8,    /* ANI statistics */
+       HAL_DIAG_RFGAIN         = 9,    /* RfGain GAIN_VALUES */
+       HAL_DIAG_RFGAIN_CURSTEP = 10,   /* RfGain GAIN_OPTIMIZATION_STEP */
+       HAL_DIAG_PCDAC          = 11,   /* PCDAC table */
+       HAL_DIAG_TXRATES        = 12,   /* Transmit rate table */
+       HAL_DIAG_REGS           = 13,   /* Registers */
+       HAL_DIAG_ANI_CMD        = 14,   /* ANI issue command (XXX do not change!) */
+       HAL_DIAG_SETKEY         = 15,   /* Set keycache backdoor */
+       HAL_DIAG_RESETKEY       = 16,   /* Reset keycache backdoor */
+       HAL_DIAG_EEREAD         = 17,   /* Read EEPROM word */
+       HAL_DIAG_EEWRITE        = 18,   /* Write EEPROM word */
+       /* 19 was HAL_DIAG_TXCONT, 20-23 were for radar */
+       HAL_DIAG_REGREAD        = 24,   /* Reg reads */
+       HAL_DIAG_REGWRITE       = 25,   /* Reg writes */
+       HAL_DIAG_GET_REGBASE    = 26,   /* Get register base */
+       HAL_DIAG_RDWRITE        = 27,   /* Write regulatory domain */
+       HAL_DIAG_RDREAD         = 28,   /* Get regulatory domain */
+       HAL_DIAG_FATALERR       = 29,   /* Read cached interrupt state */
+       HAL_DIAG_11NCOMPAT      = 30,   /* 11n compatibility tweaks */
+       HAL_DIAG_ANI_PARAMS     = 31,   /* ANI noise immunity parameters */
+       HAL_DIAG_CHECK_HANGS    = 32,   /* check h/w hangs */
+};
+
+enum {
+    HAL_BB_HANG_DFS            = 0x0001,
+    HAL_BB_HANG_RIFS           = 0x0002,
+    HAL_BB_HANG_RX_CLEAR       = 0x0004,
+    HAL_BB_HANG_UNKNOWN                = 0x0080,
+
+    HAL_MAC_HANG_SIG1          = 0x0100,
+    HAL_MAC_HANG_SIG2          = 0x0200,
+    HAL_MAC_HANG_UNKNOWN       = 0x8000,
+
+    HAL_BB_HANGS = HAL_BB_HANG_DFS
+                | HAL_BB_HANG_RIFS
+                | HAL_BB_HANG_RX_CLEAR
+                | HAL_BB_HANG_UNKNOWN,
+    HAL_MAC_HANGS = HAL_MAC_HANG_SIG1
+                | HAL_MAC_HANG_SIG2
+                | HAL_MAC_HANG_UNKNOWN,
+};
+
+/*
+ * Device revision information.
+ */
+typedef struct {
+       uint16_t        ah_devid;               /* PCI device ID */
+       uint16_t        ah_subvendorid;         /* PCI subvendor ID */
+       uint32_t        ah_macVersion;          /* MAC version id */
+       uint16_t        ah_macRev;              /* MAC revision */
+       uint16_t        ah_phyRev;              /* PHY revision */
+       uint16_t        ah_analog5GhzRev;       /* 2GHz radio revision */
+       uint16_t        ah_analog2GhzRev;       /* 5GHz radio revision */
+} HAL_REVS;
+
+/*
+ * Argument payload for HAL_DIAG_SETKEY.
+ */
+typedef struct {
+       HAL_KEYVAL      dk_keyval;
+       uint16_t        dk_keyix;       /* key index */
+       uint8_t         dk_mac[IEEE80211_ADDR_LEN];
+       int             dk_xor;         /* XOR key data */
+} HAL_DIAG_KEYVAL;
+
+/*
+ * Argument payload for HAL_DIAG_EEWRITE.
+ */
+typedef struct {
+       uint16_t        ee_off;         /* eeprom offset */
+       uint16_t        ee_data;        /* write data */
+} HAL_DIAG_EEVAL;
+
+
+typedef struct {
+       u_int offset;           /* reg offset */
+       uint32_t val;           /* reg value  */
+} HAL_DIAG_REGVAL;
+
+/*
+ * 11n compatibility tweaks.
+ */
+#define        HAL_DIAG_11N_SERVICES   0x00000003
+#define        HAL_DIAG_11N_SERVICES_S 0
+#define        HAL_DIAG_11N_TXSTOMP    0x0000000c
+#define        HAL_DIAG_11N_TXSTOMP_S  2
+
+typedef struct {
+       int             maxNoiseImmunityLevel;  /* [0..4] */
+       int             totalSizeDesired[5];
+       int             coarseHigh[5];
+       int             coarseLow[5];
+       int             firpwr[5];
+
+       int             maxSpurImmunityLevel;   /* [0..7] */
+       int             cycPwrThr1[8];
+
+       int             maxFirstepLevel;        /* [0..2] */
+       int             firstep[3];
+
+       uint32_t        ofdmTrigHigh;
+       uint32_t        ofdmTrigLow;
+       int32_t         cckTrigHigh;
+       int32_t         cckTrigLow;
+       int32_t         rssiThrLow;
+       int32_t         rssiThrHigh;
+
+       int             period;                 /* update listen period */
+} HAL_ANI_PARAMS;
+
+extern HAL_BOOL ath_hal_getdiagstate(struct ath_hal *ah, int request,
+                       const void *args, uint32_t argsize,
+                       void **result, uint32_t *resultsize);
+
+/*
+ * Setup a h/w rate table for use.
+ */
+extern void ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt);
+
+/*
+ * Common routine for implementing getChanNoise api.
+ */
+extern int16_t ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan);
+
+/*
+ * Initialization support.
+ */
+typedef struct {
+       const uint32_t  *data;
+       int             rows, cols;
+} HAL_INI_ARRAY;
+
+#define        HAL_INI_INIT(_ia, _data, _cols) do {                    \
+       (_ia)->data = (const uint32_t *)(_data);                \
+       (_ia)->rows = sizeof(_data) / sizeof((_data)[0]);       \
+       (_ia)->cols = (_cols);                                  \
+} while (0)
+#define        HAL_INI_VAL(_ia, _r, _c) \
+       ((_ia)->data[((_r)*(_ia)->cols) + (_c)])
+
+/*
+ * OS_DELAY() does a PIO READ on the PCI bus which allows
+ * other cards' DMA reads to complete in the middle of our reset.
+ */
+#define DMA_YIELD(x) do {              \
+       if ((++(x) % 64) == 0)          \
+               OS_DELAY(1);            \
+} while (0)
+
+#define HAL_INI_WRITE_ARRAY(ah, regArray, col, regWr) do {                     \
+       int r;                                                          \
+       for (r = 0; r < N(regArray); r++) {                             \
+               OS_REG_WRITE(ah, (regArray)[r][0], (regArray)[r][col]); \
+               DMA_YIELD(regWr);                                       \
+       }                                                               \
+} while (0)
+
+#define HAL_INI_WRITE_BANK(ah, regArray, bankData, regWr) do {         \
+       int r;                                                          \
+       for (r = 0; r < N(regArray); r++) {                             \
+               OS_REG_WRITE(ah, (regArray)[r][0], (bankData)[r]);      \
+               DMA_YIELD(regWr);                                       \
+       }                                                               \
+} while (0)
+
+extern int ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
+               int col, int regWr);
+extern void ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia,
+               int col);
+extern int ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
+               const uint32_t data[], int regWr);
+
+#define        WLAN_CTRL_FRAME_SIZE    (2+2+6+4)       /* ACK+FCS */
+#endif /* _ATH_AH_INTERAL_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_regdomain.c    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,2861 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2005-2006 Atheros Communications, Inc.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_regdomain.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_eeprom.h"
+#include "ah_devid.h"
+
+/*
+ * XXX this code needs a audit+review
+ */
+
+/* used throughout this file... */
+#define        N(a)    (sizeof (a) / sizeof (a[0]))
+
+#define HAL_MODE_11A_TURBO     HAL_MODE_108A
+#define HAL_MODE_11G_TURBO     HAL_MODE_108G
+
+/* 10MHz is half the 11A bandwidth used to determine upper edge freq
+   of the outdoor channel */
+#define HALF_MAXCHANBW         10
+
+/*
+ * BMLEN defines the size of the bitmask used to hold frequency
+ * band specifications.  Note this must agree with the BM macro
+ * definition that's used to setup initializers.  See also further
+ * comments below.
+ */
+#define BMLEN 2                /* 2 x 64 bits in each channel bitmask */
+typedef uint64_t chanbmask_t[BMLEN];
+
+#define        W0(_a) \
+       (((_a) >= 0 && (_a) < 64 ? (((uint64_t) 1)<<(_a)) : (uint64_t) 0))
+#define        W1(_a) \
+       (((_a) > 63 && (_a) < 128 ? (((uint64_t) 1)<<((_a)-64)) : (uint64_t) 0))
+#define BM1(_fa)       { W0(_fa), W1(_fa) }
+#define BM2(_fa, _fb)  { W0(_fa) | W0(_fb), W1(_fa) | W1(_fb) }
+#define BM3(_fa, _fb, _fc) \
+       { W0(_fa) | W0(_fb) | W0(_fc), W1(_fa) | W1(_fb) | W1(_fc) }
+#define BM4(_fa, _fb, _fc, _fd)                                                \
+       { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd),                        \
+         W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) }
+#define BM5(_fa, _fb, _fc, _fd, _fe)                                   \
+       { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe),              \
+         W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) }
+#define BM6(_fa, _fb, _fc, _fd, _fe, _ff)                              \
+       { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff),    \
+         W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) }
+#define BM7(_fa, _fb, _fc, _fd, _fe, _ff, _fg) \
+       { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) |   \
+         W0(_fg),\
+         W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) |   \
+         W1(_fg) }
+#define BM8(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh)    \
+       { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) |   \
+         W0(_fg) | W0(_fh) ,   \
+         W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) |   \
+         W1(_fg) | W1(_fh) }
+
+/*
+ * Country/Region Codes
+ * Numbering from ISO 3166
+ */
+enum {
+    CTRY_ALBANIA              = 8,       /* Albania */
+    CTRY_ALGERIA              = 12,      /* Algeria */
+    CTRY_ARGENTINA            = 32,      /* Argentina */
+    CTRY_ARMENIA              = 51,      /* Armenia */
+    CTRY_AUSTRALIA            = 36,      /* Australia */
+    CTRY_AUSTRIA              = 40,      /* Austria */
+    CTRY_AZERBAIJAN           = 31,      /* Azerbaijan */
+    CTRY_BAHRAIN              = 48,      /* Bahrain */
+    CTRY_BELARUS              = 112,     /* Belarus */
+    CTRY_BELGIUM              = 56,      /* Belgium */
+    CTRY_BELIZE               = 84,      /* Belize */
+    CTRY_BOLIVIA              = 68,      /* Bolivia */
+    CTRY_BRAZIL               = 76,      /* Brazil */
+    CTRY_BRUNEI_DARUSSALAM    = 96,      /* Brunei Darussalam */
+    CTRY_BULGARIA             = 100,     /* Bulgaria */
+    CTRY_CANADA               = 124,     /* Canada */
+    CTRY_CHILE                = 152,     /* Chile */
+    CTRY_CHINA                = 156,     /* People's Republic of China */
+    CTRY_COLOMBIA             = 170,     /* Colombia */
+    CTRY_COSTA_RICA           = 188,     /* Costa Rica */
+    CTRY_CROATIA              = 191,     /* Croatia */
+    CTRY_CYPRUS               = 196,
+    CTRY_CZECH                = 203,     /* Czech Republic */
+    CTRY_DENMARK              = 208,     /* Denmark */
+    CTRY_DOMINICAN_REPUBLIC   = 214,     /* Dominican Republic */
+    CTRY_ECUADOR              = 218,     /* Ecuador */
+    CTRY_EGYPT                = 818,     /* Egypt */
+    CTRY_EL_SALVADOR          = 222,     /* El Salvador */
+    CTRY_ESTONIA              = 233,     /* Estonia */
+    CTRY_FAEROE_ISLANDS       = 234,     /* Faeroe Islands */
+    CTRY_FINLAND              = 246,     /* Finland */
+    CTRY_FRANCE               = 250,     /* France */
+    CTRY_FRANCE2              = 255,     /* France2 */
+    CTRY_GEORGIA              = 268,     /* Georgia */
+    CTRY_GERMANY              = 276,     /* Germany */
+    CTRY_GREECE               = 300,     /* Greece */
+    CTRY_GUATEMALA            = 320,     /* Guatemala */
+    CTRY_HONDURAS             = 340,     /* Honduras */
+    CTRY_HONG_KONG            = 344,     /* Hong Kong S.A.R., P.R.C. */
+    CTRY_HUNGARY              = 348,     /* Hungary */
+    CTRY_ICELAND              = 352,     /* Iceland */
+    CTRY_INDIA                = 356,     /* India */
+    CTRY_INDONESIA            = 360,     /* Indonesia */
+    CTRY_IRAN                 = 364,     /* Iran */
+    CTRY_IRAQ                 = 368,     /* Iraq */
+    CTRY_IRELAND              = 372,     /* Ireland */
+    CTRY_ISRAEL               = 376,     /* Israel */
+    CTRY_ITALY                = 380,     /* Italy */
+    CTRY_JAMAICA              = 388,     /* Jamaica */
+    CTRY_JAPAN                = 392,     /* Japan */
+    CTRY_JAPAN1               = 393,     /* Japan (JP1) */
+    CTRY_JAPAN2               = 394,     /* Japan (JP0) */
+    CTRY_JAPAN3               = 395,     /* Japan (JP1-1) */
+    CTRY_JAPAN4               = 396,     /* Japan (JE1) */
+    CTRY_JAPAN5               = 397,     /* Japan (JE2) */
+    CTRY_JAPAN6               = 399,     /* Japan (JP6) */
+
+    CTRY_JAPAN7                      = 4007,    /* Japan (J7) */
+    CTRY_JAPAN8                      = 4008,    /* Japan (J8) */
+    CTRY_JAPAN9                      = 4009,    /* Japan (J9) */
+
+    CTRY_JAPAN10             = 4010,    /* Japan (J10) */
+    CTRY_JAPAN11             = 4011,    /* Japan (J11) */
+    CTRY_JAPAN12             = 4012,    /* Japan (J12) */
+
+    CTRY_JAPAN13             = 4013,    /* Japan (J13) */
+    CTRY_JAPAN14             = 4014,    /* Japan (J14) */
+    CTRY_JAPAN15             = 4015,    /* Japan (J15) */
+
+    CTRY_JAPAN16             = 4016,    /* Japan (J16) */
+    CTRY_JAPAN17             = 4017,    /* Japan (J17) */
+    CTRY_JAPAN18             = 4018,    /* Japan (J18) */
+
+    CTRY_JAPAN19             = 4019,    /* Japan (J19) */
+    CTRY_JAPAN20             = 4020,    /* Japan (J20) */
+    CTRY_JAPAN21             = 4021,    /* Japan (J21) */
+
+    CTRY_JAPAN22             = 4022,    /* Japan (J22) */
+    CTRY_JAPAN23             = 4023,    /* Japan (J23) */
+    CTRY_JAPAN24             = 4024,    /* Japan (J24) */
+
+    CTRY_JORDAN               = 400,     /* Jordan */
+    CTRY_KAZAKHSTAN           = 398,     /* Kazakhstan */
+    CTRY_KENYA                = 404,     /* Kenya */
+    CTRY_KOREA_NORTH          = 408,     /* North Korea */
+    CTRY_KOREA_ROC            = 410,     /* South Korea */
+    CTRY_KOREA_ROC2           = 411,     /* South Korea */
+    CTRY_KOREA_ROC3           = 412,     /* South Korea */
+    CTRY_KUWAIT               = 414,     /* Kuwait */
+    CTRY_LATVIA               = 428,     /* Latvia */
+    CTRY_LEBANON              = 422,     /* Lebanon */
+    CTRY_LIBYA                = 434,     /* Libya */
+    CTRY_LIECHTENSTEIN        = 438,     /* Liechtenstein */
+    CTRY_LITHUANIA            = 440,     /* Lithuania */
+    CTRY_LUXEMBOURG           = 442,     /* Luxembourg */
+    CTRY_MACAU                = 446,     /* Macau */
+    CTRY_MACEDONIA            = 807,     /* the Former Yugoslav Republic of Macedonia */
+    CTRY_MALAYSIA             = 458,     /* Malaysia */
+    CTRY_MALTA               = 470,     /* Malta */
+    CTRY_MEXICO               = 484,     /* Mexico */
+    CTRY_MONACO               = 492,     /* Principality of Monaco */
+    CTRY_MOROCCO              = 504,     /* Morocco */
+    CTRY_NETHERLANDS          = 528,     /* Netherlands */
+    CTRY_NEW_ZEALAND          = 554,     /* New Zealand */
+    CTRY_NICARAGUA            = 558,     /* Nicaragua */
+    CTRY_NORWAY               = 578,     /* Norway */
+    CTRY_OMAN                 = 512,     /* Oman */
+    CTRY_PAKISTAN             = 586,     /* Islamic Republic of Pakistan */
+    CTRY_PANAMA               = 591,     /* Panama */
+    CTRY_PARAGUAY             = 600,     /* Paraguay */
+    CTRY_PERU                 = 604,     /* Peru */
+    CTRY_PHILIPPINES          = 608,     /* Republic of the Philippines */
+    CTRY_POLAND               = 616,     /* Poland */
+    CTRY_PORTUGAL             = 620,     /* Portugal */
+    CTRY_PUERTO_RICO          = 630,     /* Puerto Rico */
+    CTRY_QATAR                = 634,     /* Qatar */
+    CTRY_ROMANIA              = 642,     /* Romania */
+    CTRY_RUSSIA               = 643,     /* Russia */
+    CTRY_SAUDI_ARABIA         = 682,     /* Saudi Arabia */
+    CTRY_SINGAPORE            = 702,     /* Singapore */
+    CTRY_SLOVAKIA             = 703,     /* Slovak Republic */
+    CTRY_SLOVENIA             = 705,     /* Slovenia */
+    CTRY_SOUTH_AFRICA         = 710,     /* South Africa */
+    CTRY_SPAIN                = 724,     /* Spain */
+    CTRY_SR9                  = 5000,    /* Ubiquiti SR9 (900MHz/GSM) */
+    CTRY_SWEDEN               = 752,     /* Sweden */
+    CTRY_SWITZERLAND          = 756,     /* Switzerland */
+    CTRY_SYRIA                = 760,     /* Syria */
+    CTRY_TAIWAN               = 158,     /* Taiwan */
+    CTRY_THAILAND             = 764,     /* Thailand */
+    CTRY_TRINIDAD_Y_TOBAGO    = 780,     /* Trinidad y Tobago */
+    CTRY_TUNISIA              = 788,     /* Tunisia */
+    CTRY_TURKEY               = 792,     /* Turkey */
+    CTRY_UAE                  = 784,     /* U.A.E. */
+    CTRY_UKRAINE              = 804,     /* Ukraine */
+    CTRY_UNITED_KINGDOM       = 826,     /* United Kingdom */
+    CTRY_UNITED_STATES        = 840,     /* United States */
+    CTRY_UNITED_STATES_FCC49  = 842,     /* United States (Public Safety)*/
+    CTRY_URUGUAY              = 858,     /* Uruguay */
+    CTRY_UZBEKISTAN           = 860,     /* Uzbekistan */
+    CTRY_VENEZUELA            = 862,     /* Venezuela */
+    CTRY_VIET_NAM             = 704,     /* Viet Nam */
+    CTRY_XR9                  = 5001,    /* Ubiquiti XR9 (900MHz/GSM) */
+    CTRY_GZ901                = 5002,    /* Zcomax GZ-901 (900MHz/GSM) */
+    CTRY_YEMEN                = 887,     /* Yemen */
+    CTRY_ZIMBABWE             = 716      /* Zimbabwe */
+};
+
+
+/*
+ * Mask to check whether a domain is a multidomain or a single domain
+ */
+#define MULTI_DOMAIN_MASK 0xFF00
+
+/*
+ * Enumerated Regulatory Domain Information 8 bit values indicate that
+ * the regdomain is really a pair of unitary regdomains.  12 bit values
+ * are the real unitary regdomains and are the only ones which have the
+ * frequency bitmasks and flags set.
+ */
+enum {
+       /*
+        * The following regulatory domain definitions are
+        * found in the EEPROM. Each regulatory domain
+        * can operate in either a 5GHz or 2.4GHz wireless mode or
+        * both 5GHz and 2.4GHz wireless modes.
+        * In general, the value holds no special
+        * meaning and is used to decode into either specific
+        * 2.4GHz or 5GHz wireless mode for that particular
+        * regulatory domain.
+        */
+       NO_ENUMRD       = 0x00,
+       NULL1_WORLD     = 0x03,         /* For 11b-only countries (no 11a allowed) */
+       NULL1_ETSIB     = 0x07,         /* Israel */
+       NULL1_ETSIC     = 0x08,
+       FCC1_FCCA       = 0x10,         /* USA */
+       FCC1_WORLD      = 0x11,         /* Hong Kong */
+       FCC4_FCCA       = 0x12,         /* USA - Public Safety */
+       FCC5_FCCB       = 0x13,         /* USA w/ 1/2 and 1/4 width channels */
+
+       FCC2_FCCA       = 0x20,         /* Canada */
+       FCC2_WORLD      = 0x21,         /* Australia & HK */
+       FCC2_ETSIC      = 0x22,
+       FRANCE_RES      = 0x31,         /* Legacy France for OEM */
+       FCC3_FCCA       = 0x3A,         /* USA & Canada w/5470 band, 11h, DFS enabled */
+       FCC3_WORLD      = 0x3B,         /* USA & Canada w/5470 band, 11h, DFS enabled */
+
+       ETSI1_WORLD     = 0x37,
+       ETSI3_ETSIA     = 0x32,         /* France (optional) */
+       ETSI2_WORLD     = 0x35,         /* Hungary & others */
+       ETSI3_WORLD     = 0x36,         /* France & others */
+       ETSI4_WORLD     = 0x30,
+       ETSI4_ETSIC     = 0x38,
+       ETSI5_WORLD     = 0x39,
+       ETSI6_WORLD     = 0x34,         /* Bulgaria */
+       ETSI_RESERVED   = 0x33,         /* Reserved (Do not used) */
+
+       MKK1_MKKA       = 0x40,         /* Japan (JP1) */
+       MKK1_MKKB       = 0x41,         /* Japan (JP0) */
+       APL4_WORLD      = 0x42,         /* Singapore */
+       MKK2_MKKA       = 0x43,         /* Japan with 4.9G channels */
+       APL_RESERVED    = 0x44,         /* Reserved (Do not used)  */
+       APL2_WORLD      = 0x45,         /* Korea */
+       APL2_APLC       = 0x46,
+       APL3_WORLD      = 0x47,
+       MKK1_FCCA       = 0x48,         /* Japan (JP1-1) */
+       APL2_APLD       = 0x49,         /* Korea with 2.3G channels */
+       MKK1_MKKA1      = 0x4A,         /* Japan (JE1) */
+       MKK1_MKKA2      = 0x4B,         /* Japan (JE2) */
+       MKK1_MKKC       = 0x4C,         /* Japan (MKK1_MKKA,except Ch14) */
+
+       APL3_FCCA       = 0x50,
+       APL1_WORLD      = 0x52,         /* Latin America */
+       APL1_FCCA       = 0x53,
+       APL1_APLA       = 0x54,
+       APL1_ETSIC      = 0x55,
+       APL2_ETSIC      = 0x56,         /* Venezuela */
+       APL5_WORLD      = 0x58,         /* Chile */
+       APL6_WORLD      = 0x5B,         /* Singapore */
+       APL7_FCCA   = 0x5C,     /* Taiwan 5.47 Band */
+       APL8_WORLD  = 0x5D,     /* Malaysia 5GHz */
+       APL9_WORLD  = 0x5E,     /* Korea 5GHz */
+
+       /*
+        * World mode SKUs
+        */
+       WOR0_WORLD      = 0x60,         /* World0 (WO0 SKU) */
+       WOR1_WORLD      = 0x61,         /* World1 (WO1 SKU) */
+       WOR2_WORLD      = 0x62,         /* World2 (WO2 SKU) */
+       WOR3_WORLD      = 0x63,         /* World3 (WO3 SKU) */
+       WOR4_WORLD      = 0x64,         /* World4 (WO4 SKU) */
+       WOR5_ETSIC      = 0x65,         /* World5 (WO5 SKU) */
+
+       WOR01_WORLD     = 0x66,         /* World0-1 (WW0-1 SKU) */
+       WOR02_WORLD     = 0x67,         /* World0-2 (WW0-2 SKU) */
+       EU1_WORLD       = 0x68,         /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */
+
+       WOR9_WORLD      = 0x69,         /* World9 (WO9 SKU) */
+       WORA_WORLD      = 0x6A,         /* WorldA (WOA SKU) */
+
+       MKK3_MKKB       = 0x80,         /* Japan UNI-1 even + MKKB */
+       MKK3_MKKA2      = 0x81,         /* Japan UNI-1 even + MKKA2 */
+       MKK3_MKKC       = 0x82,         /* Japan UNI-1 even + MKKC */
+
+       MKK4_MKKB       = 0x83,         /* Japan UNI-1 even + UNI-2 + MKKB */
+       MKK4_MKKA2      = 0x84,         /* Japan UNI-1 even + UNI-2 + MKKA2 */
+       MKK4_MKKC       = 0x85,         /* Japan UNI-1 even + UNI-2 + MKKC */
+
+       MKK5_MKKB       = 0x86,         /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */
+       MKK5_MKKA2      = 0x87,         /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */
+       MKK5_MKKC       = 0x88,         /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */
+
+       MKK6_MKKB       = 0x89,         /* Japan UNI-1 even + UNI-1 odd MKKB */
+       MKK6_MKKA2      = 0x8A,         /* Japan UNI-1 even + UNI-1 odd + MKKA2 */
+       MKK6_MKKC       = 0x8B,         /* Japan UNI-1 even + UNI-1 odd + MKKC */
+
+       MKK7_MKKB       = 0x8C,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */
+       MKK7_MKKA2      = 0x8D,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */
+       MKK7_MKKC       = 0x8E,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */
+
+       MKK8_MKKB       = 0x8F,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */
+       MKK8_MKKA2      = 0x90,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */
+       MKK8_MKKC       = 0x91,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */
+
+       /* Following definitions are used only by s/w to map old
+        * Japan SKUs.
+        */
+       MKK3_MKKA       = 0xF0,         /* Japan UNI-1 even + MKKA */
+       MKK3_MKKA1      = 0xF1,         /* Japan UNI-1 even + MKKA1 */
+       MKK3_FCCA       = 0xF2,         /* Japan UNI-1 even + FCCA */
+       MKK4_MKKA       = 0xF3,         /* Japan UNI-1 even + UNI-2 + MKKA */
+       MKK4_MKKA1      = 0xF4,         /* Japan UNI-1 even + UNI-2 + MKKA1 */
+       MKK4_FCCA       = 0xF5,         /* Japan UNI-1 even + UNI-2 + FCCA */
+       MKK9_MKKA       = 0xF6,         /* Japan UNI-1 even + 4.9GHz */
+       MKK10_MKKA      = 0xF7,         /* Japan UNI-1 even + UNI-2 + 4.9GHz */
+
+       /*
+        * Regulator domains ending in a number (e.g. APL1,
+        * MK1, ETSI4, etc) apply to 5GHz channel and power
+        * information.  Regulator domains ending in a letter
+        * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and
+        * power information.
+        */
+       APL1            = 0x0150,       /* LAT & Asia */
+       APL2            = 0x0250,       /* LAT & Asia */
+       APL3            = 0x0350,       /* Taiwan */
+       APL4            = 0x0450,       /* Jordan */
+       APL5            = 0x0550,       /* Chile */
+       APL6            = 0x0650,       /* Singapore */
+       APL8            = 0x0850,       /* Malaysia */
+       APL9            = 0x0950,       /* Korea (South) ROC 3 */
+
+       ETSI1           = 0x0130,       /* Europe & others */
+       ETSI2           = 0x0230,       /* Europe & others */
+       ETSI3           = 0x0330,       /* Europe & others */
+       ETSI4           = 0x0430,       /* Europe & others */
+       ETSI5           = 0x0530,       /* Europe & others */
+       ETSI6           = 0x0630,       /* Europe & others */
+       ETSIA           = 0x0A30,       /* France */
+       ETSIB           = 0x0B30,       /* Israel */
+       ETSIC           = 0x0C30,       /* Latin America */
+
+       FCC1            = 0x0110,       /* US & others */
+       FCC2            = 0x0120,       /* Canada, Australia & New Zealand */
+       FCC3            = 0x0160,       /* US w/new middle band & DFS */
+       FCC4            = 0x0165,       /* US Public Safety */
+       FCC5            = 0x0166,       /* US w/ 1/2 and 1/4 width channels */
+       FCCA            = 0x0A10,
+       FCCB            = 0x0A11,       /* US w/ 1/2 and 1/4 width channels */
+
+       APLD            = 0x0D50,       /* South Korea */
+
+       MKK1            = 0x0140,       /* Japan (UNI-1 odd)*/
+       MKK2            = 0x0240,       /* Japan (4.9 GHz + UNI-1 odd) */
+       MKK3            = 0x0340,       /* Japan (UNI-1 even) */
+       MKK4            = 0x0440,       /* Japan (UNI-1 even + UNI-2) */
+       MKK5            = 0x0540,       /* Japan (UNI-1 even + UNI-2 + mid-band) */
+       MKK6            = 0x0640,       /* Japan (UNI-1 odd + UNI-1 even) */
+       MKK7            = 0x0740,       /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */
+       MKK8            = 0x0840,       /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */
+       MKK9            = 0x0940,       /* Japan (UNI-1 even + 4.9 GHZ) */
+       MKK10           = 0x0B40,       /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
+       MKKA            = 0x0A40,       /* Japan */
+       MKKC            = 0x0A50,
+
+       NULL1           = 0x0198,
+       WORLD           = 0x0199,
+       SR9_WORLD       = 0x0298,
+       XR9_WORLD       = 0x0299,
+       GZ901_WORLD     = 0x029a,
+       DEBUG_REG_DMN   = 0x01ff,
+};
+
+#define        WORLD_SKU_MASK          0x00F0
+#define        WORLD_SKU_PREFIX        0x0060
+
+enum {                                 /* conformance test limits */
+       FCC     = 0x10,
+       MKK     = 0x40,
+       ETSI    = 0x30,
+};
+
+/*
+ * The following are flags for different requirements per reg domain.
+ * These requirements are either inhereted from the reg domain pair or
+ * from the unitary reg domain if the reg domain pair flags value is 0
+ */
+enum {
+       NO_REQ                  = 0x00000000,   /* NB: must be zero */
+       DISALLOW_ADHOC_11A      = 0x00000001,
+       DISALLOW_ADHOC_11A_TURB = 0x00000002,
+       NEED_NFC                = 0x00000004,
+       ADHOC_PER_11D           = 0x00000008,  /* Start Ad-Hoc mode */
+       ADHOC_NO_11A            = 0x00000010,
+       LIMIT_FRAME_4MS         = 0x00000020,   /* 4msec limit on frame length*/
+       NO_HOSTAP               = 0x00000040,   /* No HOSTAP mode opereation */
+};
+
+/*
+ * The following describe the bit masks for different passive scan
+ * capability/requirements per regdomain.
+ */
+#define        NO_PSCAN        0x0ULL                  /* NB: must be zero */
+#define        PSCAN_FCC       0x0000000000000001ULL
+#define        PSCAN_FCC_T     0x0000000000000002ULL
+#define        PSCAN_ETSI      0x0000000000000004ULL
+#define        PSCAN_MKK1      0x0000000000000008ULL
+#define        PSCAN_MKK2      0x0000000000000010ULL
+#define        PSCAN_MKKA      0x0000000000000020ULL
+#define        PSCAN_MKKA_G    0x0000000000000040ULL
+#define        PSCAN_ETSIA     0x0000000000000080ULL
+#define        PSCAN_ETSIB     0x0000000000000100ULL
+#define        PSCAN_ETSIC     0x0000000000000200ULL
+#define        PSCAN_WWR       0x0000000000000400ULL
+#define        PSCAN_MKKA1     0x0000000000000800ULL
+#define        PSCAN_MKKA1_G   0x0000000000001000ULL
+#define        PSCAN_MKKA2     0x0000000000002000ULL
+#define        PSCAN_MKKA2_G   0x0000000000004000ULL
+#define        PSCAN_MKK3      0x0000000000008000ULL
+#define        PSCAN_DEFER     0x7FFFFFFFFFFFFFFFULL
+#define        IS_ECM_CHAN     0x8000000000000000ULL
+
+/*
+ * THE following table is the mapping of regdomain pairs specified by
+ * an 8 bit regdomain value to the individual unitary reg domains
+ */
+typedef struct {
+       HAL_REG_DOMAIN regDmnEnum;      /* 16 bit reg domain pair */
+       HAL_REG_DOMAIN regDmn5GHz;      /* 5GHz reg domain */
+       HAL_REG_DOMAIN regDmn2GHz;      /* 2GHz reg domain */
+       uint32_t flags5GHz;             /* Requirements flags (AdHoc
+                                          disallow, noise floor cal needed,
+                                          etc) */
+       uint32_t flags2GHz;             /* Requirements flags (AdHoc
+                                          disallow, noise floor cal needed,
+                                          etc) */
+       uint64_t pscanMask;             /* Passive Scan flags which
+                                          can override unitary domain
+                                          passive scan flags.  This
+                                          value is used as a mask on
+                                          the unitary flags*/
+       uint16_t singleCC;              /* Country code of single country if
+                                          a one-on-one mapping exists */
+}  REG_DMN_PAIR_MAPPING;
+
+static REG_DMN_PAIR_MAPPING regDomainPairs[] = {
+       {NO_ENUMRD,     DEBUG_REG_DMN,  DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {NULL1_WORLD,   NULL1,          WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {NULL1_ETSIB,   NULL1,          ETSIB,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {NULL1_ETSIC,   NULL1,          ETSIC,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+       {FCC2_FCCA,     FCC2,           FCCA,           NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {FCC2_WORLD,    FCC2,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {FCC2_ETSIC,    FCC2,           ETSIC,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {FCC3_FCCA,     FCC3,           FCCA,           NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {FCC3_WORLD,    FCC3,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {FCC4_FCCA,     FCC4,           FCCA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {FCC5_FCCB,     FCC5,           FCCB,           NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+       {ETSI1_WORLD,   ETSI1,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {ETSI2_WORLD,   ETSI2,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {ETSI3_WORLD,   ETSI3,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {ETSI4_WORLD,   ETSI4,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {ETSI5_WORLD,   ETSI5,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {ETSI6_WORLD,   ETSI6,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+
+       {ETSI3_ETSIA,   ETSI3,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {FRANCE_RES,    ETSI3,          WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+       {FCC1_WORLD,    FCC1,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {FCC1_FCCA,     FCC1,           FCCA,           NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL1_WORLD,    APL1,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL2_WORLD,    APL2,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL3_WORLD,    APL3,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL4_WORLD,    APL4,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL5_WORLD,    APL5,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL6_WORLD,    APL6,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL8_WORLD,    APL8,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL9_WORLD,    APL9,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+       {APL3_FCCA,     APL3,           FCCA,           NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL1_ETSIC,    APL1,           ETSIC,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL2_ETSIC,    APL2,           ETSIC,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {APL2_APLD,     APL2,           APLD,           NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+       {MKK1_MKKA,     MKK1,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN },
+       {MKK1_MKKB,     MKK1,           MKKA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN1 },
+       {MKK1_FCCA,     MKK1,           FCCA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 },
+       {MKK1_MKKA1,    MKK1,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 },
+       {MKK1_MKKA2,    MKK1,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 },
+       {MKK1_MKKC,     MKK1,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 },
+
+       /* MKK2 */
+       {MKK2_MKKA,     MKK2,           MKKA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN3 },
+
+       /* MKK3 */
+       {MKK3_MKKA,     MKK3,   MKKA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, 0 },
+       {MKK3_MKKB,     MKK3,           MKKA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN7 },
+       {MKK3_MKKA1,    MKK3,   MKKA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, 0 },
+       {MKK3_MKKA2,MKK3,               MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 },
+       {MKK3_MKKC,     MKK3,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 },
+       {MKK3_FCCA,     MKK3,   FCCA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, 0 },
+
+       /* MKK4 */
+       {MKK4_MKKB,     MKK4,           MKKA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN10 },
+       {MKK4_MKKA1,    MKK4,   MKKA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, 0 },
+       {MKK4_MKKA2,    MKK4,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 },
+       {MKK4_MKKC,     MKK4,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 },
+       {MKK4_FCCA,     MKK4,   FCCA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, 0 },
+
+       /* MKK5 */
+       {MKK5_MKKB,     MKK5,           MKKA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN13 },
+       {MKK5_MKKA2,MKK5,               MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 },
+       {MKK5_MKKC,     MKK5,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 },
+
+       /* MKK6 */
+       {MKK6_MKKB,     MKK6,           MKKA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16 },
+       {MKK6_MKKA2,    MKK6,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 },
+       {MKK6_MKKC,     MKK6,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 },
+
+       /* MKK7 */
+       {MKK7_MKKB,     MKK7,           MKKA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19 },
+       {MKK7_MKKA2, MKK7,              MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN20 },
+       {MKK7_MKKC,     MKK7,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 },
+
+       /* MKK8 */
+       {MKK8_MKKB,     MKK8,           MKKA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22 },
+       {MKK8_MKKA2,MKK8,               MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN23 },
+       {MKK8_MKKC,     MKK8,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 },
+
+       {MKK9_MKKA,     MKK9,   MKKA,   DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, 0 },
+       {MKK10_MKKA,    MKK10,  MKKA,   DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, 0 },
+
+               /* These are super domains */
+       {WOR0_WORLD,    WOR0_WORLD,     WOR0_WORLD,     NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {WOR1_WORLD,    WOR1_WORLD,     WOR1_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {WOR2_WORLD,    WOR2_WORLD,     WOR2_WORLD,     DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {WOR3_WORLD,    WOR3_WORLD,     WOR3_WORLD,     NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {WOR4_WORLD,    WOR4_WORLD,     WOR4_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {WOR5_ETSIC,    WOR5_ETSIC,     WOR5_ETSIC,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {WOR01_WORLD,   WOR01_WORLD,    WOR01_WORLD,    NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {WOR02_WORLD,   WOR02_WORLD,    WOR02_WORLD,    NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {EU1_WORLD,     EU1_WORLD,      EU1_WORLD,      NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+       {WOR9_WORLD,    WOR9_WORLD,     WOR9_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {WORA_WORLD,    WORA_WORLD,     WORA_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+       {SR9_WORLD,     NULL1,          SR9_WORLD,      NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_SR9 },
+       {XR9_WORLD,     NULL1,          XR9_WORLD,      NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_XR9 },
+       {GZ901_WORLD,   NULL1,          GZ901_WORLD,    NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_GZ901 },
+};
+
+/*
+ * The following tables are the master list for all different freqeuncy
+ * bands with the complete matrix of all possible flags and settings
+ * for each band if it is used in ANY reg domain.
+ */
+
+#define DEF_REGDMN             FCC1_FCCA
+#define        DEF_DMN_5               FCC1
+#define        DEF_DMN_2               FCCA
+#define        COUNTRY_ERD_FLAG        0x8000
+#define WORLDWIDE_ROAMING_FLAG  0x4000
+#define        SUPER_DOMAIN_MASK       0x0fff
+#define        COUNTRY_CODE_MASK       0x3fff
+
+#define        YES     AH_TRUE
+#define        NO      AH_FALSE
+
+typedef struct {
+       HAL_CTRY_CODE           countryCode;
+       HAL_REG_DOMAIN          regDmnEnum;
+       HAL_BOOL                allow11g;
+       HAL_BOOL                allow11aTurbo;
+       HAL_BOOL                allow11gTurbo;
+       HAL_BOOL                allow11ng20;
+       HAL_BOOL                allow11ng40;
+       HAL_BOOL                allow11na20;
+       HAL_BOOL                allow11na40;
+       uint16_t                outdoorChanStart;
+} COUNTRY_CODE_TO_ENUM_RD;
+
+static COUNTRY_CODE_TO_ENUM_RD allCountries[] = {
+    {CTRY_DEBUG,       NO_ENUMRD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_DEFAULT,     DEF_REGDMN,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_ALBANIA,     NULL1_WORLD,    YES,  NO, YES, YES, NO,  NO, NO, 7000 },
+    {CTRY_ALGERIA,     NULL1_WORLD,    YES,  NO, YES, YES, NO,  NO, NO, 7000 },
+    {CTRY_ARGENTINA,   APL3_WORLD,      NO,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_ARMENIA,     ETSI4_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_AUSTRALIA,   FCC2_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_AUSTRIA,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_AZERBAIJAN,  ETSI4_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_BAHRAIN,     APL6_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_BELARUS,     NULL1_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_BELGIUM,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_BELIZE,      APL1_ETSIC,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_BOLIVIA,     APL1_ETSIC,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_BRAZIL,      FCC3_WORLD,     YES,  NO,  NO, YES, NO, YES, NO, 7000 },
+    {CTRY_BRUNEI_DARUSSALAM,APL1_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_BULGARIA,    ETSI6_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_CANADA,      FCC2_FCCA,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_CHILE,       APL6_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_CHINA,       APL1_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_COLOMBIA,    FCC1_FCCA,       YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_COSTA_RICA,  NULL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_CROATIA,     ETSI3_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_CYPRUS,      ETSI1_WORLD,    YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_CZECH,       ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_DENMARK,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA,        YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_ECUADOR,     NULL1_WORLD,    NO,   NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_EGYPT,       ETSI3_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_EL_SALVADOR, NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_ESTONIA,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_FINLAND,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_FRANCE,      ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_FRANCE2,     ETSI3_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_GEORGIA,     ETSI4_WORLD,    YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_GERMANY,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_GREECE,      ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_GUATEMALA,   FCC1_FCCA,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_GZ901,       GZ901_WORLD,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_HONDURAS,    NULL1_WORLD,    YES, NO,  YES, YES,YES, YES, NO, 7000 },
+    {CTRY_HONG_KONG,   FCC2_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_HUNGARY,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_ICELAND,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_INDIA,       APL6_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_INDONESIA,   APL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_IRAN,        APL1_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_IRELAND,     ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_ISRAEL,      NULL1_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_ITALY,       ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_JAPAN,       MKK1_MKKA,      YES,  NO,  NO, YES, NO, YES, NO, 7000 },
+    {CTRY_JAPAN1,      MKK1_MKKB,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN2,      MKK1_FCCA,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN3,      MKK2_MKKA,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN4,      MKK1_MKKA1,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN5,      MKK1_MKKA2,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN6,      MKK1_MKKC,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+
+    {CTRY_JAPAN7,      MKK3_MKKB,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN8,      MKK3_MKKA2,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN9,      MKK3_MKKC,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+
+    {CTRY_JAPAN10,     MKK4_MKKB,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN11,     MKK4_MKKA2,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN12,     MKK4_MKKC,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+
+    {CTRY_JAPAN13,     MKK5_MKKB,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN14,     MKK5_MKKA2,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN15,     MKK5_MKKC,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+
+    {CTRY_JAPAN16,     MKK6_MKKB,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN17,     MKK6_MKKA2,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN18,     MKK6_MKKC,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+
+    {CTRY_JAPAN19,     MKK7_MKKB,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN20,     MKK7_MKKA2,     YES,  NO,  NO, YES, NO, YES, NO, 7000 },
+    {CTRY_JAPAN21,     MKK7_MKKC,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+
+    {CTRY_JAPAN22,     MKK8_MKKB,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN23,     MKK8_MKKA2,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_JAPAN24,     MKK8_MKKC,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+
+    {CTRY_JORDAN,      APL4_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_KAZAKHSTAN,  NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_KOREA_NORTH, APL2_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_KOREA_ROC,   APL2_WORLD,     YES,  NO,  NO, YES, NO, YES, NO, 7000 },
+    {CTRY_KOREA_ROC2,  APL2_WORLD,     YES,  NO,  NO, YES, NO, YES, NO, 7000 },
+    {CTRY_KOREA_ROC3,  APL9_WORLD,     YES,  NO,  NO, YES, NO, YES, NO, 7000 },
+    {CTRY_KUWAIT,      NULL1_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_LATVIA,      ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_LEBANON,     NULL1_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_LIECHTENSTEIN,ETSI1_WORLD,   YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_LITHUANIA,   ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_LUXEMBOURG,  ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_MACAU,       FCC2_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_MACEDONIA,   NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_MALAYSIA,    APL8_WORLD,     YES,  NO,  NO, YES, NO, YES, NO, 7000 },
+    {CTRY_MALTA,       ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_MEXICO,      FCC1_FCCA,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_MONACO,      ETSI4_WORLD,    YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_MOROCCO,     NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_NETHERLANDS, ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_NEW_ZEALAND, FCC2_ETSIC,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_NORWAY,      ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_OMAN,        APL6_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_PAKISTAN,    NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_PANAMA,      FCC1_FCCA,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_PERU,        APL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_PHILIPPINES, FCC3_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_POLAND,      ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_PORTUGAL,    ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_PUERTO_RICO, FCC1_FCCA,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_QATAR,       NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_ROMANIA,     NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_RUSSIA,      NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_SAUDI_ARABIA,FCC2_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_SINGAPORE,   APL6_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_SLOVAKIA,    ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_SLOVENIA,    ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_SOUTH_AFRICA,FCC3_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_SPAIN,       ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_SR9,         SR9_WORLD,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_SWEDEN,      ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_SWITZERLAND, ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_SYRIA,       NULL1_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_TAIWAN,      APL3_FCCA,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_THAILAND,    NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD,YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_TUNISIA,     ETSI3_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_TURKEY,      ETSI3_WORLD,    YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_UKRAINE,     NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_UAE,         NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_UNITED_KINGDOM, ETSI1_WORLD, YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_UNITED_STATES, FCC1_FCCA,    YES, YES, YES, YES,YES, YES,YES, 5825 },
+    {CTRY_UNITED_STATES_FCC49,FCC4_FCCA,YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_URUGUAY,     FCC1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_UZBEKISTAN,  FCC3_FCCA,      YES, YES, YES, YES,YES, YES,YES, 7000 },
+    {CTRY_VENEZUELA,   APL2_ETSIC,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
+    {CTRY_VIET_NAM,    NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_XR9,         XR9_WORLD,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
+    {CTRY_YEMEN,       NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 },
+    {CTRY_ZIMBABWE,    NULL1_WORLD,    YES,  NO, YES, YES,YES,  NO, NO, 7000 }
+};
+
+/* Bit masks for DFS per regdomain */
+enum {
+       NO_DFS   = 0x0000000000000000ULL,       /* NB: must be zero */
+       DFS_FCC3 = 0x0000000000000001ULL,
+       DFS_ETSI = 0x0000000000000002ULL,
+       DFS_MKK4 = 0x0000000000000004ULL,
+};
+
+#define        AFTER(x)        ((x)+1)
+
+/*
+ * Frequency band collections are defined using bitmasks.  Each bit
+ * in a mask is the index of an entry in one of the following tables.
+ * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit
+ * vectors must be enlarged or the tables split somehow (e.g. split
+ * 1/2 and 1/4 rate channels into a separate table).
+ *
+ * Beware of ordering; the indices are defined relative to the preceding
+ * entry so if things get off there will be confusion.  A good way to
+ * check the indices is to collect them in a switch statement in a stub
+ * function so the compiler checks for duplicates.
+ */
+
+typedef struct {
+       uint16_t        lowChannel;     /* Low channel center in MHz */
+       uint16_t        highChannel;    /* High Channel center in MHz */
+       uint8_t         powerDfs;       /* Max power (dBm) for channel
+                                          range when using DFS */
+       uint8_t         antennaMax;     /* Max allowed antenna gain */
+       uint8_t         channelBW;      /* Bandwidth of the channel */
+       uint8_t         channelSep;     /* Channel separation within
+                                          the band */
+       uint64_t        useDfs;         /* Use DFS in the RegDomain
+                                          if corresponding bit is set */
+       uint64_t        usePassScan;    /* Use Passive Scan in the RegDomain
+                                          if corresponding bit is set */
+       uint8_t         regClassId;     /* Regulatory class id */
+} REG_DMN_FREQ_BAND;
+
+/*
+ * 5GHz 11A channel tags
+ */
+static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = {
+       { 4915, 4925, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2, 16 },
+#define        F1_4915_4925    0
+       { 4935, 4945, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2, 16 },
+#define        F1_4935_4945    AFTER(F1_4915_4925)
+       { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7 },
+#define        F1_4920_4980    AFTER(F1_4935_4945)
+       { 4942, 4987, 27, 6,  5,  5, NO_DFS, PSCAN_FCC, 0 },
+#define        F1_4942_4987    AFTER(F1_4920_4980)
+       { 4945, 4985, 30, 6, 10,  5, NO_DFS, PSCAN_FCC, 0 },
+#define        F1_4945_4985    AFTER(F1_4942_4987)
+       { 4950, 4980, 33, 6, 20,  5, NO_DFS, PSCAN_FCC, 0 },
+#define        F1_4950_4980    AFTER(F1_4945_4985)
+       { 5035, 5040, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2, 12 },
+#define        F1_5035_5040    AFTER(F1_4950_4980)
+       { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2 },
+#define        F1_5040_5080    AFTER(F1_5035_5040)
+       { 5055, 5055, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2, 12 },
+#define        F1_5055_5055    AFTER(F1_5040_5080)
+
+       { 5120, 5240, 5,  6, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F1_5120_5240    AFTER(F1_5055_5055)
+       { 5120, 5240, 5,  6, 10, 10, NO_DFS, NO_PSCAN, 0 },
+#define        F2_5120_5240    AFTER(F1_5120_5240)
+       { 5120, 5240, 5,  6,  5,  5, NO_DFS, NO_PSCAN, 0 },
+#define        F3_5120_5240    AFTER(F2_5120_5240)
+
+       { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 },
+#define        F1_5170_5230    AFTER(F3_5120_5240)
+       { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 },
+#define        F2_5170_5230    AFTER(F1_5170_5230)
+
+       { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F1_5180_5240    AFTER(F2_5170_5230)
+       { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC, 1 },
+#define        F2_5180_5240    AFTER(F1_5180_5240)
+       { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F3_5180_5240    AFTER(F2_5180_5240)
+       { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F4_5180_5240    AFTER(F3_5180_5240)
+       { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F5_5180_5240    AFTER(F4_5180_5240)
+       { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0 },
+#define        F6_5180_5240    AFTER(F5_5180_5240)
+       { 5180, 5240, 17, 6, 20, 10, NO_DFS, PSCAN_FCC, 1 },
+#define        F7_5180_5240    AFTER(F6_5180_5240)
+       { 5180, 5240, 17, 6, 20,  5, NO_DFS, PSCAN_FCC, 1 },
+#define        F8_5180_5240    AFTER(F7_5180_5240)
+
+       { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 },
+#define        F1_5180_5320    AFTER(F8_5180_5240)
+
+       { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F1_5240_5280    AFTER(F1_5180_5320)
+
+       { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F1_5260_5280    AFTER(F1_5240_5280)
+
+       { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F1_5260_5320    AFTER(F1_5260_5280)
+
+       { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 , 0 },
+#define        F2_5260_5320    AFTER(F1_5260_5320)
+
+       { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 },
+#define        F3_5260_5320    AFTER(F2_5260_5320)
+       { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 },
+#define        F4_5260_5320    AFTER(F3_5260_5320)
+       { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 },
+#define        F5_5260_5320    AFTER(F4_5260_5320)
+       { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F6_5260_5320    AFTER(F5_5260_5320)
+       { 5260, 5320, 23, 6, 20, 10, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 },
+#define        F7_5260_5320    AFTER(F6_5260_5320)
+       { 5260, 5320, 23, 6, 20,  5, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 },
+#define        F8_5260_5320    AFTER(F7_5260_5320)
+
+       { 5260, 5700, 5,  6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 },
+#define        F1_5260_5700    AFTER(F8_5260_5320)
+       { 5260, 5700, 5,  6, 10, 10, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 },
+#define        F2_5260_5700    AFTER(F1_5260_5700)
+       { 5260, 5700, 5,  6,  5,  5, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 },
+#define        F3_5260_5700    AFTER(F2_5260_5700)
+
+       { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 },
+#define        F1_5280_5320    AFTER(F3_5260_5700)
+
+       { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 },
+#define        F1_5500_5620    AFTER(F1_5280_5320)
+
+       { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4 },
+#define        F1_5500_5700    AFTER(F1_5500_5620)
+       { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F2_5500_5700    AFTER(F1_5500_5700)
+       { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 },
+#define        F3_5500_5700    AFTER(F2_5500_5700)
+       { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC, 0 },
+#define        F4_5500_5700    AFTER(F3_5500_5700)
+
+       { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F1_5745_5805    AFTER(F4_5500_5700)
+       { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F2_5745_5805    AFTER(F1_5745_5805)
+       { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 },
+#define        F3_5745_5805    AFTER(F2_5745_5805)
+       { 5745, 5825, 5,  6, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F1_5745_5825    AFTER(F3_5745_5805)
+       { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F2_5745_5825    AFTER(F1_5745_5825)
+       { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F3_5745_5825    AFTER(F2_5745_5825)
+       { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F4_5745_5825    AFTER(F3_5745_5825)
+       { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3 },
+#define        F5_5745_5825    AFTER(F4_5745_5825)
+       { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 },
+#define        F6_5745_5825    AFTER(F5_5745_5825)
+       { 5745, 5825, 5,  6, 10, 10, NO_DFS, NO_PSCAN, 0 },
+#define        F7_5745_5825    AFTER(F6_5745_5825)
+       { 5745, 5825, 5,  6,  5,  5, NO_DFS, NO_PSCAN, 0 },
+#define        F8_5745_5825    AFTER(F7_5745_5825)
+       { 5745, 5825, 30, 6, 20, 10, NO_DFS, NO_PSCAN, 3 },
+#define        F9_5745_5825    AFTER(F8_5745_5825)
+       { 5745, 5825, 30, 6, 20,  5, NO_DFS, NO_PSCAN, 3 },
+#define        F10_5745_5825   AFTER(F9_5745_5825)
+
+       /*
+        * Below are the world roaming channels
+        * All WWR domains have no power limit, instead use the card's CTL
+        * or max power settings.
+        */
+       { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 },
+#define        W1_4920_4980    AFTER(F10_5745_5825)
+       { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 },
+#define        W1_5040_5080    AFTER(W1_4920_4980)
+       { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 },
+#define        W1_5170_5230    AFTER(W1_5040_5080)
+       { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 },
+#define        W1_5180_5240    AFTER(W1_5170_5230)
+       { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 },
+#define        W1_5260_5320    AFTER(W1_5180_5240)
+       { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 },
+#define        W1_5745_5825    AFTER(W1_5260_5320)
+       { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 },
+#define        W1_5500_5700    AFTER(W1_5745_5825)
+       { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN,  0 },
+#define        W2_5260_5320    AFTER(W1_5500_5700)
+       { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN,  0 },
+#define        W2_5180_5240    AFTER(W2_5260_5320)
+       { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 },
+#define        W2_5825_5825    AFTER(W2_5180_5240)
+};
+
+/*
+ * 5GHz Turbo (dynamic & static) tags
+ */
+static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = {
+       { 5130, 5210, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_5130_5210    0
+       { 5250, 5330, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0},
+#define        T1_5250_5330    AFTER(T1_5130_5210)
+       { 5370, 5490, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_5370_5490    AFTER(T1_5250_5330)
+       { 5530, 5650, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0},
+#define        T1_5530_5650    AFTER(T1_5370_5490)
+
+       { 5150, 5190, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_5150_5190    AFTER(T1_5530_5650)
+       { 5230, 5310, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0},
+#define        T1_5230_5310    AFTER(T1_5150_5190)
+       { 5350, 5470, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_5350_5470    AFTER(T1_5230_5310)
+       { 5510, 5670, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0},
+#define        T1_5510_5670    AFTER(T1_5350_5470)
+
+       { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_5200_5240    AFTER(T1_5510_5670)
+       { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T2_5200_5240    AFTER(T1_5200_5240)
+       { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_5210_5210    AFTER(T2_5200_5240)
+       { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T2_5210_5210    AFTER(T1_5210_5210)
+
+       { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
+#define        T1_5280_5280    AFTER(T2_5210_5210)
+       { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
+#define        T2_5280_5280    AFTER(T1_5280_5280)
+       { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
+#define        T1_5250_5250    AFTER(T2_5280_5280)
+       { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
+#define        T1_5290_5290    AFTER(T1_5250_5250)
+       { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
+#define        T1_5250_5290    AFTER(T1_5290_5290)
+       { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
+#define        T2_5250_5290    AFTER(T1_5250_5290)
+
+       { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
+#define        T1_5540_5660    AFTER(T2_5250_5290)
+       { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_5760_5800    AFTER(T1_5540_5660)
+       { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T2_5760_5800    AFTER(T1_5760_5800)
+
+       { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_5765_5805    AFTER(T2_5760_5800)
+
+       /*
+        * Below are the WWR frequencies
+        */
+       { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
+#define        WT1_5210_5250   AFTER(T1_5765_5805)
+       { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
+#define        WT1_5290_5290   AFTER(WT1_5210_5250)
+       { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
+#define        WT1_5540_5660   AFTER(WT1_5290_5290)
+       { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR, 0},
+#define        WT1_5760_5800   AFTER(WT1_5540_5660)
+};
+
+/*
+ * 2GHz 11b channel tags
+ */
+static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = {
+       { 2312, 2372, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F1_2312_2372    0
+       { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F2_2312_2372    AFTER(F1_2312_2372)
+
+       { 2412, 2472, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F1_2412_2472    AFTER(F2_2312_2372)
+       { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0},
+#define        F2_2412_2472    AFTER(F1_2412_2472)
+       { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F3_2412_2472    AFTER(F2_2412_2472)
+
+       { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F1_2412_2462    AFTER(F3_2412_2472)
+       { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0},
+#define        F2_2412_2462    AFTER(F1_2412_2462)
+
+       { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F1_2432_2442    AFTER(F2_2412_2462)
+
+       { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F1_2457_2472    AFTER(F1_2432_2442)
+
+       { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0},
+#define        F1_2467_2472    AFTER(F1_2457_2472)
+
+       { 2484, 2484, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F1_2484_2484    AFTER(F1_2467_2472)
+       { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0},
+#define        F2_2484_2484    AFTER(F1_2484_2484)
+
+       { 2512, 2732, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        F1_2512_2732    AFTER(F2_2484_2484)
+
+       /*
+        * WWR have powers opened up to 20dBm.
+        * Limits should often come from CTL/Max powers
+        */
+       { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        W1_2312_2372    AFTER(F1_2512_2732)
+       { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        W1_2412_2412    AFTER(W1_2312_2372)
+       { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        W1_2417_2432    AFTER(W1_2412_2412)
+       { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        W1_2437_2442    AFTER(W1_2417_2432)
+       { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        W1_2447_2457    AFTER(W1_2437_2442)
+       { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        W1_2462_2462    AFTER(W1_2447_2457)
+       { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+#define        W1_2467_2467    AFTER(W1_2462_2462)
+       { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+#define        W2_2467_2467    AFTER(W1_2467_2467)
+       { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+#define        W1_2472_2472    AFTER(W2_2467_2467)
+       { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+#define        W2_2472_2472    AFTER(W1_2472_2472)
+       { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+#define        W1_2484_2484    AFTER(W2_2472_2472)
+       { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+#define        W2_2484_2484    AFTER(W1_2484_2484)
+};
+
+/*
+ * 2GHz 11g channel tags
+ */
+static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = {
+       { 2312, 2372, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        G1_2312_2372    0
+       { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        G2_2312_2372    AFTER(G1_2312_2372)
+       { 2312, 2372, 5,  6, 10, 5, NO_DFS, NO_PSCAN, 0},
+#define        G3_2312_2372    AFTER(G2_2312_2372)
+       { 2312, 2372, 5,  6,  5, 5, NO_DFS, NO_PSCAN, 0},
+#define        G4_2312_2372    AFTER(G3_2312_2372)
+
+       { 2412, 2472, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        G1_2412_2472    AFTER(G4_2312_2372)
+       { 2412, 2472, 20, 0, 20, 5,  NO_DFS, PSCAN_MKKA_G, 0},
+#define        G2_2412_2472    AFTER(G1_2412_2472)
+       { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        G3_2412_2472    AFTER(G2_2412_2472)
+       { 2412, 2472, 5,  6, 10, 5, NO_DFS, NO_PSCAN, 0},
+#define        G4_2412_2472    AFTER(G3_2412_2472)
+       { 2412, 2472, 5,  6,  5, 5, NO_DFS, NO_PSCAN, 0},
+#define        G5_2412_2472    AFTER(G4_2412_2472)
+
+       { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        G1_2412_2462    AFTER(G5_2412_2472)
+       { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0},
+#define        G2_2412_2462    AFTER(G1_2412_2462)
+       { 2412, 2462, 27, 6, 10, 5, NO_DFS, NO_PSCAN, 0},
+#define        G3_2412_2462    AFTER(G2_2412_2462)
+       { 2412, 2462, 27, 6,  5, 5, NO_DFS, NO_PSCAN, 0},
+#define        G4_2412_2462    AFTER(G3_2412_2462)
+
+       { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        G1_2432_2442    AFTER(G4_2412_2462)
+
+       { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        G1_2457_2472    AFTER(G1_2432_2442)
+
+       { 2512, 2732, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        G1_2512_2732    AFTER(G1_2457_2472)
+       { 2512, 2732, 5,  6, 10, 5, NO_DFS, NO_PSCAN, 0},
+#define        G2_2512_2732    AFTER(G1_2512_2732)
+       { 2512, 2732, 5,  6,  5, 5, NO_DFS, NO_PSCAN, 0},
+#define        G3_2512_2732    AFTER(G2_2512_2732)
+
+       { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0 },
+#define        G1_2467_2472    AFTER(G3_2512_2732)
+
+       /*
+        * WWR open up the power to 20dBm
+        */
+       { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        WG1_2312_2372   AFTER(G1_2467_2472)
+       { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        WG1_2412_2412   AFTER(WG1_2312_2372)
+       { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        WG1_2417_2432   AFTER(WG1_2412_2412)
+       { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        WG1_2437_2442   AFTER(WG1_2417_2432)
+       { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        WG1_2447_2457   AFTER(WG1_2437_2442)
+       { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+#define        WG1_2462_2462   AFTER(WG1_2447_2457)
+       { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+#define        WG1_2467_2467   AFTER(WG1_2462_2462)
+       { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+#define        WG2_2467_2467   AFTER(WG1_2467_2467)
+       { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+#define        WG1_2472_2472   AFTER(WG2_2467_2467)
+       { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+#define        WG2_2472_2472   AFTER(WG1_2472_2472)
+
+       /*
+        * Mapping for 900MHz cards like Ubiquiti SR9 and XR9
+        * and ZComax GZ-901.
+        */
+       { 2422, 2437, 30, 0,  5, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S1_907_922_5    AFTER(WG2_2472_2472)
+       { 2422, 2437, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S1_907_922_10   AFTER(S1_907_922_5)
+       { 2427, 2432, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S1_912_917      AFTER(S1_907_922_10)
+       { 2427, 2442, 30, 0,  5, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S2_907_922_5    AFTER(S1_912_917)
+       { 2427, 2442, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S2_907_922_10   AFTER(S2_907_922_5)
+       { 2432, 2437, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S2_912_917      AFTER(S2_907_922_10)
+       { 2452, 2467, 30, 0,  5, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S1_908_923_5    AFTER(S2_912_917)
+       { 2457, 2467, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S1_913_918_10   AFTER(S1_908_923_5)
+       { 2457, 2467, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 },
+#define        S1_913_918      AFTER(S1_913_918_10)
+};
+
+/*
+ * 2GHz Dynamic turbo tags
+ */
+static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = {
+       { 2312, 2372, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_2312_2372    0
+       { 2437, 2437, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_2437_2437    AFTER(T1_2312_2372)
+       { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T2_2437_2437    AFTER(T1_2437_2437)
+       { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0},
+#define        T3_2437_2437    AFTER(T2_2437_2437)
+       { 2512, 2732, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
+#define        T1_2512_2732    AFTER(T3_2437_2437)
+};
+
+typedef struct regDomain {
+       uint16_t regDmnEnum;            /* value from EnumRd table */
+       uint8_t conformanceTestLimit;
+       uint32_t flags;                 /* Requirement flags (AdHoc disallow,
+                                          noise floor cal needed, etc) */
+       uint64_t dfsMask;               /* DFS bitmask for 5Ghz tables */
+       uint64_t pscan;                 /* Bitmask for passive scan */
+       chanbmask_t chan11a;            /* 11a channels */
+       chanbmask_t chan11a_turbo;      /* 11a static turbo channels */
+       chanbmask_t chan11a_dyn_turbo;  /* 11a dynamic turbo channels */
+       chanbmask_t chan11a_half;       /* 11a 1/2 width channels */
+       chanbmask_t chan11a_quarter;    /* 11a 1/4 width channels */
+       chanbmask_t chan11b;            /* 11b channels */
+       chanbmask_t chan11g;            /* 11g channels */
+       chanbmask_t chan11g_turbo;      /* 11g dynamic turbo channels */
+       chanbmask_t chan11g_half;       /* 11g 1/2 width channels */
+       chanbmask_t chan11g_quarter;    /* 11g 1/4 width channels */
+} REG_DOMAIN;
+
+static REG_DOMAIN regDomains[] = {
+
+       {.regDmnEnum            = DEBUG_REG_DMN,
+        .conformanceTestLimit  = FCC,
+        .dfsMask               = DFS_FCC3,
+        .chan11a               = BM3(F1_5120_5240, F1_5260_5700, F1_5745_5825),
+        .chan11a_half          = BM3(F2_5120_5240, F2_5260_5700, F7_5745_5825),
+        .chan11a_quarter       = BM3(F3_5120_5240, F3_5260_5700, F8_5745_5825),
+        .chan11a_turbo         = BM8(T1_5130_5210,
+                                     T1_5250_5330,
+                                     T1_5370_5490,
+                                     T1_5530_5650,
+                                     T1_5150_5190,
+                                     T1_5230_5310,
+                                     T1_5350_5470,
+                                     T1_5510_5670),
+        .chan11a_dyn_turbo     = BM4(T1_5200_5240,
+                                     T1_5280_5280,
+                                     T1_5540_5660,
+                                     T1_5765_5805),
+        .chan11b               = BM4(F1_2312_2372,
+                                     F1_2412_2472,
+                                     F1_2484_2484,
+                                     F1_2512_2732),
+        .chan11g               = BM3(G1_2312_2372, G1_2412_2472, G1_2512_2732),
+        .chan11g_turbo         = BM3(T1_2312_2372, T1_2437_2437, T1_2512_2732),
+        .chan11g_half          = BM3(G2_2312_2372, G4_2412_2472, G2_2512_2732),
+        .chan11g_quarter       = BM3(G3_2312_2372, G5_2412_2472, G3_2512_2732),
+       },
+
+       {.regDmnEnum            = APL1,
+        .conformanceTestLimit  = FCC,
+        .chan11a               = BM1(F4_5745_5825),
+       },
+
+       {.regDmnEnum            = APL2,
+        .conformanceTestLimit  = FCC,
+        .chan11a               = BM1(F1_5745_5805),
+       },
+
+       {.regDmnEnum            = APL3,
+        .conformanceTestLimit  = FCC,
+        .chan11a               = BM2(F1_5280_5320, F2_5745_5805),
+       },
+
+       {.regDmnEnum            = APL4,
+        .conformanceTestLimit  = FCC,
+        .chan11a               = BM2(F4_5180_5240, F3_5745_5825),
+       },
+
+       {.regDmnEnum            = APL5,
+        .conformanceTestLimit  = FCC,
+        .chan11a               = BM1(F2_5745_5825),
+       },
+
+       {.regDmnEnum            = APL6,
+        .conformanceTestLimit  = ETSI,
+        .dfsMask               = DFS_ETSI,
+        .pscan                 = PSCAN_FCC_T | PSCAN_FCC,
+        .chan11a               = BM3(F4_5180_5240, F2_5260_5320, F3_5745_5825),
+        .chan11a_turbo         = BM3(T2_5210_5210, T1_5250_5290, T1_5760_5800),
+       },
+
+       {.regDmnEnum            = APL8,
+        .conformanceTestLimit  = ETSI,
+        .flags                 = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM2(F6_5260_5320, F4_5745_5825),
+       },
+
+       {.regDmnEnum            = APL9,
+        .conformanceTestLimit  = ETSI,
+        .dfsMask               = DFS_ETSI,
+        .pscan                 = PSCAN_ETSI,
+        .flags                 = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM3(F1_5180_5320, F1_5500_5620, F3_5745_5805),
+       },
+
+       {.regDmnEnum            = ETSI1,
+        .conformanceTestLimit  = ETSI,
+        .dfsMask               = DFS_ETSI,
+        .pscan                 = PSCAN_ETSI,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM3(W2_5180_5240, F2_5260_5320, F2_5500_5700),
+       },
+
+       {.regDmnEnum            = ETSI2,
+        .conformanceTestLimit  = ETSI,
+        .dfsMask               = DFS_ETSI,
+        .pscan                 = PSCAN_ETSI,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM1(F3_5180_5240),
+       },
+
+       {.regDmnEnum            = ETSI3,
+        .conformanceTestLimit  = ETSI,
+        .dfsMask               = DFS_ETSI,
+        .pscan                 = PSCAN_ETSI,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM2(W2_5180_5240, F2_5260_5320),
+       },
+
+       {.regDmnEnum            = ETSI4,
+        .conformanceTestLimit  = ETSI,
+        .dfsMask               = DFS_ETSI,
+        .pscan                 = PSCAN_ETSI,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM2(F3_5180_5240, F1_5260_5320),
+       },
+
+       {.regDmnEnum            = ETSI5,
+        .conformanceTestLimit  = ETSI,
+        .dfsMask               = DFS_ETSI,
+        .pscan                 = PSCAN_ETSI,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM1(F1_5180_5240),
+       },
+
+       {.regDmnEnum            = ETSI6,
+        .conformanceTestLimit  = ETSI,
+        .dfsMask               = DFS_ETSI,
+        .pscan                 = PSCAN_ETSI,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM3(F5_5180_5240, F1_5260_5280, F3_5500_5700),
+       },
+
+       {.regDmnEnum            = FCC1,
+        .conformanceTestLimit  = FCC,
+        .chan11a               = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825),
+        .chan11a_turbo         = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800),
+        .chan11a_dyn_turbo     = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805),
+       },
+
+       {.regDmnEnum            = FCC2,
+        .conformanceTestLimit  = FCC,
+        .chan11a               = BM3(F6_5180_5240, F5_5260_5320, F6_5745_5825),
+        .chan11a_dyn_turbo     = BM3(T2_5200_5240, T1_5280_5280, T1_5765_5805),
+       },
+
+       {.regDmnEnum            = FCC3,
+        .conformanceTestLimit  = FCC,
+        .dfsMask               = DFS_FCC3,
+        .pscan                 = PSCAN_FCC | PSCAN_FCC_T,
+        .chan11a               = BM4(F2_5180_5240,
+                                     F3_5260_5320,
+                                     F1_5500_5700,
+                                     F5_5745_5825),
+        .chan11a_turbo         = BM4(T1_5210_5210,
+                                     T1_5250_5250,
+                                     T1_5290_5290,
+                                     T2_5760_5800),
+        .chan11a_dyn_turbo     = BM3(T1_5200_5240, T2_5280_5280, T1_5540_5660),
+       },
+
+       {.regDmnEnum            = FCC4,
+        .conformanceTestLimit  = FCC,
+        .dfsMask               = DFS_FCC3,
+        .pscan                 = PSCAN_FCC | PSCAN_FCC_T,
+        .chan11a               = BM1(F1_4950_4980),
+        .chan11a_half          = BM1(F1_4945_4985),
+        .chan11a_quarter       = BM1(F1_4942_4987),
+       },
+
+       /* FCC1 w/ 1/2 and 1/4 width channels */
+       {.regDmnEnum            = FCC5,
+        .conformanceTestLimit  = FCC,
+        .chan11a               = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825),
+        .chan11a_turbo         = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800),
+        .chan11a_dyn_turbo     = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805),
+        .chan11a_half          = BM3(F7_5180_5240, F7_5260_5320, F9_5745_5825),
+        .chan11a_quarter       = BM3(F8_5180_5240, F8_5260_5320,F10_5745_5825),
+       },
+
+       {.regDmnEnum            = MKK1,
+        .conformanceTestLimit  = MKK,
+        .pscan                 = PSCAN_MKK1,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM1(F1_5170_5230),
+       },
+
+       {.regDmnEnum            = MKK2,
+        .conformanceTestLimit  = MKK,
+        .pscan                 = PSCAN_MKK2,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM3(F1_4920_4980, F1_5040_5080, F1_5170_5230),
+       .chan11a_half           = BM4(F1_4915_4925,
+                                     F1_4935_4945,
+                                     F1_5035_5040,
+                                     F1_5055_5055),
+       },
+
+       /* UNI-1 even */
+       {.regDmnEnum            = MKK3,
+        .conformanceTestLimit  = MKK,
+        .pscan                 = PSCAN_MKK3,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM1(F4_5180_5240),
+       },
+
+       /* UNI-1 even + UNI-2 */
+       {.regDmnEnum            = MKK4,
+        .conformanceTestLimit  = MKK,
+        .dfsMask               = DFS_MKK4,
+        .pscan                 = PSCAN_MKK3,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM2(F4_5180_5240, F2_5260_5320),
+       },
+
+       /* UNI-1 even + UNI-2 + mid-band */
+       {.regDmnEnum            = MKK5,
+        .conformanceTestLimit  = MKK,
+        .dfsMask               = DFS_MKK4,
+        .pscan                 = PSCAN_MKK3,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM3(F4_5180_5240, F2_5260_5320, F4_5500_5700),
+       },
+
+       /* UNI-1 odd + even */
+       {.regDmnEnum            = MKK6,
+        .conformanceTestLimit  = MKK,
+        .pscan                 = PSCAN_MKK1,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM2(F2_5170_5230, F4_5180_5240),
+       },
+
+       /* UNI-1 odd + UNI-1 even + UNI-2 */
+       {.regDmnEnum            = MKK7,
+        .conformanceTestLimit  = MKK,
+        .dfsMask               = DFS_MKK4,
+        .pscan                 = PSCAN_MKK1 | PSCAN_MKK3,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM3(F1_5170_5230, F4_5180_5240, F2_5260_5320),
+       },
+
+       /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */
+       {.regDmnEnum            = MKK8,
+        .conformanceTestLimit  = MKK,
+        .dfsMask               = DFS_MKK4,
+        .pscan                 = PSCAN_MKK1 | PSCAN_MKK3,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11a               = BM4(F1_5170_5230,
+                                     F4_5180_5240,
+                                     F2_5260_5320,
+                                     F4_5500_5700),
+       },
+
+        /* UNI-1 even + 4.9 GHZ */
+        {.regDmnEnum           = MKK9,
+        .conformanceTestLimit  = MKK,
+        .pscan                 = PSCAN_MKK3,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+         .chan11a              = BM7(F1_4915_4925,
+                                     F1_4935_4945,
+                                     F1_4920_4980,
+                                     F1_5035_5040,
+                                     F1_5055_5055,
+                                     F1_5040_5080,
+                                     F4_5180_5240),
+        },
+
+        /* UNI-1 even + UNI-2 + 4.9 GHZ */
+        {.regDmnEnum           = MKK10,
+        .conformanceTestLimit  = MKK,
+        .dfsMask               = DFS_MKK4,
+        .pscan                 = PSCAN_MKK3,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+         .chan11a              = BM8(F1_4915_4925,
+                                     F1_4935_4945,
+                                     F1_4920_4980,
+                                     F1_5035_5040,
+                                     F1_5055_5055,
+                                     F1_5040_5080,
+                                     F4_5180_5240,
+                                     F2_5260_5320),
+        },
+
+       /* Defined here to use when 2G channels are authorised for country K2 */
+       {.regDmnEnum            = APLD,
+        .conformanceTestLimit  = NO_CTL,
+        .chan11b               = BM2(F2_2312_2372,F2_2412_2472),
+        .chan11g               = BM2(G2_2312_2372,G2_2412_2472),
+       },
+
+       {.regDmnEnum            = ETSIA,
+        .conformanceTestLimit  = NO_CTL,
+        .pscan                 = PSCAN_ETSIA,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11b               = BM1(F1_2457_2472),
+        .chan11g               = BM1(G1_2457_2472),
+        .chan11g_turbo         = BM1(T2_2437_2437)
+       },
+
+       {.regDmnEnum            = ETSIB,
+        .conformanceTestLimit  = ETSI,
+        .pscan                 = PSCAN_ETSIB,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11b               = BM1(F1_2432_2442),
+        .chan11g               = BM1(G1_2432_2442),
+        .chan11g_turbo         = BM1(T2_2437_2437)
+       },
+
+       {.regDmnEnum            = ETSIC,
+        .conformanceTestLimit  = ETSI,
+        .pscan                 = PSCAN_ETSIC,
+        .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+        .chan11b               = BM1(F3_2412_2472),
+        .chan11g               = BM1(G3_2412_2472),
+        .chan11g_turbo         = BM1(T2_2437_2437)
+       },
+
+       {.regDmnEnum            = FCCA,
+        .conformanceTestLimit  = FCC,
+        .chan11b               = BM1(F1_2412_2462),
+        .chan11g               = BM1(G1_2412_2462),
+        .chan11g_turbo         = BM1(T2_2437_2437),
+       },
+
+       /* FCCA w/ 1/2 and 1/4 width channels */
+       {.regDmnEnum            = FCCB,
+        .conformanceTestLimit  = FCC,
+        .chan11b               = BM1(F1_2412_2462),
+        .chan11g               = BM1(G1_2412_2462),
+        .chan11g_turbo         = BM1(T2_2437_2437),
+        .chan11g_half          = BM1(G3_2412_2462),
+        .chan11g_quarter       = BM1(G4_2412_2462),
+       },
+
+       {.regDmnEnum            = MKKA,
+        .conformanceTestLimit  = MKK,
+        .pscan                 = PSCAN_MKKA | PSCAN_MKKA_G
+                               | PSCAN_MKKA1 | PSCAN_MKKA1_G
+                               | PSCAN_MKKA2 | PSCAN_MKKA2_G,
+        .flags                 = DISALLOW_ADHOC_11A_TURB,
+        .chan11b               = BM3(F2_2412_2462, F1_2467_2472, F2_2484_2484),
+        .chan11g               = BM2(G2_2412_2462, G1_2467_2472),
+        .chan11g_turbo         = BM1(T2_2437_2437)
+       },
+
+       {.regDmnEnum            = MKKC,
+        .conformanceTestLimit  = MKK,
+        .chan11b               = BM1(F2_2412_2472),
+        .chan11g               = BM1(G2_2412_2472),
+        .chan11g_turbo         = BM1(T2_2437_2437)
+       },
+
+       {.regDmnEnum            = WORLD,
+        .conformanceTestLimit  = ETSI,
+        .chan11b               = BM1(F2_2412_2472),
+        .chan11g               = BM1(G2_2412_2472),
+        .chan11g_turbo         = BM1(T2_2437_2437)
+       },
+
+       {.regDmnEnum            = WOR0_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_PER_11D,
+        .chan11a               = BM5(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5170_5230,
+                                     W1_5745_5825,
+                                     W1_5500_5700),
+        .chan11a_turbo         = BM3(WT1_5210_5250,
+                                     WT1_5290_5290,
+                                     WT1_5760_5800),
+        .chan11b               = BM8(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2472_2472,
+                                     W1_2417_2432,
+                                     W1_2447_2457,
+                                     W1_2467_2467,
+                                     W1_2484_2484),
+        .chan11g               = BM7(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2472_2472,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457,
+                                     WG1_2467_2467),
+        .chan11g_turbo         = BM1(T3_2437_2437)
+       },
+
+       {.regDmnEnum            = WOR01_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_PER_11D,
+        .chan11a               = BM5(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5170_5230,
+                                     W1_5745_5825,
+                                     W1_5500_5700),
+        .chan11a_turbo         = BM3(WT1_5210_5250,
+                                     WT1_5290_5290,
+                                     WT1_5760_5800),
+        .chan11b               = BM5(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2417_2432,
+                                     W1_2447_2457),
+        .chan11g               = BM5(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = WOR02_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_PER_11D,
+        .chan11a               = BM5(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5170_5230,
+                                     W1_5745_5825,
+                                     W1_5500_5700),
+        .chan11a_turbo         = BM3(WT1_5210_5250,
+                                     WT1_5290_5290,
+                                     WT1_5760_5800),
+        .chan11b               = BM7(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2472_2472,
+                                     W1_2417_2432,
+                                     W1_2447_2457,
+                                     W1_2467_2467),
+        .chan11g               = BM7(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2472_2472,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457,
+                                     WG1_2467_2467),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = EU1_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_PER_11D,
+        .chan11a               = BM5(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5170_5230,
+                                     W1_5745_5825,
+                                     W1_5500_5700),
+        .chan11a_turbo         = BM3(WT1_5210_5250,
+                                     WT1_5290_5290,
+                                     WT1_5760_5800),
+        .chan11b               = BM7(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W2_2472_2472,
+                                     W1_2417_2432,
+                                     W1_2447_2457,
+                                     W2_2467_2467),
+        .chan11g               = BM7(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG2_2472_2472,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457,
+                                     WG2_2467_2467),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = WOR1_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_NO_11A,
+        .chan11a               = BM5(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5170_5230,
+                                     W1_5745_5825,
+                                     W1_5500_5700),
+        .chan11b               = BM8(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2472_2472,
+                                     W1_2417_2432,
+                                     W1_2447_2457,
+                                     W1_2467_2467,
+                                     W1_2484_2484),
+        .chan11g               = BM7(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2472_2472,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457,
+                                     WG1_2467_2467),
+        .chan11g_turbo         = BM1(T3_2437_2437)
+       },
+
+       {.regDmnEnum            = WOR2_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_NO_11A,
+        .chan11a               = BM5(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5170_5230,
+                                     W1_5745_5825,
+                                     W1_5500_5700),
+        .chan11a_turbo         = BM3(WT1_5210_5250,
+                                     WT1_5290_5290,
+                                     WT1_5760_5800),
+        .chan11b               = BM8(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2472_2472,
+                                     W1_2417_2432,
+                                     W1_2447_2457,
+                                     W1_2467_2467,
+                                     W1_2484_2484),
+        .chan11g               = BM7(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2472_2472,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457,
+                                     WG1_2467_2467),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = WOR3_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_PER_11D,
+        .chan11a               = BM4(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5170_5230,
+                                     W1_5745_5825),
+        .chan11a_turbo         = BM3(WT1_5210_5250,
+                                     WT1_5290_5290,
+                                     WT1_5760_5800),
+        .chan11b               = BM7(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2472_2472,
+                                     W1_2417_2432,
+                                     W1_2447_2457,
+                                     W1_2467_2467),
+        .chan11g               = BM7(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2472_2472,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457,
+                                     WG1_2467_2467),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = WOR4_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_NO_11A,
+        .chan11a               = BM4(W2_5260_5320,
+                                     W2_5180_5240,
+                                     F2_5745_5805,
+                                     W2_5825_5825),
+        .chan11a_turbo         = BM3(WT1_5210_5250,
+                                     WT1_5290_5290,
+                                     WT1_5760_5800),
+        .chan11b               = BM5(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2417_2432,
+                                     W1_2447_2457),
+        .chan11g               = BM5(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = WOR5_ETSIC,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_NO_11A,
+        .chan11a               = BM3(W1_5260_5320, W2_5180_5240, F6_5745_5825),
+        .chan11b               = BM7(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W2_2472_2472,
+                                     W1_2417_2432,
+                                     W1_2447_2457,
+                                     W2_2467_2467),
+        .chan11g               = BM7(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG2_2472_2472,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457,
+                                     WG2_2467_2467),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = WOR9_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_NO_11A,
+        .chan11a               = BM4(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5745_5825,
+                                     W1_5500_5700),
+        .chan11a_turbo         = BM3(WT1_5210_5250,
+                                     WT1_5290_5290,
+                                     WT1_5760_5800),
+        .chan11b               = BM5(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2417_2432,
+                                     W1_2447_2457),
+        .chan11g               = BM5(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = WORA_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .dfsMask               = DFS_FCC3 | DFS_ETSI,
+        .pscan                 = PSCAN_WWR,
+        .flags                 = ADHOC_NO_11A,
+        .chan11a               = BM4(W1_5260_5320,
+                                     W1_5180_5240,
+                                     W1_5745_5825,
+                                     W1_5500_5700),
+        .chan11b               = BM7(W1_2412_2412,
+                                     W1_2437_2442,
+                                     W1_2462_2462,
+                                     W1_2472_2472,
+                                     W1_2417_2432,
+                                     W1_2447_2457,
+                                     W1_2467_2467),
+        .chan11g               = BM7(WG1_2412_2412,
+                                     WG1_2437_2442,
+                                     WG1_2462_2462,
+                                     WG1_2472_2472,
+                                     WG1_2417_2432,
+                                     WG1_2447_2457,
+                                     WG1_2467_2467),
+        .chan11g_turbo         = BM1(T3_2437_2437)},
+
+       {.regDmnEnum            = SR9_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .pscan                 = PSCAN_FCC | PSCAN_FCC_T,
+        .chan11g               = BM1(S1_912_917),
+        .chan11g_half          = BM1(S1_907_922_10),
+        .chan11g_quarter       = BM1(S1_907_922_5),
+       },
+
+       {.regDmnEnum            = XR9_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .pscan                 = PSCAN_FCC | PSCAN_FCC_T,
+        .chan11g               = BM1(S2_912_917),
+        .chan11g_half          = BM1(S2_907_922_10),
+        .chan11g_quarter       = BM1(S2_907_922_5),
+       },
+
+       {.regDmnEnum            = GZ901_WORLD,
+        .conformanceTestLimit  = NO_CTL,
+        .pscan                 = PSCAN_FCC | PSCAN_FCC_T,
+        .chan11g               = BM1(S1_913_918),
+        .chan11g_half          = BM1(S1_913_918_10),
+        .chan11g_quarter       = BM1(S1_908_923_5),
+       },
+
+       {.regDmnEnum            = NULL1,
+        .conformanceTestLimit  = NO_CTL,
+       }
+};
+
+struct cmode {
+       u_int   mode;
+       u_int   flags;
+};
+
+static const struct cmode modes[] = {
+       { HAL_MODE_TURBO,       CHANNEL_ST},    /* NB: 11a Static Turbo */
+       { HAL_MODE_11A,         CHANNEL_A},
+       { HAL_MODE_11B,         CHANNEL_B},
+       { HAL_MODE_11G,         CHANNEL_G},
+       { HAL_MODE_11G_TURBO,   CHANNEL_108G},
+       { HAL_MODE_11A_TURBO,   CHANNEL_108A},
+       { HAL_MODE_11A_QUARTER_RATE,    CHANNEL_A | CHANNEL_QUARTER},
+       { HAL_MODE_11A_HALF_RATE,       CHANNEL_A | CHANNEL_HALF},
+       { HAL_MODE_11G_QUARTER_RATE,    CHANNEL_G | CHANNEL_QUARTER},
+       { HAL_MODE_11G_HALF_RATE,       CHANNEL_G | CHANNEL_HALF},
+       { HAL_MODE_11NG_HT20,   CHANNEL_G_HT20},
+       { HAL_MODE_11NG_HT40PLUS,       CHANNEL_G_HT40PLUS},
+       { HAL_MODE_11NG_HT40MINUS,      CHANNEL_G_HT40MINUS},
+       { HAL_MODE_11NA_HT20,   CHANNEL_A_HT20},
+       { HAL_MODE_11NA_HT40PLUS,       CHANNEL_A_HT40PLUS},
+       { HAL_MODE_11NA_HT40MINUS,      CHANNEL_A_HT40MINUS},
+};
+
+static int
+chansort(const void *a, const void *b)
+{
+#define CHAN_FLAGS     (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)
+       const HAL_CHANNEL_INTERNAL *ca = a;
+       const HAL_CHANNEL_INTERNAL *cb = b;
+
+       return (ca->channel == cb->channel) ?
+               (ca->channelFlags & CHAN_FLAGS) -
+                       (cb->channelFlags & CHAN_FLAGS) :
+               ca->channel - cb->channel;
+#undef CHAN_FLAGS
+}
+typedef int ath_hal_cmp_t(const void *, const void *);
+static void ath_hal_sort(void *a, size_t n, size_t es, ath_hal_cmp_t *cmp);
+static COUNTRY_CODE_TO_ENUM_RD* findCountry(HAL_CTRY_CODE countryCode);
+static HAL_BOOL getWmRD(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country, uint16_t channelFlag, REG_DOMAIN *rd);
+
+
+static uint16_t
+getEepromRD(struct ath_hal *ah)
+{
+       return AH_PRIVATE(ah)->ah_currentRD &~ WORLDWIDE_ROAMING_FLAG;
+}
+
+/*
+ * Test to see if the bitmask array is all zeros
+ */
+static HAL_BOOL
+isChanBitMaskZero(const uint64_t *bitmask)
+{
+#if BMLEN > 2
+#error "add more cases"
+#endif
+#if BMLEN > 1
+       if (bitmask[1] != 0)
+               return AH_FALSE;
+#endif
+       return (bitmask[0] == 0);
+}
+
+/*
+ * Return whether or not the regulatory domain/country in EEPROM
+ * is acceptable.
+ */
+static HAL_BOOL
+isEepromValid(struct ath_hal *ah)
+{
+       uint16_t rd = getEepromRD(ah);
+       int i;
+
+       if (rd & COUNTRY_ERD_FLAG) {
+               uint16_t cc = rd &~ COUNTRY_ERD_FLAG;
+               for (i = 0; i < N(allCountries); i++)
+                       if (allCountries[i].countryCode == cc)
+                               return AH_TRUE;
+       } else {
+               for (i = 0; i < N(regDomainPairs); i++)
+                       if (regDomainPairs[i].regDmnEnum == rd)
+                               return AH_TRUE;
+       }
+       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+           "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd);
+       return AH_FALSE;
+}
+
+/*
+ * Returns whether or not the specified country code
+ * is allowed by the EEPROM setting
+ */
+static HAL_BOOL
+isCountryCodeValid(struct ath_hal *ah, HAL_CTRY_CODE cc)
+{
+       uint16_t rd;
+
+       /* Default setting requires no checks */
+       if (cc == CTRY_DEFAULT)
+               return AH_TRUE;
+#ifdef AH_DEBUG_COUNTRY
+       if (cc == CTRY_DEBUG)
+               return AH_TRUE;
+#endif
+       rd = getEepromRD(ah);
+       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: EEPROM regdomain 0x%x\n",
+           __func__, rd);
+
+       if (rd & COUNTRY_ERD_FLAG) {
+               /* EEP setting is a country - config shall match */
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: EEPROM setting is country code %u\n", __func__,
+                   rd &~ COUNTRY_ERD_FLAG);
+               return (cc == (rd & ~COUNTRY_ERD_FLAG));
+       } else if (rd == DEBUG_REG_DMN || rd == NO_ENUMRD) {
+               /* Set to Debug or AllowAnyCountry mode - allow any setting */
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: rd %d allowed\n",
+                   __func__, rd);
+               return AH_TRUE;
+#ifdef AH_SUPPORT_11D
+       } else  if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) {
+               int i;
+               for (i=0; i < N(allCountries); i++) {
+                       if (cc == allCountries[i].countryCode)
+                               return AH_TRUE;
+               }
+#endif
+       } else {
+               int i;
+               for (i = 0; i < N(allCountries); i++) {
+                       if (cc == allCountries[i].countryCode &&
+                           allCountries[i].regDmnEnum == rd)
+                               return AH_TRUE;
+               }
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Return the mask of available modes based on the hardware
+ * capabilities and the specified country code and reg domain.
+ */
+static u_int
+ath_hal_getwmodesnreg(struct ath_hal *ah,
+    const COUNTRY_CODE_TO_ENUM_RD *country, const REG_DOMAIN *rd5GHz)
+{
+#define        HAL_MODE_11G_ALL \
+       (HAL_MODE_11G | HAL_MODE_11G_TURBO | HAL_MODE_11G_QUARTER_RATE | \
+        HAL_MODE_11G_HALF_RATE)
+#define        HAL_MODE_11A_ALL \
+       (HAL_MODE_11A | HAL_MODE_11A_TURBO | HAL_MODE_TURBO | \
+        HAL_MODE_11A_QUARTER_RATE | HAL_MODE_11A_HALF_RATE)
+       u_int modesAvail;
+
+       /* Get modes that HW is capable of */
+       modesAvail = ath_hal_getWirelessModes(ah);
+
+       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+           "%s: wireless modes 0x%x cc %u rd %u\n",
+           __func__, modesAvail, country->countryCode, country->regDmnEnum);
+
+       /* Check country regulations for allowed modes */
+       if (!country->allow11g && (modesAvail & HAL_MODE_11G_ALL)) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow all 11g\n", __func__);
+               modesAvail &= ~HAL_MODE_11G_ALL;
+       }
+       if (isChanBitMaskZero(rd5GHz->chan11a) &&
+           (modesAvail & HAL_MODE_11A_ALL)) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow all 11a\n", __func__);
+               modesAvail &= ~HAL_MODE_11A_ALL;
+       }
+       if ((modesAvail & (HAL_MODE_11A_TURBO | HAL_MODE_TURBO)) &&
+           !country->allow11aTurbo) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow 11aTurbo\n", __func__);
+               modesAvail &= ~(HAL_MODE_11A_TURBO | HAL_MODE_TURBO);
+       }
+       if ((modesAvail & HAL_MODE_11G_TURBO) && !country->allow11gTurbo) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow 11gTurbo\n", __func__);
+               modesAvail &= ~HAL_MODE_11G_TURBO;
+       }
+
+       /* Check 11n operation */
+       if ((modesAvail & HAL_MODE_11NG_HT20) && !country->allow11ng20) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow 11g HT20\n", __func__);
+               modesAvail &= ~HAL_MODE_11NG_HT20;
+       }
+       if ((modesAvail & HAL_MODE_11NA_HT20) && !country->allow11na20) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow 11a HT20\n", __func__);
+               modesAvail &= ~HAL_MODE_11NA_HT20;
+       }
+       if ((modesAvail & HAL_MODE_11NG_HT40PLUS) && !country->allow11ng40) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow 11g HT40+\n", __func__);
+               modesAvail &= ~HAL_MODE_11NG_HT40PLUS;
+       }
+       if ((modesAvail & HAL_MODE_11NG_HT40MINUS) && !country->allow11ng40) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow 11g HT40-\n", __func__);
+               modesAvail &= ~HAL_MODE_11NG_HT40MINUS;
+       }
+       if ((modesAvail & HAL_MODE_11NA_HT40PLUS) && !country->allow11na40) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow 11a HT40+\n", __func__);
+               modesAvail &= ~HAL_MODE_11NA_HT40PLUS;
+       }
+       if ((modesAvail & HAL_MODE_11NA_HT40MINUS) && !country->allow11na40) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: disallow 11a HT40-\n", __func__);
+               modesAvail &= ~HAL_MODE_11NA_HT40MINUS;
+       }
+
+       return modesAvail;
+#undef HAL_MODE_11A_ALL
+#undef HAL_MODE_11G_ALL
+}
+
+/*
+ * Return the mask of available modes based on the hardware
+ * capabilities and the specified country code.
+ */
+
+u_int
+ath_hal_getwirelessmodes(struct ath_hal *ah, HAL_CTRY_CODE cc)
+{
+       COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL;
+       u_int mode = 0;
+       REG_DOMAIN rd;
+
+       country = findCountry(cc);
+       if (country != AH_NULL) {
+               if (getWmRD(ah, country, ~CHANNEL_2GHZ, &rd))
+                       mode = ath_hal_getwmodesnreg(ah, country, &rd);
+       }
+       return mode;
+}
+
+/*
+ * Return if device is public safety.
+ */
+HAL_BOOL
+ath_hal_ispublicsafetysku(struct ath_hal *ah)
+{
+       uint16_t rd = getEepromRD(ah);
+
+       switch (rd) {
+       case FCC4_FCCA:
+       case CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG:
+               return AH_TRUE;
+       case DEBUG_REG_DMN:
+       case NO_ENUMRD:
+               if (AH_PRIVATE(ah)->ah_countryCode == CTRY_UNITED_STATES_FCC49)
+                       return AH_TRUE;
+               break;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Return if device is actually operating in 900 MHz band.
+ */
+HAL_BOOL
+ath_hal_isgsmsku(struct ath_hal *ah)
+{
+       uint16_t rd = getEepromRD(ah);
+
+       switch (rd) {
+       case SR9_WORLD:
+       case XR9_WORLD:
+       case GZ901_WORLD:
+       case CTRY_SR9 | COUNTRY_ERD_FLAG:
+       case CTRY_XR9 | COUNTRY_ERD_FLAG:
+       case CTRY_GZ901 | COUNTRY_ERD_FLAG:
+               return AH_TRUE;
+       case DEBUG_REG_DMN:
+       case NO_ENUMRD:
+               return AH_PRIVATE(ah)->ah_countryCode == CTRY_SR9
+                      || AH_PRIVATE(ah)->ah_countryCode == CTRY_XR9
+                      || AH_PRIVATE(ah)->ah_countryCode == CTRY_GZ901
+                      ;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Find the pointer to the country element in the country table
+ * corresponding to the country code
+ */
+static COUNTRY_CODE_TO_ENUM_RD*
+findCountry(HAL_CTRY_CODE countryCode)
+{
+       int i;
+
+       for (i = 0; i < N(allCountries); i++) {
+               if (allCountries[i].countryCode == countryCode)
+                       return &allCountries[i];
+       }
+       return AH_NULL;         /* Not found */
+}
+
+/*
+ * Calculate a default country based on the EEPROM setting.
+ */
+static HAL_CTRY_CODE
+getDefaultCountry(struct ath_hal *ah)
+{
+       uint16_t rd;
+       int i;
+
+       rd = getEepromRD(ah);
+       if (rd & COUNTRY_ERD_FLAG) {
+               COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL;
+               uint16_t cc = rd & ~COUNTRY_ERD_FLAG;
+
+               country = findCountry(cc);
+               if (country != AH_NULL)
+                       return cc;
+       }
+       /*
+        * Check reg domains that have only one country
+        */
+       for (i = 0; i < N(regDomainPairs); i++)
+               if (regDomainPairs[i].regDmnEnum == rd) {
+                       if (regDomainPairs[i].singleCC != 0)
+                               return regDomainPairs[i].singleCC;
+                       else
+                               i = N(regDomainPairs);
+               }
+       return CTRY_DEFAULT;
+}
+
+static HAL_BOOL
+isValidRegDmn(int regDmn, REG_DOMAIN *rd)
+{
+       int i;
+
+       for (i = 0; i < N(regDomains); i++) {
+               if (regDomains[i].regDmnEnum == regDmn) {
+                       if (rd != AH_NULL) {
+                               OS_MEMCPY(rd, &regDomains[i],
+                                         sizeof(REG_DOMAIN));
+                       }
+                       return AH_TRUE;
+               }
+       }
+       return AH_FALSE;
+}
+
+static HAL_BOOL
+isValidRegDmnPair(int regDmnPair)
+{
+       int i;
+
+       if (regDmnPair == NO_ENUMRD)
+               return AH_FALSE;
+       for (i = 0; i < N(regDomainPairs); i++) {
+               if (regDomainPairs[i].regDmnEnum == regDmnPair)
+                       return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Return the Wireless Mode Regulatory Domain based
+ * on the country code and the wireless mode.
+ */
+static HAL_BOOL
+getWmRD(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country,
+       uint16_t channelFlag, REG_DOMAIN *rd)
+{
+       int regDmn;
+       REG_DMN_PAIR_MAPPING *regPair;
+       uint64_t flags;
+
+       if (country->countryCode == CTRY_DEFAULT) {
+               uint16_t rdnum = getEepromRD(ah);
+
+               if ((rdnum & COUNTRY_ERD_FLAG) == 0) {
+                       if (isValidRegDmn(rdnum, AH_NULL) ||
+                           isValidRegDmnPair(rdnum))
+                               regDmn = rdnum;
+                       else
+                               regDmn = country->regDmnEnum;
+               } else
+                       regDmn = country->regDmnEnum;
+       } else
+               regDmn = country->regDmnEnum;
+       regPair = AH_NULL;
+       flags = NO_REQ;
+       if ((regDmn & MULTI_DOMAIN_MASK) == 0) {
+               int i;
+
+               for (i = 0; i < N(regDomainPairs); i++) {
+                       if (regDomainPairs[i].regDmnEnum == regDmn) {
+                               regPair = &regDomainPairs[i];
+                               break;
+                       }
+               }
+               if (regPair == AH_NULL) {
+                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                           "%s: Failed to find reg domain pair %u\n",
+                           __func__, regDmn);
+                       return AH_FALSE;
+               }
+               if (channelFlag & CHANNEL_2GHZ) {
+                       regDmn = regPair->regDmn2GHz;
+                       flags = regPair->flags2GHz;
+               } else {
+                       regDmn = regPair->regDmn5GHz;
+                       flags = regPair->flags5GHz;
+               }
+       }
+
+       /*
+        * We either started with a unitary reg domain or we've found the
+        * unitary reg domain of the pair
+        */
+       if (isValidRegDmn(regDmn, rd)) {
+               if (regPair != AH_NULL)
+                       rd->pscan &= regPair->pscanMask;
+               if ((country->regDmnEnum & MULTI_DOMAIN_MASK) == 0 &&
+                   flags != NO_REQ)
+                       rd->flags = flags;
+               return AH_TRUE;
+       } else {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: Failed to find unitary reg domain %u\n", __func__,
+                   country->regDmnEnum);
+               return AH_FALSE;
+       }
+}
+
+static HAL_BOOL
+IS_BIT_SET(int bit, const uint64_t bitmask[])
+{
+       int byteOffset, bitnum;
+       uint64_t val;
+
+       byteOffset = bit/64;
+       bitnum = bit - byteOffset*64;
+       val = ((uint64_t) 1) << bitnum;
+       return (bitmask[byteOffset] & val) != 0;
+}
+
+/* Add given regclassid into regclassids array upto max of maxregids */
+static void
+ath_add_regclassid(uint8_t *regclassids, u_int maxregids,
+       u_int *nregids, uint8_t regclassid)
+{
+       int i;
+
+       /* Is regclassid valid? */
+       if (regclassid == 0)
+               return;
+
+       for (i = 0; i < maxregids; i++) {
+               if (regclassids[i] == regclassid)       /* already present */
+                       return;
+               if (regclassids[i] == 0) {              /* free slot */
+                       regclassids[i] = regclassid;
+                       (*nregids)++;
+                       return;
+               }
+       }
+}
+
+/*
+ * Setup the channel list based on the information in the EEPROM and
+ * any supplied country code.  Note that we also do a bunch of EEPROM
+ * verification here and setup certain regulatory-related access
+ * control data used later on.
+ */
+
+HAL_BOOL
+ath_hal_init_channels(struct ath_hal *ah,
+                     HAL_CHANNEL *chans, u_int maxchans, u_int *nchans,
+                     uint8_t *regclassids, u_int maxregids, u_int *nregids,
+                     HAL_CTRY_CODE cc, u_int modeSelect,
+                     HAL_BOOL enableOutdoor, HAL_BOOL enableExtendedChannels)
+{
+#define CHANNEL_HALF_BW                10
+#define CHANNEL_QUARTER_BW     5
+       u_int modesAvail;
+       uint16_t maxChan;
+       COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL;
+       REG_DOMAIN rd5GHz, rd2GHz;
+       const struct cmode *cm;
+       HAL_CHANNEL_INTERNAL *ichans = &AH_PRIVATE(ah)->ah_channels[0];
+       int next, b;
+       uint8_t ctl;
+
+       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u mode 0x%x%s%s\n",
+           __func__, cc, modeSelect, enableOutdoor? " Enable outdoor" : " ",
+           enableExtendedChannels ? " Enable ecm" : "");
+
+       /*
+        * Validate the EEPROM setting and setup defaults
+        */
+       if (!isEepromValid(ah)) {
+               /*
+                * Don't return any channels if the EEPROM has an
+                * invalid regulatory domain/country code setting.
+                */
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: invalid EEPROM contents\n",__func__);
+               return AH_FALSE;
+       }
+
+       AH_PRIVATE(ah)->ah_countryCode = getDefaultCountry(ah);
+
+#ifndef AH_SUPPORT_11D
+       if (AH_PRIVATE(ah)->ah_countryCode == CTRY_DEFAULT) {
+#endif
+               /*
+                * We now have enough state to validate any country code
+                * passed in by the caller.
+                */
+               if (!isCountryCodeValid(ah, cc)) {
+                       /* NB: Atheros silently ignores invalid country codes */
+                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                           "%s: invalid country code %d\n", __func__, cc);
+                       return AH_FALSE;
+               }
+               AH_PRIVATE(ah)->ah_countryCode = cc & COUNTRY_CODE_MASK;
+#ifndef AH_SUPPORT_11D
+       }
+#endif
+
+       /* Get pointers to the country element and the reg domain elements */
+       country = findCountry(AH_PRIVATE(ah)->ah_countryCode);
+
+       if (country == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "NULL Country!, cc= %d\n",
+                   AH_PRIVATE(ah)->ah_countryCode);
+               return AH_FALSE;
+       }
+
+       if (!getWmRD(ah, country, ~CHANNEL_2GHZ, &rd5GHz)) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: no unitary 5GHz regdomain for country %u\n",
+                    __func__, AH_PRIVATE(ah)->ah_countryCode);
+               return AH_FALSE;
+       }
+       if (!getWmRD(ah, country, CHANNEL_2GHZ, &rd2GHz)) {
+               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                   "%s: no unitary 2GHz regdomain for country %u\n",
+                   __func__, AH_PRIVATE(ah)->ah_countryCode);
+               return AH_FALSE;
+       }
+
+       modesAvail = ath_hal_getwmodesnreg(ah, country, &rd5GHz);
+       maxChan = !enableOutdoor ? country->outdoorChanStart : 7000;
+
+       if (maxchans > N(AH_PRIVATE(ah)->ah_channels))
+               maxchans = N(AH_PRIVATE(ah)->ah_channels);
+       next = 0;
+       for (cm = modes; cm < &modes[N(modes)]; cm++) {
+               uint16_t c, c_hi, c_lo;
+               uint64_t *channelBM = AH_NULL;
+               REG_DOMAIN *rd = AH_NULL;
+               REG_DMN_FREQ_BAND *fband = AH_NULL,*freqs;
+               int low_adj, hi_adj, channelSep, lastc;
+
+               if ((cm->mode & modeSelect) == 0) {
+                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                           "%s: skip mode 0x%x flags 0x%x\n",
+                           __func__, cm->mode, cm->flags);
+                       continue;
+               }
+               if ((cm->mode & modesAvail) == 0) {
+                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                           "%s: !avail mode 0x%x (0x%x) flags 0x%x\n",
+                           __func__, modesAvail, cm->mode, cm->flags);
+                       continue;
+               }
+               if (!ath_hal_getChannelEdges(ah, cm->flags, &c_lo, &c_hi)) {
+                       /* channel not supported by hardware, skip it */
+                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                           "%s: channels 0x%x not supported by hardware\n",
+                           __func__,cm->flags);
+                       continue;
+               }
+               switch (cm->mode) {
+               case HAL_MODE_TURBO:
+                       rd = &rd5GHz;
+                       channelBM = rd->chan11a_turbo;
+                       freqs = &regDmn5GhzTurboFreq[0];
+                       ctl = rd->conformanceTestLimit | CTL_TURBO;
+                       break;
+               case HAL_MODE_11A:
+               case HAL_MODE_11A_HALF_RATE:
+               case HAL_MODE_11A_QUARTER_RATE:
+               case HAL_MODE_11NA_HT20:
+               case HAL_MODE_11NA_HT40PLUS:
+               case HAL_MODE_11NA_HT40MINUS:
+                       rd = &rd5GHz;
+                       if (cm->mode == HAL_MODE_11A_HALF_RATE)
+                               channelBM = rd->chan11a_half;
+                       else if (cm->mode == HAL_MODE_11A_QUARTER_RATE)
+                               channelBM = rd->chan11a_quarter;
+                       else
+                               channelBM = rd->chan11a;
+                       freqs = &regDmn5GhzFreq[0];
+                       ctl = rd->conformanceTestLimit;
+                       break;
+               case HAL_MODE_11B:
+                       rd = &rd2GHz;
+                       channelBM = rd->chan11b;
+                       freqs = &regDmn2GhzFreq[0];
+                       ctl = rd->conformanceTestLimit | CTL_11B;
+                       break;
+               case HAL_MODE_11G:
+               case HAL_MODE_11G_HALF_RATE:
+               case HAL_MODE_11G_QUARTER_RATE:
+               case HAL_MODE_11NG_HT20:
+               case HAL_MODE_11NG_HT40PLUS:
+               case HAL_MODE_11NG_HT40MINUS:
+                       rd = &rd2GHz;
+                       if (cm->mode == HAL_MODE_11G_HALF_RATE)
+                               channelBM = rd->chan11g_half;
+                       else if (cm->mode == HAL_MODE_11G_QUARTER_RATE)
+                               channelBM = rd->chan11g_quarter;
+                       else
+                               channelBM = rd->chan11g;
+                       freqs = &regDmn2Ghz11gFreq[0];
+                       ctl = rd->conformanceTestLimit | CTL_11G;
+                       break;
+               case HAL_MODE_11G_TURBO:
+                       rd = &rd2GHz;
+                       channelBM = rd->chan11g_turbo;
+                       freqs = &regDmn2Ghz11gTurboFreq[0];
+                       ctl = rd->conformanceTestLimit | CTL_108G;
+                       break;
+               case HAL_MODE_11A_TURBO:
+                       rd = &rd5GHz;
+                       channelBM = rd->chan11a_dyn_turbo;
+                       freqs = &regDmn5GhzTurboFreq[0];
+                       ctl = rd->conformanceTestLimit | CTL_108G;
+                       break;
+               default:
+                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                           "%s: Unkonwn HAL mode 0x%x\n", __func__, cm->mode);
+                       continue;
+               }
+               if (isChanBitMaskZero(channelBM))
+                       continue;
+               /*
+                * Setup special handling for HT40 channels; e.g.
+                * 5G HT40 channels require 40Mhz channel separation.
+                */
+               hi_adj = (cm->mode == HAL_MODE_11NA_HT40PLUS ||
+                   cm->mode == HAL_MODE_11NG_HT40PLUS) ? -20 : 0;
+               low_adj = (cm->mode == HAL_MODE_11NA_HT40MINUS ||
+                   cm->mode == HAL_MODE_11NG_HT40MINUS) ? 20 : 0;
+               channelSep = (cm->mode == HAL_MODE_11NA_HT40PLUS ||
+                   cm->mode == HAL_MODE_11NA_HT40MINUS) ? 40 : 0;
+
+               for (b = 0; b < 64*BMLEN; b++) {
+                       if (!IS_BIT_SET(b, channelBM))
+                               continue;
+                       fband = &freqs[b];
+                       lastc = 0;
+
+                       ath_add_regclassid(regclassids, maxregids,
+                                       nregids, fband->regClassId);
+
+                       for (c = fband->lowChannel + low_adj;
+                            c <= fband->highChannel + hi_adj;
+                            c += fband->channelSep) {
+                               HAL_CHANNEL_INTERNAL icv;
+
+                               if (!(c_lo <= c && c <= c_hi)) {
+                                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                                           "%s: c %u out of range [%u..%u]\n",
+                                           __func__, c, c_lo, c_hi);
+                                       continue;
+                               }
+                               if (((c+fband->channelSep)/2) > (maxChan+HALF_MAXCHANBW)) {
+                                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                                           "%s: c %u > maxChan %u\n",
+                                           __func__, c, maxChan);
+                                       continue;
+                               }
+                               if (next >= maxchans){
+                                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                                           "%s: too many channels for channel table\n",
+                                           __func__);
+                                       goto done;
+                               }
+                               if ((fband->usePassScan & IS_ECM_CHAN) &&
+                                   !enableExtendedChannels) {
+                                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                                           "Skipping ecm channel\n");
+                                       continue;
+                               }
+                               /* XXX needs to be in ath_hal_checkchannel */
+                               if ((rd->flags & NO_HOSTAP) &&
+                                   (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP)) {
+                                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                                           "Skipping HOSTAP channel\n");
+                                       continue;
+                               }
+                               /*
+                                * Make sure that channel separation
+                                * meets the requirement.
+                                */
+                               if (lastc && channelSep &&
+                                   (c-lastc) < channelSep)
+                                       continue;
+
+                               OS_MEMZERO(&icv, sizeof(icv));
+                               icv.channel = c;
+                               icv.channelFlags = cm->flags;
+                               icv.maxRegTxPower = fband->powerDfs;
+                               icv.antennaMax = fband->antennaMax;
+                               icv.regDmnFlags = rd->flags;
+                               icv.conformanceTestLimit = ctl;
+                               if (fband->usePassScan & rd->pscan)
+                                       icv.channelFlags |= CHANNEL_PASSIVE;
+                               else
+                                       icv.channelFlags &= ~CHANNEL_PASSIVE;
+                               lastc = c;
+                               if (fband->useDfs & rd->dfsMask) {
+                                       /* DFS and HT40 don't mix */
+                                       if (cm->mode == HAL_MODE_11NA_HT40PLUS ||
+                                           cm->mode == HAL_MODE_11NA_HT40MINUS)
+                                               continue;
+                                       icv.privFlags = CHANNEL_DFS;
+                               } else
+                                       icv.privFlags = 0;
+                               if (rd->flags & LIMIT_FRAME_4MS)
+                                       icv.privFlags |= CHANNEL_4MS_LIMIT;
+
+                               ichans[next++] = icv;
+                       }
+               }
+       }
+done:
+       if (next != 0) {
+               int i;
+
+               /* XXX maxchans set above so this cannot happen? */
+               if (next > N(AH_PRIVATE(ah)->ah_channels)) {
+                       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
+                           "%s: too many channels %u; truncating to %u\n",
+                           __func__, next,
+                           (int) N(AH_PRIVATE(ah)->ah_channels));
+                       next = N(AH_PRIVATE(ah)->ah_channels);
+               }
+
+               /*
+                * Keep a private copy of the channel list so we can
+                * constrain future requests to only these channels
+                */
+               ath_hal_sort(ichans, next, sizeof(HAL_CHANNEL_INTERNAL),
+                   chansort);
+               AH_PRIVATE(ah)->ah_nchan = next;
+
+               /*
+                * Copy the channel list to the public channel list
+                */
+               for (i = 0; i < next; i++) {
+                       chans[i].channel = ichans[i].channel;
+                       chans[i].channelFlags = ichans[i].channelFlags;
+                       chans[i].privFlags = ichans[i].privFlags;
+                       chans[i].maxRegTxPower = ichans[i].maxRegTxPower;
+               }
+               /*
+                * Retrieve power limits.
+                */
+               ath_hal_getpowerlimits(ah, chans, next);
+               for (i = 0; i < next; i++) {
+                       ichans[i].maxTxPower = chans[i].maxTxPower;
+                       ichans[i].minTxPower = chans[i].minTxPower;
+               }
+       }
+       *nchans = next;
+       /* XXX copy private setting to public area */
+       ah->ah_countryCode = AH_PRIVATE(ah)->ah_countryCode;
+       return (next != 0);
+#undef CHANNEL_HALF_BW
+#undef CHANNEL_QUARTER_BW
+}
+
+/*
+ * Return whether or not the specified channel is ok to use
+ * based on the current regulatory domain constraints and
+ * DFS interference.
+ */
+HAL_CHANNEL_INTERNAL *
+ath_hal_checkchannel(struct ath_hal *ah, const HAL_CHANNEL *c)
+{
+#define CHAN_FLAGS     (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)
+       HAL_CHANNEL_INTERNAL *base, *cc;
+       /* NB: be wary of user-specified channel flags */
+       int flags = c->channelFlags & CHAN_FLAGS;
+       int n, lim, d;
+
+       /*
+        * Check current channel to avoid the lookup.
+        */
+       cc = AH_PRIVATE(ah)->ah_curchan;
+       if (cc != AH_NULL && cc->channel == c->channel &&
+           (cc->channelFlags & CHAN_FLAGS) == flags) {
+               if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
+                   (cc->channelFlags & CHANNEL_DFS))
+                       return AH_NULL;
+               else
+                       return cc;
+       }
+
+       /* binary search based on known sorting order */
+       base = AH_PRIVATE(ah)->ah_channels;
+       n = AH_PRIVATE(ah)->ah_nchan;
+       /* binary search based on known sorting order */
+       for (lim = n; lim != 0; lim >>= 1) {
+               cc = &base[lim>>1];
+               d = c->channel - cc->channel;
+               if (d == 0) {
+                       if ((cc->channelFlags & CHAN_FLAGS) == flags) {
+                               if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
+                                   (cc->channelFlags & CHANNEL_DFS))
+                                       return AH_NULL;
+                               else
+                                       return cc;
+                       }
+                       d = flags - (cc->channelFlags & CHAN_FLAGS);
+               }
+               if (d > 0) {
+                       base = cc + 1;
+                       lim--;
+               }
+       }
+       HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: no match for %u/0x%x\n",
+          __func__, c->channel, c->channelFlags);
+       return AH_NULL;
+#undef CHAN_FLAGS
+}
+
+/*
+ * Return the max allowed antenna gain and apply any regulatory
+ * domain specific changes.
+ *
+ * NOTE: a negative reduction is possible in RD's that only
+ * measure radiated power (e.g., ETSI) which would increase
+ * that actual conducted output power (though never beyond
+ * the calibrated target power).
+ */
+u_int
+ath_hal_getantennareduction(struct ath_hal *ah, HAL_CHANNEL *chan, u_int twiceGain)
+{
+       HAL_CHANNEL_INTERNAL *ichan=AH_NULL;
+       int8_t antennaMax;
+
+       if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL) {
+               antennaMax = twiceGain - ichan->antennaMax*2;
+               return (antennaMax < 0) ? 0 : antennaMax;
+       } else {
+               /* Failed to find the correct index - may be a debug channel */
+               return 0;
+       }
+}
+
+
+/* XXX - maybe move ctl decision into channel set area or
+ into the tables so no decision is needed in the code */
+
+#define isWwrSKU(_ah) \
+       ((getEepromRD((_ah)) & WORLD_SKU_MASK) == WORLD_SKU_PREFIX || \
+         getEepromRD(_ah) == WORLD)
+
+
+/*
+ * Return the test group from the specified channel from
+ * the regulatory table.
+ *
+ * TODO: CTL for 11B CommonMode when regulatory domain is unknown
+ */
+u_int
+ath_hal_getctl(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       u_int ctl = NO_CTL;
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       /* Special CTL to signify WWR SKU without a known country */
+       if (AH_PRIVATE(ah)->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)) {
+               if (IS_CHAN_B(chan)) {
+                       ctl = SD_NO_CTL | CTL_11B;
+               } else if (IS_CHAN_G(chan)) {
+                       ctl = SD_NO_CTL | CTL_11G;
+               } else if (IS_CHAN_108G(chan)) {
+                       ctl = SD_NO_CTL | CTL_108G;
+               } else if (IS_CHAN_T(chan)) {
+                       ctl = SD_NO_CTL | CTL_TURBO;
+               } else {
+                       ctl = SD_NO_CTL | CTL_11A;
+               }
+       } else {
+               if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL) {
+                       ctl = ichan->conformanceTestLimit;
+                       /* limit 11G OFDM power */
+                       if (IS_CHAN_PUREG(chan) &&
+                           (ctl & CTL_MODE_M) == CTL_11B)
+                               ctl = (ctl &~ CTL_MODE_M) | CTL_11G;
+               }
+       }
+       return ctl;
+}
+
+/*
+ * Return whether or not a noise floor check is required in
+ * the current regulatory domain for the specified channel.
+ */
+HAL_BOOL
+ath_hal_getnfcheckrequired(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL)
+               return ((ichan->regDmnFlags & NEED_NFC) ? AH_TRUE : AH_FALSE);
+       return AH_FALSE;
+}
+
+/*
+ * Insertion sort.
+ */
+#define swap(_a, _b, _size) {                  \
+       uint8_t *s = _b;                        \
+       int i = _size;                          \
+       do {                                    \
+               uint8_t tmp = *_a;              \
+               *_a++ = *s;                     \
+               *s++ = tmp;                     \
+       } while (--i);                          \
+       _a -= _size;                            \
+}
+
+static void
+ath_hal_sort(void *a, size_t n, size_t size, ath_hal_cmp_t *cmp)
+{
+       uint8_t *aa = a;
+       uint8_t *ai, *t;
+
+       for (ai = aa+size; --n >= 1; ai += size)
+               for (t = ai; t > aa; t -= size) {
+                       uint8_t *u = t - size;
+                       if (cmp(u, t) <= 0)
+                               break;
+                       swap(u, t, size);
+               }
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_soc.h  2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_soc.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AH_SOC_H_
+#define _ATH_AH_SOC_H_
+/*
+ * Atheros System on Chip (SoC) public definitions.
+ */
+
+/*
+ * This is board-specific data that is stored in a "known"
+ * location in flash.  To find the start of this data search
+ * back from the (aliased) end of flash by 0x1000 bytes at a
+ * time until you find the string "5311", which marks the
+ * start of Board Configuration.  Typically one gives up if
+ * more than 500KB is searched.
+ */
+struct ar531x_boarddata {
+       uint32_t magic;             /* board data is valid */
+#define AR531X_BD_MAGIC 0x35333131   /* "5311", for all 531x platforms */
+       uint16_t cksum;             /* checksum (starting with BD_REV 2) */
+       uint16_t rev;               /* revision of this struct */
+#define BD_REV  4
+       char   boardName[64];        /* Name of board */
+       uint16_t major;             /* Board major number */
+       uint16_t minor;             /* Board minor number */
+       uint32_t config;            /* Board configuration */
+#define BD_ENET0        0x00000001   /* ENET0 is stuffed */
+#define BD_ENET1        0x00000002   /* ENET1 is stuffed */
+#define BD_UART1        0x00000004   /* UART1 is stuffed */
+#define BD_UART0        0x00000008   /* UART0 is stuffed (dma) */
+#define BD_RSTFACTORY   0x00000010   /* Reset factory defaults stuffed */
+#define BD_SYSLED       0x00000020   /* System LED stuffed */
+#define BD_EXTUARTCLK   0x00000040   /* External UART clock */
+#define BD_CPUFREQ      0x00000080   /* cpu freq is valid in nvram */
+#define BD_SYSFREQ      0x00000100   /* sys freq is set in nvram */
+#define BD_WLAN0        0x00000200   /* Enable WLAN0 */
+#define BD_MEMCAP       0x00000400   /* CAP SDRAM @ memCap for testing */
+#define BD_DISWATCHDOG  0x00000800   /* disable system watchdog */
+#define BD_WLAN1        0x00001000   /* Enable WLAN1 (ar5212) */
+#define BD_ISCASPER     0x00002000   /* FLAG for AR2312 */
+#define BD_WLAN0_2G_EN  0x00004000   /* FLAG for radio0_2G */
+#define BD_WLAN0_5G_EN  0x00008000   /* FLAG for radio0_2G */
+#define BD_WLAN1_2G_EN  0x00020000   /* FLAG for radio0_2G */
+#define BD_WLAN1_5G_EN  0x00040000   /* FLAG for radio0_2G */
+       uint16_t resetConfigGpio;   /* Reset factory GPIO pin */
+       uint16_t sysLedGpio;        /* System LED GPIO pin */
+
+       uint32_t cpuFreq;           /* CPU core frequency in Hz */
+       uint32_t sysFreq;           /* System frequency in Hz */
+       uint32_t cntFreq;           /* Calculated C0_COUNT frequency */
+
+       uint8_t  wlan0Mac[6];
+       uint8_t  enet0Mac[6];
+       uint8_t  enet1Mac[6];
+
+       uint16_t pciId;             /* Pseudo PCIID for common code */
+       uint16_t memCap;            /* cap bank1 in MB */
+
+       /* version 3 */
+       uint8_t  wlan1Mac[6];       /* (ar5212) */
+};
+
+/*
+ * Board support data.  The driver is required to locate
+ * and fill-in this information before passing a reference to
+ * this structure as the HAL_BUS_TAG parameter supplied to
+ * ath_hal_attach.
+ */
+struct ar531x_config {
+       const struct ar531x_boarddata *board;   /* board config data */
+       const char      *radio;                 /* radio config data */
+       int             unit;                   /* unit number [0, 1] */
+       void            *tag;                   /* bus space tag */
+};
+#endif /* _ATH_AH_SOC_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_decode.h       2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_decode.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#ifndef _ATH_AH_DECODE_H_
+#define _ATH_AH_DECODE_H_
+/*
+ * Register tracing support.
+ *
+ * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
+ * writes to the file /tmp/ath_hal.log.  The file format is a simple
+ * fixed-size array of records.  When done logging set hw.ath.hal.alq=0
+ * and then decode the file with the arcode program (that is part of the
+ * HAL).  If you start+stop tracing the data will be appended to an
+ * existing file.
+ */
+struct athregrec {
+       uint32_t        op      : 8,
+                       reg     : 24;
+       uint32_t        val;
+};
+
+enum {
+       OP_READ         = 0,            /* register read */
+       OP_WRITE        = 1,            /* register write */
+       OP_DEVICE       = 2,            /* device identification */
+       OP_MARK         = 3,            /* application marker */
+};
+
+enum {
+       AH_MARK_RESET,                  /* ar*Reset entry, bChannelChange */
+       AH_MARK_RESET_LINE,             /* ar*_reset.c, line %d */
+       AH_MARK_RESET_DONE,             /* ar*Reset exit, error code */
+       AH_MARK_CHIPRESET,              /* ar*ChipReset, channel num */
+       AH_MARK_PERCAL,                 /* ar*PerCalibration, channel num */
+       AH_MARK_SETCHANNEL,             /* ar*SetChannel, channel num */
+       AH_MARK_ANI_RESET,              /* ar*AniReset, opmode */
+       AH_MARK_ANI_POLL,               /* ar*AniReset, listen time */
+       AH_MARK_ANI_CONTROL,            /* ar*AniReset, cmd */
+};
+#endif /* _ATH_AH_DECODE_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah.h      2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,899 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+
+#ifndef _ATH_AH_H_
+#define _ATH_AH_H_
+/*
+ * Atheros Hardware Access Layer
+ *
+ * Clients of the HAL call ath_hal_attach to obtain a reference to an ath_hal
+ * structure for use with the device.  Hardware-related operations that
+ * follow must call back into the HAL through interface, supplying the
+ * reference as the first parameter.
+ */
+
+#include "ah_osdep.h"
+
+/*
+ * __ahdecl is analogous to _cdecl; it defines the calling
+ * convention used within the HAL.  For most systems this
+ * can just default to be empty and the compiler will (should)
+ * use _cdecl.  For systems where _cdecl is not compatible this
+ * must be defined.  See linux/ah_osdep.h for an example.
+ */
+#ifndef __ahdecl
+#define __ahdecl
+#endif
+
+/*
+ * Status codes that may be returned by the HAL.  Note that
+ * interfaces that return a status code set it only when an
+ * error occurs--i.e. you cannot check it for success.
+ */
+typedef enum {
+       HAL_OK          = 0,    /* No error */
+       HAL_ENXIO       = 1,    /* No hardware present */
+       HAL_ENOMEM      = 2,    /* Memory allocation failed */
+       HAL_EIO         = 3,    /* Hardware didn't respond as expected */
+       HAL_EEMAGIC     = 4,    /* EEPROM magic number invalid */
+       HAL_EEVERSION   = 5,    /* EEPROM version invalid */
+       HAL_EELOCKED    = 6,    /* EEPROM unreadable */
+       HAL_EEBADSUM    = 7,    /* EEPROM checksum invalid */
+       HAL_EEREAD      = 8,    /* EEPROM read problem */
+       HAL_EEBADMAC    = 9,    /* EEPROM mac address invalid */
+       HAL_EESIZE      = 10,   /* EEPROM size not supported */
+       HAL_EEWRITE     = 11,   /* Attempt to change write-locked EEPROM */
+       HAL_EINVAL      = 12,   /* Invalid parameter to function */
+       HAL_ENOTSUPP    = 13,   /* Hardware revision not supported */
+       HAL_ESELFTEST   = 14,   /* Hardware self-test failed */
+       HAL_EINPROGRESS = 15,   /* Operation incomplete */
+} HAL_STATUS;
+
+typedef enum {
+       AH_FALSE = 0,           /* NB: lots of code assumes false is zero */
+       AH_TRUE  = 1,
+} HAL_BOOL;
+
+typedef enum {
+       HAL_CAP_REG_DMN         = 0,    /* current regulatory domain */
+       HAL_CAP_CIPHER          = 1,    /* hardware supports cipher */
+       HAL_CAP_TKIP_MIC        = 2,    /* handle TKIP MIC in hardware */
+       HAL_CAP_TKIP_SPLIT      = 3,    /* hardware TKIP uses split keys */
+       HAL_CAP_PHYCOUNTERS     = 4,    /* hardware PHY error counters */
+       HAL_CAP_DIVERSITY       = 5,    /* hardware supports fast diversity */
+       HAL_CAP_KEYCACHE_SIZE   = 6,    /* number of entries in key cache */
+       HAL_CAP_NUM_TXQUEUES    = 7,    /* number of hardware xmit queues */
+       HAL_CAP_VEOL            = 9,    /* hardware supports virtual EOL */
+       HAL_CAP_PSPOLL          = 10,   /* hardware has working PS-Poll support */
+       HAL_CAP_DIAG            = 11,   /* hardware diagnostic support */
+       HAL_CAP_COMPRESSION     = 12,   /* hardware supports compression */
+       HAL_CAP_BURST           = 13,   /* hardware supports packet bursting */
+       HAL_CAP_FASTFRAME       = 14,   /* hardware supoprts fast frames */
+       HAL_CAP_TXPOW           = 15,   /* global tx power limit  */
+       HAL_CAP_TPC             = 16,   /* per-packet tx power control  */
+       HAL_CAP_PHYDIAG         = 17,   /* hardware phy error diagnostic */
+       HAL_CAP_BSSIDMASK       = 18,   /* hardware supports bssid mask */
+       HAL_CAP_MCAST_KEYSRCH   = 19,   /* hardware has multicast key search */
+       HAL_CAP_TSF_ADJUST      = 20,   /* hardware has beacon tsf adjust */
+       /* 21 was HAL_CAP_XR */
+       HAL_CAP_WME_TKIPMIC     = 22,   /* hardware can support TKIP MIC when WMM is turned on */
+       /* 23 was HAL_CAP_CHAN_HALFRATE */
+       /* 24 was HAL_CAP_CHAN_QUARTERRATE */
+       HAL_CAP_RFSILENT        = 25,   /* hardware has rfsilent support  */
+       HAL_CAP_TPC_ACK         = 26,   /* ack txpower with per-packet tpc */
+       HAL_CAP_TPC_CTS         = 27,   /* cts txpower with per-packet tpc */
+       HAL_CAP_11D             = 28,   /* 11d beacon support for changing cc */
+       HAL_CAP_INTMIT          = 29,   /* interference mitigation */
+       HAL_CAP_RXORN_FATAL     = 30,   /* HAL_INT_RXORN treated as fatal */
+       HAL_CAP_HT              = 31,   /* hardware can support HT */
+       HAL_CAP_TX_CHAINMASK    = 32,   /* mask of TX chains supported */
+       HAL_CAP_RX_CHAINMASK    = 33,   /* mask of RX chains supported */
+       HAL_CAP_RXTSTAMP_PREC   = 34,   /* rx desc tstamp precision (bits) */
+       HAL_CAP_BB_HANG         = 35,   /* can baseband hang */
+       HAL_CAP_MAC_HANG        = 36,   /* can MAC hang */
+} HAL_CAPABILITY_TYPE;
+
+/*
+ * "States" for setting the LED.  These correspond to
+ * the possible 802.11 operational states and there may
+ * be a many-to-one mapping between these states and the
+ * actual hardware state for the LED's (i.e. the hardware
+ * may have fewer states).
+ */
+typedef enum {
+       HAL_LED_INIT    = 0,
+       HAL_LED_SCAN    = 1,
+       HAL_LED_AUTH    = 2,
+       HAL_LED_ASSOC   = 3,
+       HAL_LED_RUN     = 4
+} HAL_LED_STATE;
+
+/*
+ * Transmit queue types/numbers.  These are used to tag
+ * each transmit queue in the hardware and to identify a set
+ * of transmit queues for operations such as start/stop dma.
+ */
+typedef enum {
+       HAL_TX_QUEUE_INACTIVE   = 0,            /* queue is inactive/unused */
+       HAL_TX_QUEUE_DATA       = 1,            /* data xmit q's */
+       HAL_TX_QUEUE_BEACON     = 2,            /* beacon xmit q */
+       HAL_TX_QUEUE_CAB        = 3,            /* "crap after beacon" xmit q */
+       HAL_TX_QUEUE_UAPSD      = 4,            /* u-apsd power save xmit q */
+} HAL_TX_QUEUE;
+
+#define        HAL_NUM_TX_QUEUES       10              /* max possible # of queues */
+
+/*
+ * Transmit queue subtype.  These map directly to
+ * WME Access Categories (except for UPSD).  Refer
+ * to Table 5 of the WME spec.
+ */
+typedef enum {
+       HAL_WME_AC_BK   = 0,                    /* background access category */
+       HAL_WME_AC_BE   = 1,                    /* best effort access category*/
+       HAL_WME_AC_VI   = 2,                    /* video access category */
+       HAL_WME_AC_VO   = 3,                    /* voice access category */
+       HAL_WME_UPSD    = 4,                    /* uplink power save */
+} HAL_TX_QUEUE_SUBTYPE;
+
+/*
+ * Transmit queue flags that control various
+ * operational parameters.
+ */
+typedef enum {
+       /*
+        * Per queue interrupt enables.  When set the associated
+        * interrupt may be delivered for packets sent through
+        * the queue.  Without these enabled no interrupts will
+        * be delivered for transmits through the queue.
+        */
+       HAL_TXQ_TXOKINT_ENABLE     = 0x0001,    /* enable TXOK interrupt */
+       HAL_TXQ_TXERRINT_ENABLE    = 0x0001,    /* enable TXERR interrupt */
+       HAL_TXQ_TXDESCINT_ENABLE   = 0x0002,    /* enable TXDESC interrupt */
+       HAL_TXQ_TXEOLINT_ENABLE    = 0x0004,    /* enable TXEOL interrupt */
+       HAL_TXQ_TXURNINT_ENABLE    = 0x0008,    /* enable TXURN interrupt */
+       /*
+        * Enable hardware compression for packets sent through
+        * the queue.  The compression buffer must be setup and
+        * packets must have a key entry marked in the tx descriptor.
+        */
+       HAL_TXQ_COMPRESSION_ENABLE  = 0x0010,   /* enable h/w compression */
+       /*
+        * Disable queue when veol is hit or ready time expires.
+        * By default the queue is disabled only on reaching the
+        * physical end of queue (i.e. a null link ptr in the
+        * descriptor chain).
+        */
+       HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE = 0x0020,
+       /*
+        * Schedule frames on delivery of a DBA (DMA Beacon Alert)
+        * event.  Frames will be transmitted only when this timer
+        * fires, e.g to transmit a beacon in ap or adhoc modes.
+        */
+       HAL_TXQ_DBA_GATED           = 0x0040,   /* schedule based on DBA */
+       /*
+        * Each transmit queue has a counter that is incremented
+        * each time the queue is enabled and decremented when
+        * the list of frames to transmit is traversed (or when
+        * the ready time for the queue expires).  This counter
+        * must be non-zero for frames to be scheduled for
+        * transmission.  The following controls disable bumping
+        * this counter under certain conditions.  Typically this
+        * is used to gate frames based on the contents of another
+        * queue (e.g. CAB traffic may only follow a beacon frame).
+        * These are meaningful only when frames are scheduled
+        * with a non-ASAP policy (e.g. DBA-gated).
+        */
+       HAL_TXQ_CBR_DIS_QEMPTY      = 0x0080,   /* disable on this q empty */
+       HAL_TXQ_CBR_DIS_BEMPTY      = 0x0100,   /* disable on beacon q empty */
+
+       /*
+        * Fragment burst backoff policy.  Normally the no backoff
+        * is done after a successful transmission, the next fragment
+        * is sent at SIFS.  If this flag is set backoff is done
+        * after each fragment, regardless whether it was ack'd or
+        * not, after the backoff count reaches zero a normal channel
+        * access procedure is done before the next transmit (i.e.
+        * wait AIFS instead of SIFS).
+        */
+       HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE = 0x00800000,
+       /*
+        * Disable post-tx backoff following each frame.
+        */
+       HAL_TXQ_BACKOFF_DISABLE     = 0x00010000, /* disable post backoff  */
+       /*
+        * DCU arbiter lockout control.  This controls how
+        * lower priority tx queues are handled with respect to
+        * to a specific queue when multiple queues have frames
+        * to send.  No lockout means lower priority queues arbitrate
+        * concurrently with this queue.  Intra-frame lockout
+        * means lower priority queues are locked out until the
+        * current frame transmits (e.g. including backoffs and bursting).
+        * Global lockout means nothing lower can arbitrary so
+        * long as there is traffic activity on this queue (frames,
+        * backoff, etc).
+        */
+       HAL_TXQ_ARB_LOCKOUT_INTRA   = 0x00020000, /* intra-frame lockout */
+       HAL_TXQ_ARB_LOCKOUT_GLOBAL  = 0x00040000, /* full lockout s */
+
+       HAL_TXQ_IGNORE_VIRTCOL      = 0x00080000, /* ignore virt collisions */
+       HAL_TXQ_SEQNUM_INC_DIS      = 0x00100000, /* disable seqnum increment */
+} HAL_TX_QUEUE_FLAGS;
+
+typedef struct {
+       uint32_t        tqi_ver;                /* hal TXQ version */
+       HAL_TX_QUEUE_SUBTYPE tqi_subtype;       /* subtype if applicable */
+       HAL_TX_QUEUE_FLAGS tqi_qflags;          /* flags (see above) */
+       uint32_t        tqi_priority;           /* (not used) */
+       uint32_t        tqi_aifs;               /* aifs */
+       uint32_t        tqi_cwmin;              /* cwMin */
+       uint32_t        tqi_cwmax;              /* cwMax */
+       uint16_t        tqi_shretry;            /* rts retry limit */
+       uint16_t        tqi_lgretry;            /* long retry limit (not used)*/
+       uint32_t        tqi_cbrPeriod;          /* CBR period (us) */
+       uint32_t        tqi_cbrOverflowLimit;   /* threshold for CBROVF int */
+       uint32_t        tqi_burstTime;          /* max burst duration (us) */
+       uint32_t        tqi_readyTime;          /* frame schedule time (us) */
+       uint32_t        tqi_compBuf;            /* comp buffer phys addr */
+} HAL_TXQ_INFO;
+
+#define HAL_TQI_NONVAL 0xffff
+
+/* token to use for aifs, cwmin, cwmax */
+#define        HAL_TXQ_USEDEFAULT      ((uint32_t) -1)
+
+/* compression definitions */
+#define HAL_COMP_BUF_MAX_SIZE           9216            /* 9K */
+#define HAL_COMP_BUF_ALIGN_SIZE         512
+
+/*
+ * Transmit packet types.  This belongs in ah_desc.h, but
+ * is here so we can give a proper type to various parameters
+ * (and not require everyone include the file).
+ *
+ * NB: These values are intentionally assigned for
+ *     direct use when setting up h/w descriptors.
+ */
+typedef enum {
+       HAL_PKT_TYPE_NORMAL     = 0,
+       HAL_PKT_TYPE_ATIM       = 1,
+       HAL_PKT_TYPE_PSPOLL     = 2,
+       HAL_PKT_TYPE_BEACON     = 3,
+       HAL_PKT_TYPE_PROBE_RESP = 4,
+       HAL_PKT_TYPE_CHIRP      = 5,
+       HAL_PKT_TYPE_GRP_POLL   = 6,
+       HAL_PKT_TYPE_AMPDU      = 7,
+} HAL_PKT_TYPE;
+
+/* Rx Filter Frame Types */
+typedef enum {
+       HAL_RX_FILTER_UCAST     = 0x00000001,   /* Allow unicast frames */
+       HAL_RX_FILTER_MCAST     = 0x00000002,   /* Allow multicast frames */
+       HAL_RX_FILTER_BCAST     = 0x00000004,   /* Allow broadcast frames */
+       HAL_RX_FILTER_CONTROL   = 0x00000008,   /* Allow control frames */
+       HAL_RX_FILTER_BEACON    = 0x00000010,   /* Allow beacon frames */
+       HAL_RX_FILTER_PROM      = 0x00000020,   /* Promiscuous mode */
+       HAL_RX_FILTER_PROBEREQ  = 0x00000080,   /* Allow probe request frames */
+       HAL_RX_FILTER_PHYERR    = 0x00000100,   /* Allow phy errors */
+       HAL_RX_FILTER_PHYRADAR  = 0x00000200,   /* Allow phy radar errors */
+       HAL_RX_FILTER_COMPBAR   = 0x00000400,   /* Allow compressed BAR */
+} HAL_RX_FILTER;
+
+typedef enum {
+       HAL_PM_AWAKE            = 0,
+       HAL_PM_FULL_SLEEP       = 1,
+       HAL_PM_NETWORK_SLEEP    = 2,
+       HAL_PM_UNDEFINED        = 3
+} HAL_POWER_MODE;
+
+/*
+ * NOTE WELL:
+ * These are mapped to take advantage of the common locations for many of
+ * the bits on all of the currently supported MAC chips. This is to make
+ * the ISR as efficient as possible, while still abstracting HW differences.
+ * When new hardware breaks this commonality this enumerated type, as well
+ * as the HAL functions using it, must be modified. All values are directly
+ * mapped unless commented otherwise.
+ */
+typedef enum {
+       HAL_INT_RX      = 0x00000001,   /* Non-common mapping */
+       HAL_INT_RXDESC  = 0x00000002,
+       HAL_INT_RXNOFRM = 0x00000008,
+       HAL_INT_RXEOL   = 0x00000010,
+       HAL_INT_RXORN   = 0x00000020,
+       HAL_INT_TX      = 0x00000040,   /* Non-common mapping */
+       HAL_INT_TXDESC  = 0x00000080,
+       HAL_INT_TXURN   = 0x00000800,
+       HAL_INT_MIB     = 0x00001000,
+       HAL_INT_RXPHY   = 0x00004000,
+       HAL_INT_RXKCM   = 0x00008000,
+       HAL_INT_SWBA    = 0x00010000,
+       HAL_INT_BMISS   = 0x00040000,
+       HAL_INT_BNR     = 0x00100000,   /* Non-common mapping */
+       HAL_INT_TIM     = 0x00200000,   /* Non-common mapping */
+       HAL_INT_DTIM    = 0x00400000,   /* Non-common mapping */
+       HAL_INT_DTIMSYNC= 0x00800000,   /* Non-common mapping */
+       HAL_INT_GPIO    = 0x01000000,
+       HAL_INT_CABEND  = 0x02000000,   /* Non-common mapping */
+       HAL_INT_TSFOOR  = 0x04000000,   /* Non-common mapping */
+       HAL_INT_CST     = 0x10000000,   /* Non-common mapping */
+       HAL_INT_GTT     = 0x20000000,   /* Non-common mapping */
+       HAL_INT_FATAL   = 0x40000000,   /* Non-common mapping */
+#define        HAL_INT_GLOBAL  0x80000000      /* Set/clear IER */
+       HAL_INT_BMISC   = HAL_INT_TIM
+                       | HAL_INT_DTIM
+                       | HAL_INT_DTIMSYNC
+                       | HAL_INT_CABEND,
+
+       /* Interrupt bits that map directly to ISR/IMR bits */
+       HAL_INT_COMMON  = HAL_INT_RXNOFRM
+                       | HAL_INT_RXDESC
+                       | HAL_INT_RXEOL
+                       | HAL_INT_RXORN
+                       | HAL_INT_TXURN
+                       | HAL_INT_TXDESC
+                       | HAL_INT_MIB
+                       | HAL_INT_RXPHY
+                       | HAL_INT_RXKCM
+                       | HAL_INT_SWBA
+                       | HAL_INT_BMISS
+                       | HAL_INT_GPIO,
+} HAL_INT;
+
+typedef enum {
+       HAL_RFGAIN_INACTIVE             = 0,
+       HAL_RFGAIN_READ_REQUESTED       = 1,
+       HAL_RFGAIN_NEED_CHANGE          = 2
+} HAL_RFGAIN;
+
+/*
+ * Channels are specified by frequency.
+ */
+typedef struct {
+       uint32_t        channelFlags;   /* see below */
+       uint16_t        channel;        /* setting in Mhz */
+       uint8_t         privFlags;
+       int8_t          maxRegTxPower;  /* max regulatory tx power in dBm */
+       int8_t          maxTxPower;     /* max true tx power in 0.5 dBm */
+       int8_t          minTxPower;     /* min true tx power in 0.5 dBm */
+} HAL_CHANNEL;
+
+/* channelFlags */
+#define        CHANNEL_CW_INT  0x00002 /* CW interference detected on channel */
+#define        CHANNEL_TURBO   0x00010 /* Turbo Channel */
+#define        CHANNEL_CCK     0x00020 /* CCK channel */
+#define        CHANNEL_OFDM    0x00040 /* OFDM channel */
+#define        CHANNEL_2GHZ    0x00080 /* 2 GHz spectrum channel */
+#define        CHANNEL_5GHZ    0x00100 /* 5 GHz spectrum channel */
+#define        CHANNEL_PASSIVE 0x00200 /* Only passive scan allowed in the channel */
+#define        CHANNEL_DYN     0x00400 /* dynamic CCK-OFDM channel */
+#define        CHANNEL_STURBO  0x02000 /* Static turbo, no 11a-only usage */
+#define        CHANNEL_HALF    0x04000 /* Half rate channel */
+#define        CHANNEL_QUARTER 0x08000 /* Quarter rate channel */
+#define        CHANNEL_HT20    0x10000 /* 11n 20MHZ channel */
+#define        CHANNEL_HT40PLUS 0x20000 /* 11n 40MHZ channel w/ ext chan above */
+#define        CHANNEL_HT40MINUS 0x40000 /* 11n 40MHZ channel w/ ext chan below */
+
+/* privFlags */
+#define CHANNEL_INTERFERENCE           0x01 /* Software use: channel interference
+                                       used for as AR as well as RADAR
+                                       interference detection */
+#define CHANNEL_DFS            0x02 /* DFS required on channel */
+#define CHANNEL_4MS_LIMIT      0x04 /* 4msec packet limit on this channel */
+#define CHANNEL_DFS_CLEAR      0x08 /* if channel has been checked for DFS */
+
+#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_ST     (CHANNEL_T|CHANNEL_STURBO)
+#define        CHANNEL_108G    (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define        CHANNEL_108A    CHANNEL_T
+#define        CHANNEL_G_HT20          (CHANNEL_G|CHANNEL_HT20)
+#define        CHANNEL_A_HT20          (CHANNEL_A|CHANNEL_HT20)
+#define        CHANNEL_G_HT40PLUS      (CHANNEL_G|CHANNEL_HT40PLUS)
+#define        CHANNEL_G_HT40MINUS     (CHANNEL_G|CHANNEL_HT40MINUS)
+#define        CHANNEL_A_HT40PLUS      (CHANNEL_A|CHANNEL_HT40PLUS)
+#define        CHANNEL_A_HT40MINUS     (CHANNEL_A|CHANNEL_HT40MINUS)
+#define        CHANNEL_ALL \
+       (CHANNEL_OFDM | CHANNEL_CCK| CHANNEL_2GHZ | CHANNEL_5GHZ | \
+        CHANNEL_TURBO | CHANNEL_HT20 | CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)
+#define        CHANNEL_ALL_NOTURBO     (CHANNEL_ALL &~ CHANNEL_TURBO)
+
+#define HAL_ANTENNA_MIN_MODE  0
+#define HAL_ANTENNA_FIXED_A   1
+#define HAL_ANTENNA_FIXED_B   2
+#define HAL_ANTENNA_MAX_MODE  3
+
+typedef struct {
+       uint32_t        ackrcv_bad;
+       uint32_t        rts_bad;
+       uint32_t        rts_good;
+       uint32_t        fcs_bad;
+       uint32_t        beacons;
+} HAL_MIB_STATS;
+
+typedef uint16_t HAL_CTRY_CODE;                /* country code */
+typedef uint16_t HAL_REG_DOMAIN;               /* regulatory domain code */
+
+enum {
+       CTRY_DEBUG      = 0x1ff,                /* debug country code */
+       CTRY_DEFAULT    = 0                     /* default country code */
+};
+
+enum {
+       HAL_MODE_11A    = 0x001,                /* 11a channels */
+       HAL_MODE_TURBO  = 0x002,                /* 11a turbo-only channels */
+       HAL_MODE_11B    = 0x004,                /* 11b channels */
+       HAL_MODE_PUREG  = 0x008,                /* 11g channels (OFDM only) */
+#ifdef notdef
+       HAL_MODE_11G    = 0x010,                /* 11g channels (OFDM/CCK) */
+#else
+       HAL_MODE_11G    = 0x008,                /* XXX historical */
+#endif
+       HAL_MODE_108G   = 0x020,                /* 11g+Turbo channels */
+       HAL_MODE_108A   = 0x040,                /* 11a+Turbo channels */
+       HAL_MODE_11A_HALF_RATE = 0x200,         /* 11a half width channels */
+       HAL_MODE_11A_QUARTER_RATE = 0x400,      /* 11a quarter width channels */
+       HAL_MODE_11G_HALF_RATE = 0x800,         /* 11g half width channels */
+       HAL_MODE_11G_QUARTER_RATE = 0x1000,     /* 11g quarter width channels */
+       HAL_MODE_11NG_HT20      = 0x008000,
+       HAL_MODE_11NA_HT20      = 0x010000,
+       HAL_MODE_11NG_HT40PLUS  = 0x020000,
+       HAL_MODE_11NG_HT40MINUS = 0x040000,
+       HAL_MODE_11NA_HT40PLUS  = 0x080000,
+       HAL_MODE_11NA_HT40MINUS = 0x100000,
+       HAL_MODE_ALL    = 0xffffff
+};
+
+typedef struct {
+       int             rateCount;              /* NB: for proper padding */
+       uint8_t         rateCodeToIndex[144];   /* back mapping */
+       struct {
+               uint8_t valid;          /* valid for rate control use */
+               uint8_t phy;            /* CCK/OFDM/XR */
+               uint32_t        rateKbps;       /* transfer rate in kbs */
+               uint8_t         rateCode;       /* rate for h/w descriptors */
+               uint8_t         shortPreamble;  /* mask for enabling short
+                                                * preamble in CCK rate code */
+               uint8_t         dot11Rate;      /* value for supported rates
+                                                * info element of MLME */
+               uint8_t         controlRate;    /* index of next lower basic
+                                                * rate; used for dur. calcs */
+               uint16_t        lpAckDuration;  /* long preamble ACK duration */
+               uint16_t        spAckDuration;  /* short preamble ACK duration*/
+       } info[32];
+} HAL_RATE_TABLE;
+
+typedef struct {
+       u_int           rs_count;               /* number of valid entries */
+       uint8_t rs_rates[32];           /* rates */
+} HAL_RATE_SET;
+
+/*
+ * 802.11n specific structures and enums
+ */
+typedef enum {
+       HAL_CHAINTYPE_TX        = 1,    /* Tx chain type */
+       HAL_CHAINTYPE_RX        = 2,    /* RX chain type */
+} HAL_CHAIN_TYPE;
+
+typedef struct {
+       u_int   Tries;
+       u_int   Rate;
+       u_int   PktDuration;
+       u_int   ChSel;
+       u_int   RateFlags;
+#define        HAL_RATESERIES_RTS_CTS          0x0001  /* use rts/cts w/this series */
+#define        HAL_RATESERIES_2040             0x0002  /* use ext channel for series */
+#define        HAL_RATESERIES_HALFGI           0x0004  /* use half-gi for series */
+} HAL_11N_RATE_SERIES;
+
+typedef enum {
+       HAL_HT_MACMODE_20       = 0,    /* 20 MHz operation */
+       HAL_HT_MACMODE_2040     = 1,    /* 20/40 MHz operation */
+} HAL_HT_MACMODE;
+
+typedef enum {
+       HAL_HT_PHYMODE_20       = 0,    /* 20 MHz operation */
+       HAL_HT_PHYMODE_2040     = 1,    /* 20/40 MHz operation */
+} HAL_HT_PHYMODE;
+
+typedef enum {
+       HAL_HT_EXTPROTSPACING_20 = 0,   /* 20 MHz spacing */
+       HAL_HT_EXTPROTSPACING_25 = 1,   /* 25 MHz spacing */
+} HAL_HT_EXTPROTSPACING;
+
+
+typedef enum {
+       HAL_RX_CLEAR_CTL_LOW    = 0x1,  /* force control channel to appear busy */
+       HAL_RX_CLEAR_EXT_LOW    = 0x2,  /* force extension channel to appear busy */
+} HAL_HT_RXCLEAR;
+
+/*
+ * Antenna switch control.  By default antenna selection
+ * enables multiple (2) antenna use.  To force use of the
+ * A or B antenna only specify a fixed setting.  Fixing
+ * the antenna will also disable any diversity support.
+ */
+typedef enum {
+       HAL_ANT_VARIABLE = 0,                   /* variable by programming */
+       HAL_ANT_FIXED_A  = 1,                   /* fixed antenna A */
+       HAL_ANT_FIXED_B  = 2,                   /* fixed antenna B */
+} HAL_ANT_SETTING;
+
+typedef enum {
+       HAL_M_STA       = 1,                    /* infrastructure station */
+       HAL_M_IBSS      = 0,                    /* IBSS (adhoc) station */
+       HAL_M_HOSTAP    = 6,                    /* Software Access Point */
+       HAL_M_MONITOR   = 8                     /* Monitor mode */
+} HAL_OPMODE;
+
+typedef struct {
+       uint8_t         kv_type;                /* one of HAL_CIPHER */
+       uint8_t         kv_pad;
+       uint16_t        kv_len;                 /* length in bits */
+       uint8_t         kv_val[16];             /* enough for 128-bit keys */
+       uint8_t         kv_mic[8];              /* TKIP MIC key */
+       uint8_t         kv_txmic[8];            /* TKIP TX MIC key (optional) */
+} HAL_KEYVAL;
+
+typedef enum {
+       HAL_CIPHER_WEP          = 0,
+       HAL_CIPHER_AES_OCB      = 1,
+       HAL_CIPHER_AES_CCM      = 2,
+       HAL_CIPHER_CKIP         = 3,
+       HAL_CIPHER_TKIP         = 4,
+       HAL_CIPHER_CLR          = 5,            /* no encryption */
+
+       HAL_CIPHER_MIC          = 127           /* TKIP-MIC, not a cipher */
+} HAL_CIPHER;
+
+enum {
+       HAL_SLOT_TIME_6  = 6,                   /* NB: for turbo mode */
+       HAL_SLOT_TIME_9  = 9,
+       HAL_SLOT_TIME_20 = 20,
+};
+
+/*
+ * Per-station beacon timer state.  Note that the specified
+ * beacon interval (given in TU's) can also include flags
+ * to force a TSF reset and to enable the beacon xmit logic.
+ * If bs_cfpmaxduration is non-zero the hardware is setup to
+ * coexist with a PCF-capable AP.
+ */
+typedef struct {
+       uint32_t        bs_nexttbtt;            /* next beacon in TU */
+       uint32_t        bs_nextdtim;            /* next DTIM in TU */
+       uint32_t        bs_intval;              /* beacon interval+flags */
+#define        HAL_BEACON_PERIOD       0x0000ffff      /* beacon interval period */
+#define        HAL_BEACON_ENA          0x00800000      /* beacon xmit enable */
+#define        HAL_BEACON_RESET_TSF    0x01000000      /* clear TSF */
+       uint32_t        bs_dtimperiod;
+       uint16_t        bs_cfpperiod;           /* CFP period in TU */
+       uint16_t        bs_cfpmaxduration;      /* max CFP duration in TU */
+       uint32_t        bs_cfpnext;             /* next CFP in TU */
+       uint16_t        bs_timoffset;           /* byte offset to TIM bitmap */
+       uint16_t        bs_bmissthreshold;      /* beacon miss threshold */
+       uint32_t        bs_sleepduration;       /* max sleep duration */
+} HAL_BEACON_STATE;
+
+/*
+ * Like HAL_BEACON_STATE but for non-station mode setup.
+ * NB: see above flag definitions for bt_intval.
+ */
+typedef struct {
+       uint32_t        bt_intval;              /* beacon interval+flags */
+       uint32_t        bt_nexttbtt;            /* next beacon in TU */
+       uint32_t        bt_nextatim;            /* next ATIM in TU */
+       uint32_t        bt_nextdba;             /* next DBA in 1/8th TU */
+       uint32_t        bt_nextswba;            /* next SWBA in 1/8th TU */
+       uint32_t        bt_flags;               /* timer enables */
+#define HAL_BEACON_TBTT_EN     0x00000001
+#define HAL_BEACON_DBA_EN      0x00000002
+#define HAL_BEACON_SWBA_EN     0x00000004
+} HAL_BEACON_TIMERS;
+
+/*
+ * Per-node statistics maintained by the driver for use in
+ * optimizing signal quality and other operational aspects.
+ */
+typedef struct {
+       uint32_t        ns_avgbrssi;    /* average beacon rssi */
+       uint32_t        ns_avgrssi;     /* average data rssi */
+       uint32_t        ns_avgtxrssi;   /* average tx rssi */
+} HAL_NODE_STATS;
+
+#define        HAL_RSSI_EP_MULTIPLIER  (1<<7)  /* pow2 to optimize out * and / */
+
+struct ath_desc;
+struct ath_tx_status;
+struct ath_rx_status;
+
+/*
+ * Hardware Access Layer (HAL) API.
+ *
+ * Clients of the HAL call ath_hal_attach to obtain a reference to an
+ * ath_hal structure for use with the device.  Hardware-related operations
+ * that follow must call back into the HAL through interface, supplying
+ * the reference as the first parameter.  Note that before using the
+ * reference returned by ath_hal_attach the caller should verify the
+ * ABI version number.
+ */
+struct ath_hal {
+       uint32_t        ah_magic;       /* consistency check magic number */
+       uint32_t        ah_abi;         /* HAL ABI version */
+#define        HAL_ABI_VERSION 0x08112800      /* YYMMDDnn */
+       uint16_t        ah_devid;       /* PCI device ID */
+       uint16_t        ah_subvendorid; /* PCI subvendor ID */
+       HAL_SOFTC       ah_sc;          /* back pointer to driver/os state */
+       HAL_BUS_TAG     ah_st;          /* params for register r+w */
+       HAL_BUS_HANDLE  ah_sh;
+       HAL_CTRY_CODE   ah_countryCode;
+
+       uint32_t        ah_macVersion;  /* MAC version id */
+       uint16_t        ah_macRev;      /* MAC revision */
+       uint16_t        ah_phyRev;      /* PHY revision */
+       /* NB: when only one radio is present the rev is in 5Ghz */
+       uint16_t        ah_analog5GhzRev;/* 5GHz radio revision */
+       uint16_t        ah_analog2GhzRev;/* 2GHz radio revision */
+
+       const HAL_RATE_TABLE *__ahdecl(*ah_getRateTable)(struct ath_hal *,
+                               u_int mode);
+       void      __ahdecl(*ah_detach)(struct ath_hal*);
+
+       /* Reset functions */
+       HAL_BOOL  __ahdecl(*ah_reset)(struct ath_hal *, HAL_OPMODE,
+                               HAL_CHANNEL *, HAL_BOOL bChannelChange,
+                               HAL_STATUS *status);
+       HAL_BOOL  __ahdecl(*ah_phyDisable)(struct ath_hal *);
+       HAL_BOOL  __ahdecl(*ah_disable)(struct ath_hal *);
+       void      __ahdecl(*ah_setPCUConfig)(struct ath_hal *);
+       HAL_BOOL  __ahdecl(*ah_perCalibration)(struct ath_hal*, HAL_CHANNEL *,
+                       HAL_BOOL *);
+       HAL_BOOL  __ahdecl(*ah_perCalibrationN)(struct ath_hal *, HAL_CHANNEL *,
+                       u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone);
+       HAL_BOOL  __ahdecl(*ah_resetCalValid)(struct ath_hal *, HAL_CHANNEL *);
+       HAL_BOOL  __ahdecl(*ah_setTxPowerLimit)(struct ath_hal *, uint32_t);
+
+       /* Transmit functions */
+       HAL_BOOL  __ahdecl(*ah_updateTxTrigLevel)(struct ath_hal*,
+                               HAL_BOOL incTrigLevel);
+       int       __ahdecl(*ah_setupTxQueue)(struct ath_hal *, HAL_TX_QUEUE,
+                               const HAL_TXQ_INFO *qInfo);
+       HAL_BOOL  __ahdecl(*ah_setTxQueueProps)(struct ath_hal *, int q,
+                               const HAL_TXQ_INFO *qInfo);
+       HAL_BOOL  __ahdecl(*ah_getTxQueueProps)(struct ath_hal *, int q,
+                               HAL_TXQ_INFO *qInfo);
+       HAL_BOOL  __ahdecl(*ah_releaseTxQueue)(struct ath_hal *ah, u_int q);
+       HAL_BOOL  __ahdecl(*ah_resetTxQueue)(struct ath_hal *ah, u_int q);
+       uint32_t __ahdecl(*ah_getTxDP)(struct ath_hal*, u_int);
+       HAL_BOOL  __ahdecl(*ah_setTxDP)(struct ath_hal*, u_int, uint32_t txdp);
+       uint32_t __ahdecl(*ah_numTxPending)(struct ath_hal *, u_int q);
+       HAL_BOOL  __ahdecl(*ah_startTxDma)(struct ath_hal*, u_int);
+       HAL_BOOL  __ahdecl(*ah_stopTxDma)(struct ath_hal*, u_int);
+       HAL_BOOL  __ahdecl(*ah_setupTxDesc)(struct ath_hal *, struct ath_desc *,
+                               u_int pktLen, u_int hdrLen,
+                               HAL_PKT_TYPE type, u_int txPower,
+                               u_int txRate0, u_int txTries0,
+                               u_int keyIx, u_int antMode, u_int flags,
+                               u_int rtsctsRate, u_int rtsctsDuration,
+                               u_int compicvLen, u_int compivLen,
+                               u_int comp);
+       HAL_BOOL  __ahdecl(*ah_setupXTxDesc)(struct ath_hal *, struct ath_desc*,
+                               u_int txRate1, u_int txTries1,
+                               u_int txRate2, u_int txTries2,
+                               u_int txRate3, u_int txTries3);
+       HAL_BOOL  __ahdecl(*ah_fillTxDesc)(struct ath_hal *, struct ath_desc *,
+                               u_int segLen, HAL_BOOL firstSeg,
+                               HAL_BOOL lastSeg, const struct ath_desc *);
+       HAL_STATUS __ahdecl(*ah_procTxDesc)(struct ath_hal *,
+                               struct ath_desc *, struct ath_tx_status *);
+       void       __ahdecl(*ah_getTxIntrQueue)(struct ath_hal *, uint32_t *);
+       void       __ahdecl(*ah_reqTxIntrDesc)(struct ath_hal *, struct ath_desc*);
+
+       /* Receive Functions */
+       uint32_t __ahdecl(*ah_getRxDP)(struct ath_hal*);
+       void      __ahdecl(*ah_setRxDP)(struct ath_hal*, uint32_t rxdp);
+       void      __ahdecl(*ah_enableReceive)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_stopDmaReceive)(struct ath_hal*);
+       void      __ahdecl(*ah_startPcuReceive)(struct ath_hal*);
+       void      __ahdecl(*ah_stopPcuReceive)(struct ath_hal*);
+       void      __ahdecl(*ah_setMulticastFilter)(struct ath_hal*,
+                               uint32_t filter0, uint32_t filter1);
+       HAL_BOOL  __ahdecl(*ah_setMulticastFilterIndex)(struct ath_hal*,
+                               uint32_t index);
+       HAL_BOOL  __ahdecl(*ah_clrMulticastFilterIndex)(struct ath_hal*,
+                               uint32_t index);
+       uint32_t __ahdecl(*ah_getRxFilter)(struct ath_hal*);
+       void      __ahdecl(*ah_setRxFilter)(struct ath_hal*, uint32_t);
+       HAL_BOOL  __ahdecl(*ah_setupRxDesc)(struct ath_hal *, struct ath_desc *,
+                               uint32_t size, u_int flags);
+       HAL_STATUS __ahdecl(*ah_procRxDesc)(struct ath_hal *,
+                               struct ath_desc *, uint32_t phyAddr,
+                               struct ath_desc *next, uint64_t tsf,
+                               struct ath_rx_status *);
+       void      __ahdecl(*ah_rxMonitor)(struct ath_hal *,
+                               const HAL_NODE_STATS *, HAL_CHANNEL *);
+       void      __ahdecl(*ah_procMibEvent)(struct ath_hal *,
+                               const HAL_NODE_STATS *);
+
+       /* Misc Functions */
+       HAL_STATUS __ahdecl(*ah_getCapability)(struct ath_hal *,
+                               HAL_CAPABILITY_TYPE, uint32_t capability,
+                               uint32_t *result);
+       HAL_BOOL   __ahdecl(*ah_setCapability)(struct ath_hal *,
+                               HAL_CAPABILITY_TYPE, uint32_t capability,
+                               uint32_t setting, HAL_STATUS *);
+       HAL_BOOL   __ahdecl(*ah_getDiagState)(struct ath_hal *, int request,
+                               const void *args, uint32_t argsize,
+                               void **result, uint32_t *resultsize);
+       void      __ahdecl(*ah_getMacAddress)(struct ath_hal *, uint8_t *);
+       HAL_BOOL  __ahdecl(*ah_setMacAddress)(struct ath_hal *, const uint8_t*);
+       void      __ahdecl(*ah_getBssIdMask)(struct ath_hal *, uint8_t *);
+       HAL_BOOL  __ahdecl(*ah_setBssIdMask)(struct ath_hal *, const uint8_t*);
+       HAL_BOOL  __ahdecl(*ah_setRegulatoryDomain)(struct ath_hal*,
+                               uint16_t, HAL_STATUS *);
+       void      __ahdecl(*ah_setLedState)(struct ath_hal*, HAL_LED_STATE);
+       void      __ahdecl(*ah_writeAssocid)(struct ath_hal*,
+                               const uint8_t *bssid, uint16_t assocId);
+       HAL_BOOL  __ahdecl(*ah_gpioCfgOutput)(struct ath_hal *, uint32_t gpio);
+       HAL_BOOL  __ahdecl(*ah_gpioCfgInput)(struct ath_hal *, uint32_t gpio);
+       uint32_t __ahdecl(*ah_gpioGet)(struct ath_hal *, uint32_t gpio);
+       HAL_BOOL  __ahdecl(*ah_gpioSet)(struct ath_hal *,
+                               uint32_t gpio, uint32_t val);
+       void      __ahdecl(*ah_gpioSetIntr)(struct ath_hal*, u_int, uint32_t);
+       uint32_t __ahdecl(*ah_getTsf32)(struct ath_hal*);
+       uint64_t __ahdecl(*ah_getTsf64)(struct ath_hal*);
+       void      __ahdecl(*ah_resetTsf)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_detectCardPresent)(struct ath_hal*);
+       void      __ahdecl(*ah_updateMibCounters)(struct ath_hal*,
+                               HAL_MIB_STATS*);
+       HAL_RFGAIN __ahdecl(*ah_getRfGain)(struct ath_hal*);
+       u_int     __ahdecl(*ah_getDefAntenna)(struct ath_hal*);
+       void      __ahdecl(*ah_setDefAntenna)(struct ath_hal*, u_int);
+       HAL_ANT_SETTING  __ahdecl(*ah_getAntennaSwitch)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_setAntennaSwitch)(struct ath_hal*,
+                               HAL_ANT_SETTING);
+       HAL_BOOL  __ahdecl(*ah_setSifsTime)(struct ath_hal*, u_int);
+       u_int     __ahdecl(*ah_getSifsTime)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_setSlotTime)(struct ath_hal*, u_int);
+       u_int     __ahdecl(*ah_getSlotTime)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_setAckTimeout)(struct ath_hal*, u_int);
+       u_int     __ahdecl(*ah_getAckTimeout)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_setAckCTSRate)(struct ath_hal*, u_int);
+       u_int     __ahdecl(*ah_getAckCTSRate)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_setCTSTimeout)(struct ath_hal*, u_int);
+       u_int     __ahdecl(*ah_getCTSTimeout)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_setDecompMask)(struct ath_hal*, uint16_t, int);
+       void      __ahdecl(*ah_setCoverageClass)(struct ath_hal*, uint8_t, int);
+
+       /* Key Cache Functions */
+       uint32_t __ahdecl(*ah_getKeyCacheSize)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_resetKeyCacheEntry)(struct ath_hal*, uint16_t);
+       HAL_BOOL  __ahdecl(*ah_isKeyCacheEntryValid)(struct ath_hal *,
+                               uint16_t);
+       HAL_BOOL  __ahdecl(*ah_setKeyCacheEntry)(struct ath_hal*,
+                               uint16_t, const HAL_KEYVAL *,
+                               const uint8_t *, int);
+       HAL_BOOL  __ahdecl(*ah_setKeyCacheEntryMac)(struct ath_hal*,
+                               uint16_t, const uint8_t *);
+
+       /* Power Management Functions */
+       HAL_BOOL  __ahdecl(*ah_setPowerMode)(struct ath_hal*,
+                               HAL_POWER_MODE mode, int setChip);
+       HAL_POWER_MODE __ahdecl(*ah_getPowerMode)(struct ath_hal*);
+       int16_t   __ahdecl(*ah_getChanNoise)(struct ath_hal *, HAL_CHANNEL *);
+
+       /* Beacon Management Functions */
+       void      __ahdecl(*ah_setBeaconTimers)(struct ath_hal*,
+                               const HAL_BEACON_TIMERS *);
+       /* NB: deprecated, use ah_setBeaconTimers instead */
+       void      __ahdecl(*ah_beaconInit)(struct ath_hal *,
+                               uint32_t nexttbtt, uint32_t intval);
+       void      __ahdecl(*ah_setStationBeaconTimers)(struct ath_hal*,
+                               const HAL_BEACON_STATE *);
+       void      __ahdecl(*ah_resetStationBeaconTimers)(struct ath_hal*);
+
+       /* Interrupt functions */
+       HAL_BOOL  __ahdecl(*ah_isInterruptPending)(struct ath_hal*);
+       HAL_BOOL  __ahdecl(*ah_getPendingInterrupts)(struct ath_hal*, HAL_INT*);
+       HAL_INT   __ahdecl(*ah_getInterrupts)(struct ath_hal*);
+       HAL_INT   __ahdecl(*ah_setInterrupts)(struct ath_hal*, HAL_INT);
+};
+
+/*
+ * Check the PCI vendor ID and device ID against Atheros' values
+ * and return a printable description for any Atheros hardware.
+ * AH_NULL is returned if the ID's do not describe Atheros hardware.
+ */
+extern const char *__ahdecl ath_hal_probe(uint16_t vendorid, uint16_t devid);
+
+/*
+ * Attach the HAL for use with the specified device.  The device is
+ * defined by the PCI device ID.  The caller provides an opaque pointer
+ * to an upper-layer data structure (HAL_SOFTC) that is stored in the
+ * HAL state block for later use.  Hardware register accesses are done
+ * using the specified bus tag and handle.  On successful return a
+ * reference to a state block is returned that must be supplied in all
+ * subsequent HAL calls.  Storage associated with this reference is
+ * dynamically allocated and must be freed by calling the ah_detach
+ * method when the client is done.  If the attach operation fails a
+ * null (AH_NULL) reference will be returned and a status code will
+ * be returned if the status parameter is non-zero.
+ */
+extern struct ath_hal * __ahdecl ath_hal_attach(uint16_t devid, HAL_SOFTC,
+               HAL_BUS_TAG, HAL_BUS_HANDLE, HAL_STATUS* status);
+
+/*
+ * Return a list of channels available for use with the hardware.
+ * The list is based on what the hardware is capable of, the specified
+ * country code, the modeSelect mask, and whether or not outdoor
+ * channels are to be permitted.
+ *
+ * The channel list is returned in the supplied array.  maxchans
+ * defines the maximum size of this array.  nchans contains the actual
+ * number of channels returned.  If a problem occurred or there were
+ * no channels that met the criteria then AH_FALSE is returned.
+ */
+extern HAL_BOOL __ahdecl ath_hal_init_channels(struct ath_hal *,
+               HAL_CHANNEL *chans, u_int maxchans, u_int *nchans,
+               uint8_t *regclassids, u_int maxregids, u_int *nregids,
+               HAL_CTRY_CODE cc, u_int modeSelect,
+               HAL_BOOL enableOutdoor, HAL_BOOL enableExtendedChannels);
+
+/*
+ * Calibrate noise floor data following a channel scan or similar.
+ * This must be called prior retrieving noise floor data.
+ */
+extern void __ahdecl ath_hal_process_noisefloor(struct ath_hal *ah);
+
+/*
+ * Return bit mask of wireless modes supported by the hardware.
+ */
+extern u_int __ahdecl ath_hal_getwirelessmodes(struct ath_hal*, HAL_CTRY_CODE);
+
+/*
+ * Calculate the transmit duration of a frame.
+ */
+extern uint16_t __ahdecl ath_hal_computetxtime(struct ath_hal *,
+               const HAL_RATE_TABLE *rates, uint32_t frameLen,
+               uint16_t rateix, HAL_BOOL shortPreamble);
+
+/*
+ * Return if device is public safety.
+ */
+extern HAL_BOOL __ahdecl ath_hal_ispublicsafetysku(struct ath_hal *);
+
+/*
+ * Return if device is operating in 900 MHz band.
+ */
+extern HAL_BOOL ath_hal_isgsmsku(struct ath_hal *);
+
+/*
+ * Convert between IEEE channel number and channel frequency
+ * using the specified channel flags; e.g. CHANNEL_2GHZ.
+ */
+extern int __ahdecl ath_hal_mhz2ieee(struct ath_hal *, u_int mhz, u_int flags);
+#endif /* _ATH_AH_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah.c      2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,887 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah.c,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+/* linker set of registered chips */
+OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
+
+/*
+ * Check the set of registered chips to see if any recognize
+ * the device as one they can support.
+ */
+const char*
+ath_hal_probe(uint16_t vendorid, uint16_t devid)
+{
+       struct ath_hal_chip * const *pchip;
+
+       OS_SET_FOREACH(pchip, ah_chips) {
+               const char *name = (*pchip)->probe(vendorid, devid);
+               if (name != AH_NULL)
+                       return name;
+       }
+       return AH_NULL;
+}
+
+/*
+ * Attach detects device chip revisions, initializes the hwLayer
+ * function list, reads EEPROM information,
+ * selects reset vectors, and performs a short self test.
+ * Any failures will return an error that should cause a hardware
+ * disable.
+ */
+struct ath_hal*
+ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
+{
+       struct ath_hal_chip * const *pchip;
+
+       OS_SET_FOREACH(pchip, ah_chips) {
+               struct ath_hal_chip *chip = *pchip;
+               struct ath_hal *ah;
+
+               /* XXX don't have vendorid, assume atheros one works */
+               if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
+                       continue;
+               ah = chip->attach(devid, sc, st, sh, error);
+               if (ah != AH_NULL) {
+                       /* copy back private state to public area */
+                       ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
+                       ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
+                       ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
+                       ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
+                       ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
+                       ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
+                       ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
+                       return ah;
+               }
+       }
+       return AH_NULL;
+}
+
+/* linker set of registered RF backends */
+OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
+
+/*
+ * Check the set of registered RF backends to see if
+ * any recognize the device as one they can support.
+ */
+struct ath_hal_rf *
+ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
+{
+#ifdef AH_HAS_RF
+       struct ath_hal_rf * const *prf;
+
+       OS_SET_FOREACH(prf, ah_rfs) {
+               struct ath_hal_rf *rf = *prf;
+               if (rf->probe(ah))
+                       return rf;
+       }
+       *ecode = HAL_ENOTSUPP;
+#endif
+       return AH_NULL;
+}
+
+/*
+ * Poll the register looking for a specific value.
+ */
+HAL_BOOL
+ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
+{
+#define        AH_TIMEOUT      1000
+       int i;
+
+       for (i = 0; i < AH_TIMEOUT; i++) {
+               if ((OS_REG_READ(ah, reg) & mask) == val)
+                       return AH_TRUE;
+               OS_DELAY(10);
+       }
+       HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
+           "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
+           __func__, reg, OS_REG_READ(ah, reg), mask, val);
+       return AH_FALSE;
+#undef AH_TIMEOUT
+}
+
+/*
+ * Reverse the bits starting at the low bit for a value of
+ * bit_count in size
+ */
+uint32_t
+ath_hal_reverseBits(uint32_t val, uint32_t n)
+{
+       uint32_t retval;
+       int i;
+
+       for (i = 0, retval = 0; i < n; i++) {
+               retval = (retval << 1) | (val & 1);
+               val >>= 1;
+       }
+       return retval;
+}
+
+/*
+ * Compute the time to transmit a frame of length frameLen bytes
+ * using the specified rate, phy, and short preamble setting.
+ */
+uint16_t
+ath_hal_computetxtime(struct ath_hal *ah,
+       const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
+       HAL_BOOL shortPreamble)
+{
+       uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
+       uint32_t kbps;
+
+       kbps = rates->info[rateix].rateKbps;
+       /*
+        * index can be invalid duting dynamic Turbo transitions.
+        */
+       if(kbps == 0) return 0;
+       switch (rates->info[rateix].phy) {
+
+       case IEEE80211_T_CCK:
+#define CCK_SIFS_TIME        10
+#define CCK_PREAMBLE_BITS   144
+#define CCK_PLCP_BITS        48
+               phyTime         = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
+               if (shortPreamble && rates->info[rateix].shortPreamble)
+                       phyTime >>= 1;
+               numBits         = frameLen << 3;
+               txTime          = CCK_SIFS_TIME + phyTime
+                               + ((numBits * 1000)/kbps);
+               break;
+#undef CCK_SIFS_TIME
+#undef CCK_PREAMBLE_BITS
+#undef CCK_PLCP_BITS
+
+       case IEEE80211_T_OFDM:
+#define OFDM_SIFS_TIME        16
+#define OFDM_PREAMBLE_TIME    20
+#define OFDM_PLCP_BITS        22
+#define OFDM_SYMBOL_TIME       4
+
+#define OFDM_SIFS_TIME_HALF    32
+#define OFDM_PREAMBLE_TIME_HALF        40
+#define OFDM_PLCP_BITS_HALF    22
+#define OFDM_SYMBOL_TIME_HALF  8
+
+#define OFDM_SIFS_TIME_QUARTER                 64
+#define OFDM_PREAMBLE_TIME_QUARTER     80
+#define OFDM_PLCP_BITS_QUARTER         22
+#define OFDM_SYMBOL_TIME_QUARTER       16
+
+               if (AH_PRIVATE(ah)->ah_curchan &&
+                       IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+                       bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
+                       HALASSERT(bitsPerSymbol != 0);
+
+                       numBits         = OFDM_PLCP_BITS + (frameLen << 3);
+                       numSymbols      = howmany(numBits, bitsPerSymbol);
+                       txTime          = OFDM_SIFS_TIME_QUARTER
+                                               + OFDM_PREAMBLE_TIME_QUARTER
+                                       + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
+               } else if (AH_PRIVATE(ah)->ah_curchan &&
+                               IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
+                       bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
+                       HALASSERT(bitsPerSymbol != 0);
+
+                       numBits         = OFDM_PLCP_BITS + (frameLen << 3);
+                       numSymbols      = howmany(numBits, bitsPerSymbol);
+                       txTime          = OFDM_SIFS_TIME_HALF +
+                                               OFDM_PREAMBLE_TIME_HALF
+                                       + (numSymbols * OFDM_SYMBOL_TIME_HALF);
+               } else { /* full rate channel */
+                       bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME) / 1000;
+                       HALASSERT(bitsPerSymbol != 0);
+
+                       numBits         = OFDM_PLCP_BITS + (frameLen << 3);
+                       numSymbols      = howmany(numBits, bitsPerSymbol);
+                       txTime          = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
+                                       + (numSymbols * OFDM_SYMBOL_TIME);
+               }
+               break;
+
+#undef OFDM_SIFS_TIME
+#undef OFDM_PREAMBLE_TIME
+#undef OFDM_PLCP_BITS
+#undef OFDM_SYMBOL_TIME
+
+       case IEEE80211_T_TURBO:
+#define TURBO_SIFS_TIME         8
+#define TURBO_PREAMBLE_TIME    14
+#define TURBO_PLCP_BITS        22
+#define TURBO_SYMBOL_TIME       4
+               /* we still save OFDM rates in kbps - so double them */
+               bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
+               HALASSERT(bitsPerSymbol != 0);
+
+               numBits       = TURBO_PLCP_BITS + (frameLen << 3);
+               numSymbols    = howmany(numBits, bitsPerSymbol);
+               txTime        = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME
+                             + (numSymbols * TURBO_SYMBOL_TIME);
+               break;
+#undef TURBO_SIFS_TIME
+#undef TURBO_PREAMBLE_TIME
+#undef TURBO_PLCP_BITS
+#undef TURBO_SYMBOL_TIME
+
+       default:
+               HALDEBUG(ah, HAL_DEBUG_PHYIO,
+                   "%s: unknown phy %u (rate ix %u)\n",
+                   __func__, rates->info[rateix].phy, rateix);
+               txTime = 0;
+               break;
+       }
+       return txTime;
+}
+
+static __inline int
+mapgsm(u_int freq, u_int flags)
+{
+       freq *= 10;
+       if (flags & CHANNEL_QUARTER)
+               freq += 5;
+       else if (flags & CHANNEL_HALF)
+               freq += 10;
+       else
+               freq += 20;
+       return (freq - 24220) / 5;
+}
+
+static __inline int
+mappsb(u_int freq, u_int flags)
+{
+       return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
+}
+
+/*
+ * Convert GHz frequency to IEEE channel number.
+ */
+int
+ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags)
+{
+       if (flags & CHANNEL_2GHZ) {     /* 2GHz band */
+               if (freq == 2484)
+                       return 14;
+               if (freq < 2484) {
+                       if (ath_hal_isgsmsku(ah))
+                               return mapgsm(freq, flags);
+                       return ((int)freq - 2407) / 5;
+               } else
+                       return 15 + ((freq - 2512) / 20);
+       } else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */
+               if (ath_hal_ispublicsafetysku(ah) &&
+                   IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
+                       return mappsb(freq, flags);
+               } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
+                       return (freq - 4000) / 5;
+               } else {
+                       return (freq - 5000) / 5;
+               }
+       } else {                        /* either, guess */
+               if (freq == 2484)
+                       return 14;
+               if (freq < 2484) {
+                       if (ath_hal_isgsmsku(ah))
+                               return mapgsm(freq, flags);
+                       return ((int)freq - 2407) / 5;
+               }
+               if (freq < 5000) {
+                       if (ath_hal_ispublicsafetysku(ah) &&
+                           IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
+                               return mappsb(freq, flags);
+                       } else if (freq > 4900) {
+                               return (freq - 4000) / 5;
+                       } else {
+                               return 15 + ((freq - 2512) / 20);
+                       }
+               }
+               return (freq - 5000) / 5;
+       }
+}
+
+typedef enum {
+       WIRELESS_MODE_11a   = 0,
+       WIRELESS_MODE_TURBO = 1,
+       WIRELESS_MODE_11b   = 2,
+       WIRELESS_MODE_11g   = 3,
+       WIRELESS_MODE_108g  = 4,
+
+       WIRELESS_MODE_MAX
+} WIRELESS_MODE;
+
+static WIRELESS_MODE
+ath_hal_chan2wmode(struct ath_hal *ah, const HAL_CHANNEL *chan)
+{
+       if (IS_CHAN_CCK(chan))
+               return WIRELESS_MODE_11b;
+       if (IS_CHAN_G(chan))
+               return WIRELESS_MODE_11g;
+       if (IS_CHAN_108G(chan))
+               return WIRELESS_MODE_108g;
+       if (IS_CHAN_TURBO(chan))
+               return WIRELESS_MODE_TURBO;
+       return WIRELESS_MODE_11a;
+}
+
+/*
+ * Convert between microseconds and core system clocks.
+ */
+                                     /* 11a Turbo  11b  11g  108g */
+static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
+
+u_int
+ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
+{
+       const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
+       u_int clks;
+
+       /* NB: ah_curchan may be null when called attach time */
+       if (c != AH_NULL) {
+               clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
+               if (IS_CHAN_HT40(c))
+                       clks <<= 1;
+               else if (IS_CHAN_HALF_RATE(c))
+                       clks >>= 1;
+               else if (IS_CHAN_QUARTER_RATE(c))
+                       clks >>= 2;
+       } else
+               clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
+       return clks;
+}
+
+u_int
+ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
+{
+       const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
+       u_int usec;
+
+       /* NB: ah_curchan may be null when called attach time */
+       if (c != AH_NULL) {
+               usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
+               if (IS_CHAN_HT40(c))
+                       usec >>= 1;
+               else if (IS_CHAN_HALF_RATE(c))
+                       usec <<= 1;
+               else if (IS_CHAN_QUARTER_RATE(c))
+                       usec <<= 2;
+       } else
+               usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
+       return usec;
+}
+
+/*
+ * Setup a h/w rate table's reverse lookup table and
+ * fill in ack durations.  This routine is called for
+ * each rate table returned through the ah_getRateTable
+ * method.  The reverse lookup tables are assumed to be
+ * initialized to zero (or at least the first entry).
+ * We use this as a key that indicates whether or not
+ * we've previously setup the reverse lookup table.
+ *
+ * XXX not reentrant, but shouldn't matter
+ */
+void
+ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
+{
+#define        N(a)    (sizeof(a)/sizeof(a[0]))
+       int i;
+
+       if (rt->rateCodeToIndex[0] != 0)        /* already setup */
+               return;
+       for (i = 0; i < N(rt->rateCodeToIndex); i++)
+               rt->rateCodeToIndex[i] = (uint8_t) -1;
+       for (i = 0; i < rt->rateCount; i++) {
+               uint8_t code = rt->info[i].rateCode;
+               uint8_t cix = rt->info[i].controlRate;
+
+               HALASSERT(code < N(rt->rateCodeToIndex));
+               rt->rateCodeToIndex[code] = i;
+               HALASSERT((code | rt->info[i].shortPreamble) <
+                   N(rt->rateCodeToIndex));
+               rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
+               /*
+                * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
+                *     depends on whether they are marked as basic rates;
+                *     the static tables are setup with an 11b-compatible
+                *     2Mb/s rate which will work but is suboptimal
+                */
+               rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
+                       WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
+               rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
+                       WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
+       }
+#undef N
+}
+
+HAL_STATUS
+ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+       uint32_t capability, uint32_t *result)
+{
+       const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+
+       switch (type) {
+       case HAL_CAP_REG_DMN:           /* regulatory domain */
+               *result = AH_PRIVATE(ah)->ah_currentRD;
+               return HAL_OK;
+       case HAL_CAP_CIPHER:            /* cipher handled in hardware */
+       case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
+               return HAL_ENOTSUPP;
+       case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
+               return HAL_ENOTSUPP;
+       case HAL_CAP_PHYCOUNTERS:       /* hardware PHY error counters */
+               return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
+       case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
+               return HAL_ENOTSUPP;
+       case HAL_CAP_DIVERSITY:         /* hardware supports fast diversity */
+               return HAL_ENOTSUPP;
+       case HAL_CAP_KEYCACHE_SIZE:     /* hardware key cache size */
+               *result =  pCap->halKeyCacheSize;
+               return HAL_OK;
+       case HAL_CAP_NUM_TXQUEUES:      /* number of hardware tx queues */
+               *result = pCap->halTotalQueues;
+               return HAL_OK;
+       case HAL_CAP_VEOL:              /* hardware supports virtual EOL */
+               return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_PSPOLL:            /* hardware PS-Poll support works */
+               return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
+       case HAL_CAP_COMPRESSION:
+               return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_BURST:
+               return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_FASTFRAME:
+               return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_DIAG:              /* hardware diagnostic support */
+               *result = AH_PRIVATE(ah)->ah_diagreg;
+               return HAL_OK;
+       case HAL_CAP_TXPOW:             /* global tx power limit  */
+               switch (capability) {
+               case 0:                 /* facility is supported */
+                       return HAL_OK;
+               case 1:                 /* current limit */
+                       *result = AH_PRIVATE(ah)->ah_powerLimit;
+                       return HAL_OK;
+               case 2:                 /* current max tx power */
+                       *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
+                       return HAL_OK;
+               case 3:                 /* scale factor */
+                       *result = AH_PRIVATE(ah)->ah_tpScale;
+                       return HAL_OK;
+               }
+               return HAL_ENOTSUPP;
+       case HAL_CAP_BSSIDMASK:         /* hardware supports bssid mask */
+               return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
+               return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
+               return HAL_ENOTSUPP;
+       case HAL_CAP_RFSILENT:          /* rfsilent support  */
+               switch (capability) {
+               case 0:                 /* facility is supported */
+                       return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
+               case 1:                 /* current setting */
+                       return AH_PRIVATE(ah)->ah_rfkillEnabled ?
+                               HAL_OK : HAL_ENOTSUPP;
+               case 2:                 /* rfsilent config */
+                       *result = AH_PRIVATE(ah)->ah_rfsilent;
+                       return HAL_OK;
+               }
+               return HAL_ENOTSUPP;
+       case HAL_CAP_11D:
+#ifdef AH_SUPPORT_11D
+               return HAL_OK;
+#else
+               return HAL_ENOTSUPP;
+#endif
+       case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
+               return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_HT:
+               return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
+       case HAL_CAP_TX_CHAINMASK:      /* mask of TX chains supported */
+               *result = pCap->halTxChainMask;
+               return HAL_OK;
+       case HAL_CAP_RX_CHAINMASK:      /* mask of RX chains supported */
+               *result = pCap->halRxChainMask;
+               return HAL_OK;
+       case HAL_CAP_RXTSTAMP_PREC:     /* rx desc tstamp precision (bits) */
+               *result = pCap->halTstampPrecision;
+               return HAL_OK;
+       default:
+               return HAL_EINVAL;
+       }
+}
+
+HAL_BOOL
+ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
+       uint32_t capability, uint32_t setting, HAL_STATUS *status)
+{
+
+       switch (type) {
+       case HAL_CAP_TXPOW:
+               switch (capability) {
+               case 3:
+                       if (setting <= HAL_TP_SCALE_MIN) {
+                               AH_PRIVATE(ah)->ah_tpScale = setting;
+                               return AH_TRUE;
+                       }
+                       break;
+               }
+               break;
+       case HAL_CAP_RFSILENT:          /* rfsilent support  */
+               /*
+                * NB: allow even if halRfSilentSupport is false
+                *     in case the EEPROM is misprogrammed.
+                */
+               switch (capability) {
+               case 1:                 /* current setting */
+                       AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
+                       return AH_TRUE;
+               case 2:                 /* rfsilent config */
+                       /* XXX better done per-chip for validation? */
+                       AH_PRIVATE(ah)->ah_rfsilent = setting;
+                       return AH_TRUE;
+               }
+               break;
+       case HAL_CAP_REG_DMN:           /* regulatory domain */
+               AH_PRIVATE(ah)->ah_currentRD = setting;
+               return AH_TRUE;
+       case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
+               AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
+               return AH_TRUE;
+       default:
+               break;
+       }
+       if (status)
+               *status = HAL_EINVAL;
+       return AH_FALSE;
+}
+
+/*
+ * Common support for getDiagState method.
+ */
+
+static u_int
+ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
+       void *dstbuf, int space)
+{
+       uint32_t *dp = dstbuf;
+       int i;
+
+       for (i = 0; space >= 2*sizeof(uint32_t); i++) {
+               u_int r = regs[i].start;
+               u_int e = regs[i].end;
+               *dp++ = (r<<16) | e;
+               space -= sizeof(uint32_t);
+               do {
+                       *dp++ = OS_REG_READ(ah, r);
+                       r += sizeof(uint32_t);
+                       space -= sizeof(uint32_t);
+               } while (r <= e && space >= sizeof(uint32_t));
+       }
+       return (char *) dp - (char *) dstbuf;
+}
+
+HAL_BOOL
+ath_hal_getdiagstate(struct ath_hal *ah, int request,
+       const void *args, uint32_t argsize,
+       void **result, uint32_t *resultsize)
+{
+       switch (request) {
+       case HAL_DIAG_REVS:
+               *result = &AH_PRIVATE(ah)->ah_devid;
+               *resultsize = sizeof(HAL_REVS);
+               return AH_TRUE;
+       case HAL_DIAG_REGS:
+               *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
+               return AH_TRUE;
+       case HAL_DIAG_FATALERR:
+               *result = &AH_PRIVATE(ah)->ah_fatalState[0];
+               *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
+               return AH_TRUE;
+       case HAL_DIAG_EEREAD:
+               if (argsize != sizeof(uint16_t))
+                       return AH_FALSE;
+               if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
+                       return AH_FALSE;
+               *resultsize = sizeof(uint16_t);
+               return AH_TRUE;
+#ifdef AH_PRIVATE_DIAG
+       case HAL_DIAG_SETKEY: {
+               const HAL_DIAG_KEYVAL *dk;
+
+               if (argsize != sizeof(HAL_DIAG_KEYVAL))
+                       return AH_FALSE;
+               dk = (const HAL_DIAG_KEYVAL *)args;
+               return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
+                       &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
+       }
+       case HAL_DIAG_RESETKEY:
+               if (argsize != sizeof(uint16_t))
+                       return AH_FALSE;
+               return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
+#ifdef AH_SUPPORT_WRITE_EEPROM
+       case HAL_DIAG_EEWRITE: {
+               const HAL_DIAG_EEVAL *ee;
+               if (argsize != sizeof(HAL_DIAG_EEVAL))
+                       return AH_FALSE;
+               ee = (const HAL_DIAG_EEVAL *)args;
+               return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
+       }
+#endif /* AH_SUPPORT_WRITE_EEPROM */
+#endif /* AH_PRIVATE_DIAG */
+       case HAL_DIAG_11NCOMPAT:
+               if (argsize == 0) {
+                       *resultsize = sizeof(uint32_t);
+                       *((uint32_t *)(*result)) =
+                               AH_PRIVATE(ah)->ah_11nCompat;
+               } else if (argsize == sizeof(uint32_t)) {
+                       AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
+               } else
+                       return AH_FALSE;
+               return AH_TRUE;
+       }
+       return AH_FALSE;
+}
+
+/*
+ * Set the properties of the tx queue with the parameters
+ * from qInfo.
+ */
+HAL_BOOL
+ath_hal_setTxQProps(struct ath_hal *ah,
+       HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
+{
+       uint32_t cw;
+
+       if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
+                   "%s: inactive queue\n", __func__);
+               return AH_FALSE;
+       }
+       /* XXX validate parameters */
+       qi->tqi_ver = qInfo->tqi_ver;
+       qi->tqi_subtype = qInfo->tqi_subtype;
+       qi->tqi_qflags = qInfo->tqi_qflags;
+       qi->tqi_priority = qInfo->tqi_priority;
+       if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
+               qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
+       else
+               qi->tqi_aifs = INIT_AIFS;
+       if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
+               cw = AH_MIN(qInfo->tqi_cwmin, 1024);
+               /* make sure that the CWmin is of the form (2^n - 1) */
+               qi->tqi_cwmin = 1;
+               while (qi->tqi_cwmin < cw)
+                       qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
+       } else
+               qi->tqi_cwmin = qInfo->tqi_cwmin;
+       if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
+               cw = AH_MIN(qInfo->tqi_cwmax, 1024);
+               /* make sure that the CWmax is of the form (2^n - 1) */
+               qi->tqi_cwmax = 1;
+               while (qi->tqi_cwmax < cw)
+                       qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
+       } else
+               qi->tqi_cwmax = INIT_CWMAX;
+       /* Set retry limit values */
+       if (qInfo->tqi_shretry != 0)
+               qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
+       else
+               qi->tqi_shretry = INIT_SH_RETRY;
+       if (qInfo->tqi_lgretry != 0)
+               qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
+       else
+               qi->tqi_lgretry = INIT_LG_RETRY;
+       qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
+       qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
+       qi->tqi_burstTime = qInfo->tqi_burstTime;
+       qi->tqi_readyTime = qInfo->tqi_readyTime;
+
+       switch (qInfo->tqi_subtype) {
+       case HAL_WME_UPSD:
+               if (qi->tqi_type == HAL_TX_QUEUE_DATA)
+                       qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
+               break;
+       default:
+               break;          /* NB: silence compiler */
+       }
+       return AH_TRUE;
+}
+
+HAL_BOOL
+ath_hal_getTxQProps(struct ath_hal *ah,
+       HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
+{
+       if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
+               HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
+                   "%s: inactive queue\n", __func__);
+               return AH_FALSE;
+       }
+
+       qInfo->tqi_qflags = qi->tqi_qflags;
+       qInfo->tqi_ver = qi->tqi_ver;
+       qInfo->tqi_subtype = qi->tqi_subtype;
+       qInfo->tqi_qflags = qi->tqi_qflags;
+       qInfo->tqi_priority = qi->tqi_priority;
+       qInfo->tqi_aifs = qi->tqi_aifs;
+       qInfo->tqi_cwmin = qi->tqi_cwmin;
+       qInfo->tqi_cwmax = qi->tqi_cwmax;
+       qInfo->tqi_shretry = qi->tqi_shretry;
+       qInfo->tqi_lgretry = qi->tqi_lgretry;
+       qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
+       qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
+       qInfo->tqi_burstTime = qi->tqi_burstTime;
+       qInfo->tqi_readyTime = qi->tqi_readyTime;
+       return AH_TRUE;
+}
+
+                                     /* 11a Turbo  11b  11g  108g */
+static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
+
+/*
+ * Read the current channel noise floor and return.
+ * If nf cal hasn't finished, channel noise floor should be 0
+ * and we return a nominal value based on band and frequency.
+ *
+ * NB: This is a private routine used by per-chip code to
+ *     implement the ah_getChanNoise method.
+ */
+int16_t
+ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan)
+{
+       HAL_CHANNEL_INTERNAL *ichan;
+
+       ichan = ath_hal_checkchannel(ah, chan);
+       if (ichan == AH_NULL) {
+               HALDEBUG(ah, HAL_DEBUG_NFCAL,
+                   "%s: invalid channel %u/0x%x; no mapping\n",
+                   __func__, chan->channel, chan->channelFlags);
+               return 0;
+       }
+       if (ichan->rawNoiseFloor == 0) {
+               WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
+
+               HALASSERT(mode < WIRELESS_MODE_MAX);
+               return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
+       } else
+               return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
+}
+
+/*
+ * Process all valid raw noise floors into the dBm noise floor values.
+ * Though our device has no reference for a dBm noise floor, we perform
+ * a relative minimization of NF's based on the lowest NF found across a
+ * channel scan.
+ */
+void
+ath_hal_process_noisefloor(struct ath_hal *ah)
+{
+       HAL_CHANNEL_INTERNAL *c;
+       int16_t correct2, correct5;
+       int16_t lowest2, lowest5;
+       int i;
+
+       /*
+        * Find the lowest 2GHz and 5GHz noise floor values after adjusting
+        * for statistically recorded NF/channel deviation.
+        */
+       correct2 = lowest2 = 0;
+       correct5 = lowest5 = 0;
+       for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
+               WIRELESS_MODE mode;
+               int16_t nf;
+
+               c = &AH_PRIVATE(ah)->ah_channels[i];
+               if (c->rawNoiseFloor >= 0)
+                       continue;
+               mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) c);
+               HALASSERT(mode < WIRELESS_MODE_MAX);
+               nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
+                       ath_hal_getNfAdjust(ah, c);
+               if (IS_CHAN_5GHZ(c)) {
+                       if (nf < lowest5) {
+                               lowest5 = nf;
+                               correct5 = NOISE_FLOOR[mode] -
+                                   (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
+                       }
+               } else {
+                       if (nf < lowest2) {
+                               lowest2 = nf;
+                               correct2 = NOISE_FLOOR[mode] -
+                                   (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
+                       }
+               }
+       }
+
+       /* Correct the channels to reach the expected NF value */
+       for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
+               c = &AH_PRIVATE(ah)->ah_channels[i];
+               if (c->rawNoiseFloor >= 0)
+                       continue;
+               /* Apply correction factor */
+               c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
+                       (IS_CHAN_5GHZ(c) ? correct5 : correct2);
+               HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u/0x%x raw nf %d adjust %d\n",
+                   c->channel, c->channelFlags, c->rawNoiseFloor,
+                   c->noiseFloorAdjust);
+       }
+}
+
+/*
+ * INI support routines.
+ */
+
+int
+ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
+       int col, int regWr)
+{
+       int r;
+
+       for (r = 0; r < ia->rows; r++) {
+               OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
+                   HAL_INI_VAL(ia, r, col));
+               DMA_YIELD(regWr);
+       }
+       return regWr;
+}
+
+void
+ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
+{
+       int r;
+
+       for (r = 0; r < ia->rows; r++)
+               data[r] = HAL_INI_VAL(ia, r, col);
+}
+
+int
+ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
+       const uint32_t data[], int regWr)
+{
+       int r;
+
+       for (r = 0; r < ia->rows; r++) {
+               OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
+               DMA_YIELD(regWr);
+       }
+       return regWr;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/dist/ah_desc.h 2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ah_desc.h,v 1.1 2009/03/23 17:14:47 sborrill Exp $
+ */
+
+#ifndef _DEV_ATH_DESC_H
+#define _DEV_ATH_DESC_H
+
+#include "opt_ah.h"            /* NB: required for AH_SUPPORT_AR5416 */
+
+/*
+ * Transmit descriptor status.  This structure is filled
+ * in only after the tx descriptor process method finds a
+ * ``done'' descriptor; at which point it returns something
+ * other than HAL_EINPROGRESS.
+ *
+ * Note that ts_antenna may not be valid for all h/w.  It
+ * should be used only if non-zero.
+ */
+struct ath_tx_status {
+       uint16_t        ts_seqnum;      /* h/w assigned sequence number */
+       uint16_t        ts_tstamp;      /* h/w assigned timestamp */
+       uint8_t         ts_status;      /* frame status, 0 => xmit ok */
+       uint8_t         ts_rate;        /* h/w transmit rate index */
+#define        HAL_TXSTAT_ALTRATE      0x80    /* alternate xmit rate used */
+       int8_t          ts_rssi;        /* tx ack RSSI */
+       uint8_t         ts_shortretry;  /* # short retries */
+       uint8_t         ts_longretry;   /* # long retries */
+       uint8_t         ts_virtcol;     /* virtual collision count */
+       uint8_t         ts_antenna;     /* antenna information */
+       uint8_t         ts_finaltsi;    /* final transmit series index */
+#ifdef AH_SUPPORT_AR5416
+                                       /* 802.11n status */
+       uint8_t         ts_flags;       /* misc flags */
+       int8_t          ts_rssi_ctl[3]; /* tx ack RSSI [ctl, chain 0-2] */
+       int8_t          ts_rssi_ext[3]; /* tx ack RSSI [ext, chain 0-2] */
+/* #define ts_rssi ts_rssi_combined */
+       uint32_t        ts_ba_low;      /* blockack bitmap low */
+       uint32_t        ts_ba_high;     /* blockack bitmap high */
+       uint32_t        ts_evm0;        /* evm bytes */
+       uint32_t        ts_evm1;
+       uint32_t        ts_evm2;
+#endif /* AH_SUPPORT_AR5416 */
+};
+
+/* bits found in ts_status */
+#define        HAL_TXERR_XRETRY        0x01    /* excessive retries */
+#define        HAL_TXERR_FILT          0x02    /* blocked by tx filtering */
+#define        HAL_TXERR_FIFO          0x04    /* fifo underrun */
+#define        HAL_TXERR_XTXOP         0x08    /* txop exceeded */
+#define        HAL_TXERR_TIMER_EXPIRED 0x10    /* Tx timer expired */
+
+/* bits found in ts_flags */
+#define        HAL_TX_BA               0x01    /* Block Ack seen */
+#define        HAL_TX_AGGR             0x02    /* Aggregate */
+#define        HAL_TX_DESC_CFG_ERR     0x10    /* Error in 20/40 desc config */
+#define        HAL_TX_DATA_UNDERRUN    0x20    /* Tx buffer underrun */
+#define        HAL_TX_DELIM_UNDERRUN   0x40    /* Tx delimiter underrun */
+
+/*
+ * Receive descriptor status.  This structure is filled
+ * in only after the rx descriptor process method finds a
+ * ``done'' descriptor; at which point it returns something
+ * other than HAL_EINPROGRESS.
+ *
+ * If rx_status is zero, then the frame was received ok;
+ * otherwise the error information is indicated and rs_phyerr
+ * contains a phy error code if HAL_RXERR_PHY is set.  In general
+ * the frame contents is undefined when an error occurred thought
+ * for some errors (e.g. a decryption error), it may be meaningful.
+ *
+ * Note that the receive timestamp is expanded using the TSF to
+ * at least 15 bits (regardless of what the h/w provides directly).
+ * Newer hardware supports a full 32-bits; use HAL_CAP_32TSTAMP to
+ * find out if the hardware is capable.
+ *
+ * rx_rssi is in units of dbm above the noise floor.  This value
+ * is measured during the preamble and PLCP; i.e. with the initial
+ * 4us of detection.  The noise floor is typically a consistent
+ * -96dBm absolute power in a 20MHz channel.
+ */
+struct ath_rx_status {
+       uint16_t        rs_datalen;     /* rx frame length */
+       uint8_t         rs_status;      /* rx status, 0 => recv ok */
+       uint8_t         rs_phyerr;      /* phy error code */
+       int8_t          rs_rssi;        /* rx frame RSSI (combined for 11n) */
+       uint8_t         rs_keyix;       /* key cache index */
+       uint8_t         rs_rate;        /* h/w receive rate index */
+       uint8_t         rs_more;        /* more descriptors follow */
+       uint32_t        rs_tstamp;      /* h/w assigned timestamp */
+       uint32_t        rs_antenna;     /* antenna information */
+#ifdef AH_SUPPORT_AR5416
+                                       /* 802.11n status */
+       int8_t          rs_rssi_ctl[3]; /* rx frame RSSI [ctl, chain 0-2] */
+       int8_t          rs_rssi_ext[3]; /* rx frame RSSI [ext, chain 0-2] */
+       uint8_t         rs_isaggr;      /* is part of the aggregate */
+       uint8_t         rs_moreaggr;    /* more frames in aggr to follow */
+       uint8_t         rs_num_delims;  /* number of delims in aggr */
+       uint8_t         rs_flags;       /* misc flags */
+       uint32_t        rs_evm0;        /* evm bytes */
+       uint32_t        rs_evm1;
+       uint32_t        rs_evm2;
+#endif /* AH_SUPPORT_AR5416 */
+};
+
+/* bits found in rs_status */
+#define        HAL_RXERR_CRC           0x01    /* CRC error on frame */
+#define        HAL_RXERR_PHY           0x02    /* PHY error, rs_phyerr is valid */
+#define        HAL_RXERR_FIFO          0x04    /* fifo overrun */
+#define        HAL_RXERR_DECRYPT       0x08    /* non-Michael decrypt error */
+#define        HAL_RXERR_MIC           0x10    /* Michael MIC decrypt error */
+
+/* bits found in rs_flags */
+#define        HAL_RX_MORE             0x01    /* more descriptors follow */
+#define        HAL_RX_MORE_AGGR        0x02    /* more frames in aggr */
+#define        HAL_RX_GI               0x04    /* full gi */
+#define        HAL_RX_2040             0x08    /* 40 Mhz */
+#define        HAL_RX_DELIM_CRC_PRE    0x10    /* crc error in delimiter pre */
+#define        HAL_RX_DELIM_CRC_POST   0x20    /* crc error in delim after */
+#define        HAL_RX_DECRYPT_BUSY     0x40    /* decrypt was too slow */
+#define        HAL_RX_HI_RX_CHAIN      0x80    /* SM power save: hi Rx chain control */
+
+enum {
+       HAL_PHYERR_UNDERRUN             = 0,    /* Transmit underrun */
+       HAL_PHYERR_TIMING               = 1,    /* Timing error */
+       HAL_PHYERR_PARITY               = 2,    /* Illegal parity */
+       HAL_PHYERR_RATE                 = 3,    /* Illegal rate */
+       HAL_PHYERR_LENGTH               = 4,    /* Illegal length */
+       HAL_PHYERR_RADAR                = 5,    /* Radar detect */
+       HAL_PHYERR_SERVICE              = 6,    /* Illegal service */
+       HAL_PHYERR_TOR                  = 7,    /* Transmit override receive */
+       /* NB: these are specific to the 5212 */
+       HAL_PHYERR_OFDM_TIMING          = 17,   /* */
+       HAL_PHYERR_OFDM_SIGNAL_PARITY   = 18,   /* */
+       HAL_PHYERR_OFDM_RATE_ILLEGAL    = 19,   /* */
+       HAL_PHYERR_OFDM_LENGTH_ILLEGAL  = 20,   /* */
+       HAL_PHYERR_OFDM_POWER_DROP      = 21,   /* */
+       HAL_PHYERR_OFDM_SERVICE         = 22,   /* */
+       HAL_PHYERR_OFDM_RESTART         = 23,   /* */
+       HAL_PHYERR_CCK_TIMING           = 25,   /* */
+       HAL_PHYERR_CCK_HEADER_CRC       = 26,   /* */
+       HAL_PHYERR_CCK_RATE_ILLEGAL     = 27,   /* */
+       HAL_PHYERR_CCK_SERVICE          = 30,   /* */
+       HAL_PHYERR_CCK_RESTART          = 31,   /* */
+};
+
+/* value found in rs_keyix to mark invalid entries */
+#define        HAL_RXKEYIX_INVALID     ((uint8_t) -1)
+/* value used to specify no encryption key for xmit */
+#define        HAL_TXKEYIX_INVALID     ((u_int) -1)
+
+/* XXX rs_antenna definitions */
+
+/*
+ * Definitions for the software frame/packet descriptors used by
+ * the Atheros HAL.  This definition obscures hardware-specific
+ * details from the driver.  Drivers are expected to fillin the
+ * portions of a descriptor that are not opaque then use HAL calls
+ * to complete the work.  Status for completed frames is returned
+ * in a device-independent format.
+ */
+#ifdef AH_SUPPORT_AR5416
+#define        HAL_DESC_HW_SIZE        20
+#else
+#define        HAL_DESC_HW_SIZE        4
+#endif /* AH_SUPPORT_AR5416 */
+
+struct ath_desc {
+       /*
+        * The following definitions are passed directly
+        * the hardware and managed by the HAL.  Drivers
+        * should not touch those elements marked opaque.
+        */
+       uint32_t        ds_link;        /* phys address of next descriptor */
+       uint32_t        ds_data;        /* phys address of data buffer */
+       uint32_t        ds_ctl0;        /* opaque DMA control 0 */
+       uint32_t        ds_ctl1;        /* opaque DMA control 1 */
+       uint32_t        ds_hw[HAL_DESC_HW_SIZE];        /* opaque h/w region */
+       union {
+               struct ath_tx_status tx;/* xmit status */
+               struct ath_rx_status rx;/* recv status */
+       } ds_us;
+};
+
+#define        ds_txstat       ds_us.tx
+#define        ds_rxstat       ds_us.rx
+
+/* flags passed to tx descriptor setup methods */
+#define        HAL_TXDESC_CLRDMASK     0x0001  /* clear destination filter mask */
+#define        HAL_TXDESC_NOACK        0x0002  /* don't wait for ACK */
+#define        HAL_TXDESC_RTSENA       0x0004  /* enable RTS */
+#define        HAL_TXDESC_CTSENA       0x0008  /* enable CTS */
+#define        HAL_TXDESC_INTREQ       0x0010  /* enable per-descriptor interrupt */
+#define        HAL_TXDESC_VEOL         0x0020  /* mark virtual EOL */
+/* NB: this only affects frame, not any RTS/CTS */
+#define        HAL_TXDESC_DURENA       0x0040  /* enable h/w write of duration field */
+#define        HAL_TXDESC_EXT_ONLY     0x0080  /* send on ext channel only (11n) */
+#define        HAL_TXDESC_EXT_AND_CTL  0x0100  /* send on ext + ctl channels (11n) */
+#define        HAL_TXDESC_VMF          0x0200  /* virtual more frag */
+
+/* flags passed to rx descriptor setup methods */
+#define        HAL_RXDESC_INTREQ       0x0020  /* enable per-descriptor interrupt */
+#endif /* _DEV_ATH_DESC_H */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/ic/ah_osdep.c  2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,487 @@
+/*-
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: ah_osdep.c,v 1.2 2009/03/23 17:17:07 sborrill Exp $
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ah_osdep.c,v 1.1 2008/12/11 05:37:40 alc Exp $");
+
+#include "opt_athhal.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/kauth.h>
+
+#include <machine/stdarg.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_arp.h>
+#include <net/if_ether.h>
+
+#include <external/isc/atheros_hal/dist/ah.h>
+
+#ifdef __mips__
+#include <sys/cpu.h>
+
+#define ENTER  lwp_t *savlwp = curlwp; curlwp = cpu_info_store.ci_curlwp;
+#define        EXIT    curlwp = savlwp;
+#else
+#define        ENTER   /* nothing */
+#define        EXIT    /* nothing */
+#endif
+
+extern void ath_hal_printf(struct ath_hal *, const char*, ...);
+extern void ath_hal_vprintf(struct ath_hal *, const char*, va_list);
+extern const char* ath_hal_ether_sprintf(const u_int8_t *mac);
+extern void *ath_hal_malloc(size_t);
+extern void ath_hal_free(void *);
+#ifdef ATHHAL_ASSERT
+extern void ath_hal_assert_failed(const char* filename,
+               int lineno, const char* msg);
+#endif
+#ifdef ATHHAL_DEBUG
+extern void HALDEBUG(struct ath_hal *ah, const char* fmt, ...);
+extern void HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...);
+#endif /* ATHHAL_DEBUG */
+
+#ifdef ATHHAL_DEBUG
+static int ath_hal_debug = 0;
+#endif /* ATHHAL_DEBUG */
+
+int    ath_hal_dma_beacon_response_time = 2;   /* in TU's */
+int    ath_hal_sw_beacon_response_time = 10;   /* in TU's */
+int    ath_hal_additional_swba_backoff = 0;    /* in TU's */
+
+SYSCTL_SETUP(sysctl_ath_hal, "sysctl ath.hal subtree setup")
+{
+       int rc;
+       const struct sysctlnode *cnode, *rnode;
+
+       if ((rc = sysctl_createv(clog, 0, NULL, &rnode, CTLFLAG_PERMANENT,
+           CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0)
+               goto err;
+
+       if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, CTLFLAG_PERMANENT,
+           CTLTYPE_NODE, "ath", SYSCTL_DESCR("Atheros driver parameters"),
+           NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
+               goto err;
+
+       if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, CTLFLAG_PERMANENT,
+           CTLTYPE_NODE, "hal", SYSCTL_DESCR("Atheros HAL parameters"),
+           NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
+               goto err;
+
+#if 0
+       if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
+           CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_STRING, "version",
+           SYSCTL_DESCR("Atheros HAL version"), NULL, 0, &ath_hal_version, 0,
+           CTL_CREATE, CTL_EOL)) != 0)
+               goto err;
+#endif
+
+       if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
+           CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "dma_brt",
+           SYSCTL_DESCR("Atheros HAL DMA beacon response time"), NULL, 0,
+           &ath_hal_dma_beacon_response_time, 0, CTL_CREATE, CTL_EOL)) != 0)
+               goto err;
+
+       if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
+           CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "sw_brt",
+           SYSCTL_DESCR("Atheros HAL software beacon response time"), NULL, 0,
+           &ath_hal_sw_beacon_response_time, 0, CTL_CREATE, CTL_EOL)) != 0)
+               goto err;
+
+       if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
+           CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "swba_backoff",
+           SYSCTL_DESCR("Atheros HAL additional SWBA backoff time"), NULL, 0,
+           &ath_hal_additional_swba_backoff, 0, CTL_CREATE, CTL_EOL)) != 0)
+               goto err;
+
+#ifdef ATHHAL_DEBUG
+       if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
+           CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
+           SYSCTL_DESCR("Atheros HAL debugging printfs"), NULL, 0,
+           &ath_hal_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
+               goto err;
+#endif /* ATHHAL_DEBUG */
+       return;
+err:
+       printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
+}
+
+MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data");
+
+void*
+ath_hal_malloc(size_t size)
+{
+       void *ret;
+       ENTER
+       ret = malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
+       EXIT
+       return ret;
+}
+
+void
+ath_hal_free(void* p)
+{
+       ENTER
+       free(p, M_ATH_HAL);
+       EXIT
+}
+
+void
+ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap)
+{
+       ENTER
+       vprintf(fmt, ap);
+       EXIT
+}
+
+void
+ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
+{
+       va_list ap;
+       ENTER
+       va_start(ap, fmt);
+       ath_hal_vprintf(ah, fmt, ap);
+       va_end(ap);
+       EXIT
+}
+
+const char*
+ath_hal_ether_sprintf(const u_int8_t *mac)
+{
+       const char *ret;
+       ENTER
+       ret = ether_sprintf(mac);
+       EXIT
+       return ret;
+}
+
+#ifdef ATHHAL_DEBUG
+void
+HALDEBUG(struct ath_hal *ah, const char* fmt, ...)
+{
+       if (ath_hal_debug) {
+               va_list ap;
+               ENTER
+               va_start(ap, fmt);
+               ath_hal_vprintf(ah, fmt, ap);
+               va_end(ap);
+               EXIT
+       }
+}
+
+void
+HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...)
+{
+       if (ath_hal_debug >= level) {
+               va_list ap;
+               ENTER
+               va_start(ap, fmt);
+               ath_hal_vprintf(ah, fmt, ap);
+               va_end(ap);
+               EXIT
+       }
+}
+#endif /* ATHHAL_DEBUG */
+
+#ifdef ATHHAL_DEBUG_ALQ
+/*
+ * ALQ register tracing support.
+ *
+ * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
+ * writes to the file /tmp/ath_hal.log.  The file format is a simple
+ * fixed-size array of records.  When done logging set hw.ath.hal.alq=0
+ * and then decode the file with the arcode program (that is part of the
+ * HAL).  If you start+stop tracing the data will be appended to an
+ * existing file.
+ *
+ * NB: doesn't handle multiple devices properly; only one DEVICE record
+ *     is emitted and the different devices are not identified.
+ */
+#include <sys/alq.h>
+#include <sys/pcpu.h>
+#include <contrib/dev/ath/ah_decode.h>
+
+static struct alq *ath_hal_alq;
+static int ath_hal_alq_emitdev;        /* need to emit DEVICE record */
+static u_int ath_hal_alq_lost;         /* count of lost records */
+static const char *ath_hal_logfile = "/tmp/ath_hal.log";
+static u_int ath_hal_alq_qsize = 64*1024;
+
+static int
+ath_hal_setlogging(int enable)
+{
+       int error;
+
+       if (enable) {
+               error = kauth_authorize_network(curlwp->l_cred,
+                   KAUTH_NETWORK_INTERFACE,
+                   KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, NULL, NULL, NULL);
+               if (error == 0) {
+                       error = alq_open(&ath_hal_alq, ath_hal_logfile,
+                               curproc->p_ucred,
+                               sizeof (struct athregrec), ath_hal_alq_qsize);
+                       ath_hal_alq_lost = 0;
+                       ath_hal_alq_emitdev = 1;
+                       printf("ath_hal: logging to %s enabled\n",
+                               ath_hal_logfile);
+               }
+       } else {
+               if (ath_hal_alq)
+                       alq_close(ath_hal_alq);
+               ath_hal_alq = NULL;
+               printf("ath_hal: logging disabled\n");
+               error = 0;
+       }
+       return (error);
+}
+
+static int
+sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS)
+{
+       int error, enable;
+
+       enable = (ath_hal_alq != NULL);
+        error = sysctl_handle_int(oidp, &enable, 0, req);
+        if (error || !req->newptr)
+                return (error);
+       else
+               return (ath_hal_setlogging(enable));
+}
+SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
+       0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging");
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW,
+       &ath_hal_alq_qsize, 0, "In-memory log size (#records)");
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW,
+       &ath_hal_alq_lost, 0, "Register operations not logged");
+
+static struct ale *
+ath_hal_alq_get(struct ath_hal *ah)
+{
+       struct ale *ale;
+
+       if (ath_hal_alq_emitdev) {
+               ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
+               if (ale) {
+                       struct athregrec *r =
+                               (struct athregrec *) ale->ae_data;
+                       r->op = OP_DEVICE;
+                       r->reg = 0;
+                       r->val = ah->ah_devid;
+                       alq_post(ath_hal_alq, ale);
+                       ath_hal_alq_emitdev = 0;
+               } else
+                       ath_hal_alq_lost++;
+       }
+       ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
+       if (!ale)
+               ath_hal_alq_lost++;
+       return ale;
+}
+
+void
+ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
+{
+       bus_space_tag_t t = BUSTAG(ah);
+       ENTER
+
+       if (ath_hal_alq) {
+               struct ale *ale = ath_hal_alq_get(ah);
+               if (ale) {
+                       struct athregrec *r = (struct athregrec *) ale->ae_data;
+                       r->op = OP_WRITE;
+                       r->reg = reg;
+                       r->val = val;
+                       alq_post(ath_hal_alq, ale);
+               }
+       }
+#if _BYTE_ORDER == _BIG_ENDIAN
+       if (reg >= 0x4000 && reg < 0x5000)
+               bus_space_write_4(t, h, reg, val);
+       else
+#endif
+               bus_space_write_stream_4(t, h, reg, val);
+
+       EXIT
+}
+
+u_int32_t
+ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
+{
+       u_int32_t val;
+       bus_space_handle_t h = BUSHANDLE(ah);
+       bus_space_tag_t t = BUSTAG(ah);
+       ENTER
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+       if (reg >= 0x4000 && reg < 0x5000)
+               val = bus_space_read_4(t, h, reg);
+       else
+#endif
+               val = bus_space_read_stream_4(t, h, reg);
+
+       if (ath_hal_alq) {
+               struct ale *ale = ath_hal_alq_get(ah);
+               if (ale) {
+                       struct athregrec *r = (struct athregrec *) ale->ae_data;
+                       r->op = OP_READ;
+                       r->reg = reg;
+                       r->val = val;
+                       alq_post(ath_hal_alq, ale);
+               }
+       }
+
+       EXIT
+       return val;
+}
+
+void
+OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v)
+{
+       if (ath_hal_alq) {
+               struct ale *ale = ath_hal_alq_get(ah);
+               ENTER
+               if (ale) {
+                       struct athregrec *r = (struct athregrec *) ale->ae_data;
+                       r->op = OP_MARK;
+                       r->reg = id;
+                       r->val = v;
+                       alq_post(ath_hal_alq, ale);
+               }
+               EXIT
+       }
+}
+#elif defined(ATHHAL_DEBUG) || defined(AH_REGOPS_FUNC)
+/*
+ * Memory-mapped device register read/write.  These are here
+ * as routines when debugging support is enabled and/or when
+ * explicitly configured to use function calls.  The latter is
+ * for architectures that might need to do something before
+ * referencing memory (e.g. remap an i/o window).
+ *
+ * NB: see the comments in ah_osdep.h about byte-swapping register
+ *     reads and writes to understand what's going on below.
+ */
+
+void
+ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
+{
+       bus_space_handle_t h = BUSHANDLE(ah);
+       bus_space_tag_t t = BUSTAG(ah);
+       ENTER
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+       if (reg >= 0x4000 && reg < 0x5000)
+               bus_space_write_4(t, h, reg, val);
+       else
+#endif
+               bus_space_write_stream_4(t, h, reg, val);
+       EXIT
+}
+
+u_int32_t
+ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
+{
+       bus_space_handle_t h = BUSHANDLE(ah);
+       bus_space_tag_t t = BUSTAG(ah);
+       uint32_t ret;
+       ENTER
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+       if (reg >= 0x4000 && reg < 0x5000)
+               ret = bus_space_read_4(t, h, reg);
+       else
+#endif
+               ret = bus_space_read_stream_4(t, h, reg);
+       EXIT
+
+       return ret;
+}
+#endif /* ATHHAL_DEBUG || AH_REGOPS_FUNC */
+
+#ifdef ATHHAL_ASSERT
+void
+ath_hal_assert_failed(const char* filename, int lineno, const char *msg)
+{
+       ENTER
+       printf("Atheros HAL assertion failure: %s: line %u: %s\n",
+               filename, lineno, msg);
+       panic("ath_hal_assert");
+}
+#endif /* ATHHAL_ASSERT */
+
+/*
+ * Delay n microseconds.
+ */
+void
+ath_hal_delay(int n)
+{
+       ENTER
+       DELAY(n);
+       EXIT
+}
+
+u_int32_t
+ath_hal_getuptime(struct ath_hal *ah)
+{
+       struct bintime bt;
+       uint32_t ret;
+       ENTER
+       getbinuptime(&bt);
+       ret = (bt.sec * 1000) +
+               (((uint64_t)1000 * (uint32_t)(bt.frac >> 32)) >> 32);
+       EXIT
+       return ret;
+}
+
+void
+ath_hal_memzero(void *dst, size_t n)
+{
+       ENTER
+       (void)memset(dst, 0, n);
+       EXIT
+}
+
+void *
+ath_hal_memcpy(void *dst, const void *src, size_t n)
+{
+       void *ret;
+       ENTER
+       ret = memcpy(dst, src, n);
+       EXIT
+       return ret;
+}
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/ic/ah_osdep.h  2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,151 @@
+/*-
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: ah_osdep.h,v 1.1 2009/03/23 17:14:48 sborrill Exp $
+ */
+
+#ifndef _ATH_AH_OSDEP_H_
+#define _ATH_AH_OSDEP_H_
+/*
+ * Atheros Hardware Access Layer (HAL) OS Dependent Definitions.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/endian.h>
+#include <sys/bus.h>
+
+#include <machine/stdarg.h>
+
+/*
+ * Delay n microseconds.
+ */
+extern void ath_hal_delay(int);
+#define        OS_DELAY(_n)    ath_hal_delay(_n)
+
+#define        OS_INLINE       __inline
+#define        OS_MEMZERO(_a, _n)      ath_hal_memzero((_a), (_n))
+extern void ath_hal_memzero(void *, size_t);
+#define        OS_MEMCPY(_d, _s, _n)   ath_hal_memcpy(_d,_s,_n)
+extern void *ath_hal_memcpy(void *, const void *, size_t);
+
+#define        abs(_a)         __builtin_abs(_a)
+
+struct ath_hal;
+extern u_int32_t ath_hal_getuptime(struct ath_hal *);
+#define        OS_GETUPTIME(_ah)       ath_hal_getuptime(_ah)
+
+/*
+ * WiSoC boards overload the bus tag with information about the
+ * board layout.  We must extract the bus space tag from that
+ * indirect structure.  For everyone else the tag is passed in
+ * directly.
+ * XXX cache indirect ref privately
+ */
+#ifdef AH_SUPPORT_AR5312
+#define        BUSTAG(ah) \
+       ((bus_space_tag_t) ((struct ar531x_config *)((ah)->ah_st))->tag)
+#define        BUSHANDLE(ah)   ((bus_space_handle_t)((ah)->ah_sh))
+
+#elif defined(AH_REGOPS_FUNC)
+#define        BUSTAG(ah)      (*(bus_space_tag_t *) (ah)->ah_st)
+#define        BUSHANDLE(ah)   (*(bus_space_handle_t *)((ah)->ah_sh))
+#define        HALTAG(t)       (HAL_BUS_TAG) &(t)
+#define        HALHANDLE(h)    (HAL_BUS_HANDLE) &(h)
+#else
+#define        BUSTAG(ah)      ((bus_space_tag_t) (ah)->ah_st)
+#define        BUSHANDLE(ah)   ((bus_space_handle_t) ((ah)->ah_sh))
+#define        HALTAG(t)       (HAL_BUS_TAG) (t)
+#define        HALHANDLE(h)    (HAL_BUS_HANDLE) (h)
+#endif
+
+/*
+ * Register read/write; we assume the registers will always
+ * be memory-mapped.  Note that register accesses are done
+ * using target-specific functions when debugging is enabled
+ * (ATHHAL_DEBUG) or we are explicitly configured this way.  The
+ * latter is used on some platforms where the full i/o space
+ * cannot be directly mapped.
+ */
+#if defined(ATHHAL_DEBUG) || defined(AH_REGOPS_FUNC) || defined(ATHHAL_DEBUG_ALQ)
+#define        OS_REG_WRITE(_ah, _reg, _val)   ath_hal_reg_write(_ah, _reg, _val)
+#define        OS_REG_READ(_ah, _reg)          ath_hal_reg_read(_ah, _reg)
+
+extern void ath_hal_reg_write(struct ath_hal *ah, u_int reg, u_int32_t val);
+extern u_int32_t ath_hal_reg_read(struct ath_hal *ah, u_int reg);
+#else
+/*
+ * The hardware registers are native little-endian byte order.
+ * Big-endian hosts are handled by enabling hardware byte-swap
+ * of register reads and writes at reset.  But the PCI clock
+ * domain registers are not byte swapped!  Thus, on big-endian
+ * platforms we have to byte-swap thoese registers specifically.
+ * Most of this code is collapsed at compile time because the
+ * register values are constants.
+ */
+#define        AH_LITTLE_ENDIAN        1234
+#define        AH_BIG_ENDIAN           4321
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define OS_REG_WRITE(_ah, _reg, _val) do {                             \
+       if ( (_reg) >= 0x4000 && (_reg) < 0x5000)                       \
+               bus_space_write_4((_ah)->ah_st, (_ah)->ah_sh,           \
+                       (_reg), (_val));                                \
+       else                                                            \
+               bus_space_write_stream_4((_ah)->ah_st, (_ah)->ah_sh,    \
+                       (_reg), (_val));                                \
+} while (0)
+#define OS_REG_READ(_ah, _reg)                                         \
+       (((_reg) >= 0x4000 && (_reg) < 0x5000) ?                        \
+               bus_space_read_4((_ah)->ah_st, (_ah)->ah_sh, (_reg)) :  \
+               bus_space_read_stream_4((_ah)->ah_st, (_ah)->ah_sh, (_reg)))
+#else /* _BYTE_ORDER == _LITTLE_ENDIAN */
+#define        OS_REG_WRITE(_ah, _reg, _val)                                   \
+       bus_space_write_4((_ah)->ah_st, (_ah)->ah_sh, (_reg), (_val))
+#define        OS_REG_READ(_ah, _reg)                                          \
+       ((u_int32_t) bus_space_read_4((_ah)->ah_st, (_ah)->ah_sh, (_reg)))
+#endif /* _BYTE_ORDER */
+#endif /* ATHHAL_DEBUG || AH_REGFUNC || ATHHAL_DEBUG_ALQ */
+
+#ifdef ATHHAL_DEBUG_ALQ
+extern void OS_MARK(struct ath_hal *, u_int id, u_int32_t value);
+#else
+#define        OS_MARK(_ah, _id, _v)
+#endif
+
+typedef void * HAL_SOFTC;              /* pointer to driver/OS state */
+typedef bus_space_tag_t                HAL_BUS_TAG;    /* opaque bus i/o id tag */
+typedef bus_space_handle_t     HAL_BUS_HANDLE; /* opaque bus i/o handle */
+
+#define OS_SET_DECLARE(set, ptype)     __link_set_decl(set, ptype)
+#define OS_DATA_SET(set, sym)          __link_set_add_rodata(set, sym)
+#define OS_SET_FOREACH(pvar, set)      __link_set_foreach(pvar, set)
+
+#define __bswap16(x)                   bswap16(x)
+#define __bswap32(x)                   bswap32(x)
+
+#endif /* _ATH_AH_OSDEP_H_ */
--- /dev/null   2009-05-15 14:10:01.000000000 +0100
+++ sys/external/isc/atheros_hal/ic/opt_ah.h    2009-03-23 17:36:56.000000000 +0000
@@ -0,0 +1,91 @@
+/* $NetBSD: opt_ah.h,v 1.1 2008/12/11 05:37:40 alc Exp $ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef OPT_AH_H
+#define OPT_AH_H
+
+#include "opt_athhal.h"
+
+#ifdef ATHHAL_ASSERT
+#define AH_ASSERT              1
+#endif
+
+#ifdef ATHHAL_DEBUG
+#define AH_DEBUG               1
+#endif
+
+#ifdef ATHHAL_DEBUG_ALQ
+#define AH_DEBUG_ALQ           1
+#endif
+
+#ifdef ATHHAL_AR5210
+#define AH_SUPPORT_5210                1
+#endif
+
+#ifdef ATHHAL_AR5211
+#define AH_SUPPORT_5211                1
+#endif
+
+#ifdef ATHHAL_AR5212
+#define AH_SUPPORT_5212                1
+#endif
+
+#ifdef ATHHAL_AR5311
+#define AH_SUPPORT_5311                1
+#endif
+
+#ifdef ATHHAL_AR5312
+#define AH_SUPPORT_AR5312      1
+#endif
+
+#ifdef ATHHAL_AR2316
+#define AH_SUPPORT_2316                1
+#endif
+
+#ifdef ATHHAL_AR2317
+#define AH_SUPPORT_2317                1
+#endif
+
+#ifdef ATHHAL_AR5416
+#define AH_SUPPORT_AR5416      1
+#endif
+
+#ifdef ATHHAL_AR9280
+#define AH_SUPPORT_AR9280      1
+#endif
+
+#if defined(ATHHAL_RF2316) || \
+       defined(ATHHAL_RF2317) || \
+       defined(ATHHAL_RF2413) || \
+       defined(ATHHAL_RF2425) || \
+       defined(ATHHAL_RF5111) || \
+       defined(ATHHAL_RF5112) || \
+       defined(ATHHAL_RF5413)
+#define AH_HAS_RF
+#endif
+
+#endif /* OPT_AH_H */
Index: sys/net80211/ieee80211_var.h
===================================================================
RCS file: /cvsroot/src/sys/net80211/ieee80211_var.h,v
retrieving revision 1.26
diff -u -r1.26 ieee80211_var.h
--- sys/net80211/ieee80211_var.h        4 Mar 2007 06:03:19 -0000       1.26
+++ sys/net80211/ieee80211_var.h        16 May 2009 11:24:22 -0000
@@ -282,7 +282,7 @@
#define        IEEE80211_C_BURST       0x02000000      /* CAPABILITY: frame bursting */
#define        IEEE80211_C_WME         0x04000000      /* CAPABILITY: WME avail */
#define        IEEE80211_C_WDS         0x08000000      /* CAPABILITY: 4-addr support */
-/* 0x10000000 reserved */
+#define        IEEE80211_C_WME_TKIPMIC 0x10000000      /* CAPABILITY: TKIP MIC for QoS frame */
#define        IEEE80211_C_BGSCAN      0x20000000      /* CAPABILITY: bg scanning */
#define        IEEE80211_C_TXFRAG      0x40000000      /* CAPABILITY: tx fragments */
/* XXX protection/barker? */