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? */
