summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/pkgdefs/Makefile1
-rw-r--r--usr/src/pkgdefs/SUNWarn/Makefile39
-rw-r--r--usr/src/pkgdefs/SUNWarn/pkginfo.tmpl45
-rw-r--r--usr/src/pkgdefs/SUNWarn/postinstall91
-rw-r--r--usr/src/pkgdefs/SUNWarn/postremove50
-rw-r--r--usr/src/pkgdefs/SUNWarn/prototype_com45
-rw-r--r--usr/src/pkgdefs/SUNWarn/prototype_i38651
-rw-r--r--usr/src/pkgdefs/common_files/i.minorperm_i3864
-rw-r--r--usr/src/tools/opensolaris/license-list1
-rw-r--r--usr/src/uts/common/Makefile.files3
-rw-r--r--usr/src/uts/common/Makefile.rules7
-rw-r--r--usr/src/uts/common/io/arn/LICENSE50
-rw-r--r--usr/src/uts/common/io/arn/LICENSE.descrip1
-rw-r--r--usr/src/uts/common/io/arn/arn_ani.c891
-rw-r--r--usr/src/uts/common/io/arn/arn_ath9k.h1100
-rw-r--r--usr/src/uts/common/io/arn/arn_beacon.c515
-rw-r--r--usr/src/uts/common/io/arn/arn_calib.c1069
-rw-r--r--usr/src/uts/common/io/arn/arn_core.h877
-rw-r--r--usr/src/uts/common/io/arn/arn_eeprom.c2912
-rw-r--r--usr/src/uts/common/io/arn/arn_hw.c4149
-rw-r--r--usr/src/uts/common/io/arn/arn_hw.h1089
-rw-r--r--usr/src/uts/common/io/arn/arn_initvals.h6337
-rw-r--r--usr/src/uts/common/io/arn/arn_mac.c1107
-rw-r--r--usr/src/uts/common/io/arn/arn_main.c3190
-rw-r--r--usr/src/uts/common/io/arn/arn_phy.c451
-rw-r--r--usr/src/uts/common/io/arn/arn_phy.h555
-rw-r--r--usr/src/uts/common/io/arn/arn_rc.c704
-rw-r--r--usr/src/uts/common/io/arn/arn_rc.h221
-rw-r--r--usr/src/uts/common/io/arn/arn_recv.c461
-rw-r--r--usr/src/uts/common/io/arn/arn_reg.h1485
-rw-r--r--usr/src/uts/common/io/arn/arn_regd.c1046
-rw-r--r--usr/src/uts/common/io/arn/arn_regd.h425
-rw-r--r--usr/src/uts/common/io/arn/arn_regd_common.h2117
-rw-r--r--usr/src/uts/common/io/arn/arn_xmit.c1016
-rw-r--r--usr/src/uts/intel/Makefile.intel.shared1
-rw-r--r--usr/src/uts/intel/arn/Makefile94
-rw-r--r--usr/src/uts/intel/os/minor_perm2
37 files changed, 32202 insertions, 0 deletions
diff --git a/usr/src/pkgdefs/Makefile b/usr/src/pkgdefs/Makefile
index 03d6180b1f..eaf2299317 100644
--- a/usr/src/pkgdefs/Makefile
+++ b/usr/src/pkgdefs/Makefile
@@ -115,6 +115,7 @@ i386_SUBDIRS= \
SUNWamt \
SUNWamt-lms \
SUNWarcmsr \
+ SUNWarn \
SUNWatheros \
SUNWatigfx \
SUNWatu \
diff --git a/usr/src/pkgdefs/SUNWarn/Makefile b/usr/src/pkgdefs/SUNWarn/Makefile
new file mode 100644
index 0000000000..601f5724c1
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWarn/Makefile
@@ -0,0 +1,39 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.com
+
+DATAFILES += depend
+LICENSEFILES += ../../uts/common/io/arn/LICENSE
+CDDL=
+
+.KEEP_STATE:
+
+all: $(FILES) postinstall postremove
+install: all pkg
+
+include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWarn/pkginfo.tmpl b/usr/src/pkgdefs/SUNWarn/pkginfo.tmpl
new file mode 100644
index 0000000000..8cbb3c6f70
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWarn/pkginfo.tmpl
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+PKG="SUNWarn"
+NAME="Atheros IEEE 802.11 Wireless NIC Driver"
+ARCH="ISA"
+VERSION="ONVERS,REV=0.0.0"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGVERS="1.0"
+SUNW_PKGTYPE="root"
+MAXINST="1000"
+CATEGORY="system"
+VENDOR="Sun Microsystems, Inc."
+DESC="Atheros AR9xxx 802.11 Wireless NIC Driver"
+CLASSES="none"
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+BASEDIR=/
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="true"
+SUNW_PKG_THISZONE="false"
diff --git a/usr/src/pkgdefs/SUNWarn/postinstall b/usr/src/pkgdefs/SUNWarn/postinstall
new file mode 100644
index 0000000000..39dede0c32
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWarn/postinstall
@@ -0,0 +1,91 @@
+#! /usr/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+# Driver info
+DRV=arn
+DRVALIAS='"pciex168c,2a" "pciex168c,2b"'
+
+BASEDIR=${BASEDIR:-/}
+
+# Function: check_add_drv()
+#
+# This function will check if add_drv has been executed.
+# If not simply calls add_drv. Otherwise adds entries to
+# driver_aliases, driver_classes and minor_perm if necessary.
+# The syntax of this function is the same as add_drv.
+
+check_add_drv()
+{
+ CMD="add_drv"
+
+ ALIAS=""
+ ALIASDIR="${BASEDIR}"/etc/driver_aliases
+ while getopts i:b: opt 2>/dev/null; do
+ case "$opt" in
+ i) CMD="${CMD} -i ${OPTARG}"
+ ALIAS=`echo ${OPTARG} | /usr/bin/sed -e "s/'//g"`
+ ;;
+ b) if [ "${OPTARG}" != "/" ]; then
+ # On a client
+ # modify the sytem files and touch
+ # /reconfigure for reconfigure reboot
+ CMD="${CMD} -b \"${OPTARG}\""
+ fi
+ ;;
+ \?) echo "check_add_drv(): Unknown option $opt"
+ return
+ ;;
+ esac
+ done
+ shift `/usr/bin/expr ${OPTIND} - 1`
+ DRIVER=$1
+ CMD="${CMD} ${DRIVER}"
+
+ # Make sure add_drv has not been previously executed
+ # before attempting to add the driver
+ /usr/bin/egrep -s "^${DRIVER}[ ]" "$BASEDIR"/etc/name_to_major
+
+ if [ $? -ne 0 ]; then
+ eval ${CMD}
+ if [ $? -ne 0 ]; then
+ echo "Failed add_drv ${DRIVER}!\n" >&2
+ exit 1
+ fi
+ else
+ # Add driver entry if necessary
+ if [ -n "${ALIAS}" ]; then
+ for i in ${ALIAS}; do
+ /usr/bin/egrep -s "^${DRIVER}[ ]+$i" ${ALIASDIR}
+ if [ $? -ne 0 ]; then
+ echo "${DRIVER} $i" >> ${ALIASDIR}
+ fi
+ done
+ fi
+ fi
+}
+
+check_add_drv -b "${BASEDIR}" -i "'${DRVALIAS}'" ${DRV}
diff --git a/usr/src/pkgdefs/SUNWarn/postremove b/usr/src/pkgdefs/SUNWarn/postremove
new file mode 100644
index 0000000000..6884880e87
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWarn/postremove
@@ -0,0 +1,50 @@
+#! /usr/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+DRV=arn
+BASEDIR=${BASEDIR:-/}
+
+# Select the correct rem_drv options to execute.
+# Only attempt to unload the driver on a running system
+if [ "$BASEDIR" = "/" ]; then
+ REM_DRV="rem_drv"
+else
+ REM_DRV="rem_drv -b ${BASEDIR}"
+fi
+
+# Make sure rem_drv has not been previously executed
+# before attempting to remove the driver
+/usr/bin/egrep -s "^${DRV}[ ]" $BASEDIR/etc/name_to_major
+if [ $? -eq 0 ]; then
+ ${REM_DRV} ${DRV}
+ if [ $? -ne 0 ]; then
+ echo "Failed rem_drv ${DRV}!\n" >&2
+ exit 1
+ fi
+fi
+
+exit 0
diff --git a/usr/src/pkgdefs/SUNWarn/prototype_com b/usr/src/pkgdefs/SUNWarn/prototype_com
new file mode 100644
index 0000000000..30c5ed788a
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWarn/prototype_com
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# SUNWarn
+#
+
+i pkginfo
+i copyright
+i depend
+i postinstall
+i postremove
diff --git a/usr/src/pkgdefs/SUNWarn/prototype_i386 b/usr/src/pkgdefs/SUNWarn/prototype_i386
new file mode 100644
index 0000000000..cdc33a44ad
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWarn/prototype_i386
@@ -0,0 +1,51 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# SUNWarn
+#
+
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+
+# Atheros IEEE 80211n NIC driver
+d none kernel 0755 root sys
+d none kernel/drv 0755 root sys
+f none kernel/drv/arn 0755 root sys
+d none kernel/drv/amd64 0755 root sys
+f none kernel/drv/amd64/arn 0755 root sys
diff --git a/usr/src/pkgdefs/common_files/i.minorperm_i386 b/usr/src/pkgdefs/common_files/i.minorperm_i386
index 2d85ce5c07..b03dcff7df 100644
--- a/usr/src/pkgdefs/common_files/i.minorperm_i386
+++ b/usr/src/pkgdefs/common_files/i.minorperm_i386
@@ -109,6 +109,7 @@ clone:nge 0600 root sys 0666 root sys /dev/nge
clone:chxge 0600 root sys 0666 root sys /dev/chxge
clone:pcn 0600 root sys 0666 root sys /dev/pcn
clone:rtls 0600 root sys 0666 root sys /dev/rtls
+clone:arn 0600 root sys 0666 root sys /dev/arn
clone:ath 0600 root sys 0666 root sys /dev/ath
clone:atu 0600 root sys 0666 root sys /dev/atu
clone:ipw 0600 root sys 0666 root sys /dev/ipw
@@ -139,6 +140,7 @@ e1000g:* 0666 root root 0666 root sys /dev/e1000g*
chxge:* 0600 root sys 0666 root sys /dev/chxge*
pcn:* 0600 root sys 0666 root sys /dev/pcn*
rtls:* 0600 root sys 0666 root sys /dev/rtls*
+arn:* 0600 root sys 0666 root sys /dev/arn*
ath:* 0600 root sys 0666 root sys /dev/ath*
atu:* 0600 root sys 0666 root sys /dev/atu*
ipw:* 0600 root sys 0666 root sys /dev/ipw*
@@ -296,6 +298,7 @@ clone:e1000g
clone:chxge
clone:pcn
clone:rtls
+clone:arn
clone:ath
clone:atu
clone:ipw
@@ -326,6 +329,7 @@ e1000g:*
chxge:*
pcn:*
rtls:*
+arn:*
ath:*
atu:*
ipw:*
diff --git a/usr/src/tools/opensolaris/license-list b/usr/src/tools/opensolaris/license-list
index 52908efbc2..6500077d8e 100644
--- a/usr/src/tools/opensolaris/license-list
+++ b/usr/src/tools/opensolaris/license-list
@@ -139,6 +139,7 @@ usr/src/uts/common/inet/tcp/THIRDPARTYLICENSE
usr/src/uts/common/io/THIRDPARTYLICENSE.etheraddr
usr/src/uts/common/io/aac/THIRDPARTYLICENSE
usr/src/uts/common/io/afe/THIRDPARTYLICENSE
+usr/src/uts/common/io/arn/LICENSE
usr/src/uts/common/io/ath/LICENSE
usr/src/uts/common/io/atu/THIRDPARTYLICENSE
usr/src/uts/common/io/chxge/com/THIRDPARTYLICENSE
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index f68f88c325..c99d41bb4e 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1702,6 +1702,9 @@ RGE_OBJS += rge_main.o rge_chip.o rge_ndd.o rge_kstats.o rge_log.o rge_rxtx.o
URTW_OBJS += urtw.o
+ARN_OBJS += arn_hw.o arn_eeprom.o arn_mac.o arn_calib.o arn_ani.o arn_phy.o arn_regd.o arn_beacon.o \
+ arn_main.o arn_recv.o arn_xmit.o arn_rc.o
+
ATH_OBJS += ath_aux.o ath_main.o ath_osdep.o ath_rate.o
ATU_OBJS += atu.o
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index cc36d33d2b..2922f86b8a 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -528,6 +528,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/io/afe/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/arn/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/ath/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -1763,6 +1767,9 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/aac/%.c
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/afe/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/arn/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/ath/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
diff --git a/usr/src/uts/common/io/arn/LICENSE b/usr/src/uts/common/io/arn/LICENSE
new file mode 100644
index 0000000000..99b8956fb1
--- /dev/null
+++ b/usr/src/uts/common/io/arn/LICENSE
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+ /*
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * Copyright (c) 2004-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.
+ */
+
+ /*
+ * Copyright (c) 2004 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * 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.
+ */
diff --git a/usr/src/uts/common/io/arn/LICENSE.descrip b/usr/src/uts/common/io/arn/LICENSE.descrip
new file mode 100644
index 0000000000..9ed013caa0
--- /dev/null
+++ b/usr/src/uts/common/io/arn/LICENSE.descrip
@@ -0,0 +1 @@
+Atheros AR5416/5418/9280/9281/9285 IEEE802.11 a/b/g/n Wireless Network Driver
diff --git a/usr/src/uts/common/io/arn/arn_ani.c b/usr/src/uts/common/io/arn/arn_ani.c
new file mode 100644
index 0000000000..bc83d614ce
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_ani.c
@@ -0,0 +1,891 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include "arn_core.h"
+#include "arn_hw.h"
+#include "arn_reg.h"
+#include "arn_phy.h"
+
+static int
+ath9k_hw_get_ani_channel_idx(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
+ if (ahp->ah_ani[i].c.channel == chan->channel)
+ return (i);
+ if (ahp->ah_ani[i].c.channel == 0) {
+ ahp->ah_ani[i].c.channel = chan->channel;
+ ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
+ return (i);
+ }
+ }
+
+ ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_get_ani_channel_idx(): "
+ "No more channel states left. Using channel 0\n"));
+
+ return (0);
+}
+
+static boolean_t
+ath9k_hw_ani_control(struct ath_hal *ah, enum ath9k_ani_cmd cmd, int param)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState = ahp->ah_curani;
+
+ switch (cmd & ahp->ah_ani_function) {
+ case ATH9K_ANI_NOISE_IMMUNITY_LEVEL: {
+ uint32_t level = param;
+
+ if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "ah->ah_sc, ATH_DBG_ANI",
+ "%s: level out of range (%u > %u)\n",
+ __func__, level,
+ (unsigned)ARRAY_SIZE(ahp->ah_totalSizeDesired)));
+
+ return (B_FALSE);
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_TOT_DES,
+ ahp->ah_totalSizeDesired[level]);
+ REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+ AR_PHY_AGC_CTL1_COARSE_LOW,
+ ahp->ah_coarseLow[level]);
+ REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+ AR_PHY_AGC_CTL1_COARSE_HIGH,
+ ahp->ah_coarseHigh[level]);
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRPWR,
+ ahp->ah_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 = (uint8_t)level; /* LINT */
+ break;
+ }
+ case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
+ const int m1ThreshLow[] = { 127, 50 };
+ const int m2ThreshLow[] = { 127, 40 };
+ const int m1Thresh[] = { 127, 0x4d };
+ const int m2Thresh[] = { 127, 0x40 };
+ const int m2CountThr[] = { 31, 16 };
+ const int m2CountThrLow[] = { 63, 48 };
+ uint32_t on = param ? 1 : 0;
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+ m1ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+ m2ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M1_THRESH,
+ m1Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2_THRESH,
+ m2Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2COUNT_THR,
+ m2CountThr[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+ m2CountThrLow[on]);
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+ m1ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+ m2ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH,
+ m1Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH,
+ m2Thresh[on]);
+
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+ else
+ REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+ if (!on != aniState->ofdmWeakSigDetectOff) {
+ if (on)
+ ahp->ah_stats.ast_ani_ofdmon++;
+ else
+ ahp->ah_stats.ast_ani_ofdmoff++;
+ aniState->ofdmWeakSigDetectOff = !on;
+ }
+ break;
+ }
+ case ATH9K_ANI_CCK_WEAK_SIGNAL_THR: {
+ const int weakSigThrCck[] = { 8, 6 };
+ uint32_t high = param ? 1 : 0;
+
+ REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+ AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
+ weakSigThrCck[high]);
+ if (high != aniState->cckWeakSigThreshold) {
+ if (high)
+ ahp->ah_stats.ast_ani_cckhigh++;
+ else
+ ahp->ah_stats.ast_ani_ccklow++;
+ /* LINT */
+ aniState->cckWeakSigThreshold = (uint8_t)high;
+ }
+ break;
+ }
+ case ATH9K_ANI_FIRSTEP_LEVEL: {
+ const int firstep[] = { 0, 4, 8 };
+ uint32_t level = param;
+
+ if (level >= ARRAY_SIZE(firstep)) {
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "%s: level out of range (%u > %u)\n",
+ __func__, level,
+ (unsigned)ARRAY_SIZE(firstep)));
+
+ return (B_FALSE);
+ }
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRSTEP, 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 = (uint8_t)level; /* LINT */
+ break;
+ }
+ case ATH9K_ANI_SPUR_IMMUNITY_LEVEL: {
+ const int cycpwrThr1[] =
+ { 2, 4, 6, 8, 10, 12, 14, 16 };
+ uint32_t level = param;
+
+ if (level >= ARRAY_SIZE(cycpwrThr1)) {
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "%s: level out of range (%u > %u)\n",
+ __func__, level,
+ (unsigned)ARRAY_SIZE(cycpwrThr1)));
+
+ return (B_FALSE);
+ }
+ REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+ AR_PHY_TIMING5_CYCPWR_THR1, 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 = (uint8_t)level; /* LINT */
+ break;
+ }
+ case ATH9K_ANI_PRESENT:
+ break;
+ default:
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "%s: invalid cmd %u\n", __func__, cmd));
+ return (B_FALSE);
+ }
+
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "%s: ANI parameters:\n", __func__));
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
+ "ofdmWeakSigDetectOff=%d\n",
+ aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
+ !aniState->ofdmWeakSigDetectOff));
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "cckWeakSigThreshold=%d, "
+ "firstepLevel=%d, listenTime=%d\n",
+ aniState->cckWeakSigThreshold, aniState->firstepLevel,
+ aniState->listenTime));
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
+ aniState->cycleCount, aniState->ofdmPhyErrCount,
+ aniState->cckPhyErrCount));
+
+ return (B_TRUE);
+}
+
+static void
+ath9k_hw_update_mibstats(struct ath_hal *ah, struct ath9k_mib_stats *stats)
+{
+ stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
+ stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
+ stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
+ stats->rts_good += REG_READ(ah, AR_RTS_OK);
+ stats->beacons += REG_READ(ah, AR_BEACON_CNT);
+}
+
+static void
+ath9k_ani_restart(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = ahp->ah_curani;
+
+ aniState->listenTime = 0;
+ if (ahp->ah_hasHwPhyCounters) {
+ if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
+ aniState->ofdmPhyErrBase = 0;
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "OFDM Trigger is too high for hw counters\n"));
+ } else {
+ aniState->ofdmPhyErrBase =
+ AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+ }
+ if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
+ aniState->cckPhyErrBase = 0;
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "CCK Trigger is too high for hw counters\n"));
+ } else {
+ aniState->cckPhyErrBase =
+ AR_PHY_COUNTMAX - aniState->cckTrigHigh;
+ }
+
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "%s: Writing ofdmbase=%u cckbase=%u\n",
+ __func__, aniState->ofdmPhyErrBase,
+ aniState->cckPhyErrBase));
+
+ REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+ }
+ aniState->ofdmPhyErrCount = 0;
+ aniState->cckPhyErrCount = 0;
+}
+
+static void
+ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *chan = ah->ah_curchan;
+ struct ar5416AniState *aniState;
+ enum wireless_mode mode;
+ int32_t rssi;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = ahp->ah_curani;
+
+ if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel + 1)) {
+ return;
+ }
+ }
+
+ if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel + 1)) {
+ return;
+ }
+ }
+
+ if (ah->ah_opmode == ATH9K_M_HOSTAP) {
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ }
+ return;
+ }
+ rssi = BEACON_RSSI(ahp);
+ if (rssi > aniState->rssiThrHigh) {
+ if (!aniState->ofdmWeakSigDetectOff) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ B_FALSE)) {
+ (void) ath9k_hw_ani_control(ah,
+ ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+ return;
+ }
+ }
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ return;
+ }
+ } else if (rssi > aniState->rssiThrLow) {
+ if (aniState->ofdmWeakSigDetectOff)
+ (void) ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ B_TRUE);
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ return;
+ } else {
+ mode = ath9k_hw_chan2wmode(ah, chan);
+ if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
+ if (!aniState->ofdmWeakSigDetectOff)
+ (void) ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ B_FALSE);
+ if (aniState->firstepLevel > 0)
+ (void) ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL, 0);
+ return;
+ }
+ }
+}
+
+static void
+ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *chan = ah->ah_curchan;
+ struct ar5416AniState *aniState;
+ enum wireless_mode mode;
+ int32_t rssi;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = ahp->ah_curani;
+ if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel + 1)) {
+ return;
+ }
+ }
+ if (ah->ah_opmode == ATH9K_M_HOSTAP) {
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ }
+ return;
+ }
+ rssi = BEACON_RSSI(ahp);
+ if (rssi > aniState->rssiThrLow) {
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ } else {
+ mode = ath9k_hw_chan2wmode(ah, chan);
+ if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
+ if (aniState->firstepLevel > 0)
+ (void) ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL, 0);
+ }
+ }
+}
+
+static void
+ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+ int32_t rssi;
+
+ aniState = ahp->ah_curani;
+
+ if (ah->ah_opmode == ATH9K_M_HOSTAP) {
+ if (aniState->firstepLevel > 0) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel - 1))
+ return;
+ }
+ } else {
+ rssi = BEACON_RSSI(ahp);
+ if (rssi > aniState->rssiThrHigh) {
+ /* XXX: Handle me */
+ ARN_DBG((ARN_DBG_ANI, "arn: ath9k_ani_reset():\n"));
+ } else if (rssi > aniState->rssiThrLow) {
+ if (aniState->ofdmWeakSigDetectOff) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ B_TRUE) == B_TRUE)
+ return;
+ }
+ if (aniState->firstepLevel > 0) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel - 1) == B_TRUE)
+ return;
+ }
+ } else {
+ if (aniState->firstepLevel > 0) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel - 1) == B_TRUE)
+ return;
+ }
+ }
+ }
+
+ if (aniState->spurImmunityLevel > 0) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel - 1))
+ return;
+ }
+
+ if (aniState->noiseImmunityLevel > 0) {
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel - 1);
+ return;
+ }
+}
+
+static int32_t
+ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+ uint32_t txFrameCount, rxFrameCount, cycleCount;
+ int32_t listenTime;
+
+ txFrameCount = REG_READ(ah, AR_TFCNT);
+ rxFrameCount = REG_READ(ah, AR_RFCNT);
+ cycleCount = REG_READ(ah, AR_CCCNT);
+
+ aniState = ahp->ah_curani;
+ if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
+
+ 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) / 44000;
+ }
+ aniState->cycleCount = cycleCount;
+ aniState->txFrameCount = txFrameCount;
+ aniState->rxFrameCount = rxFrameCount;
+
+ return (listenTime);
+}
+
+void
+ath9k_ani_reset(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+ struct ath9k_channel *chan = ah->ah_curchan;
+ int index;
+
+ /* For Lint Reasons */
+ boolean_t ANI_USE_OFDM_WEAK_SIG = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+
+ if (!DO_ANI(ah))
+ return;
+
+ index = ath9k_hw_get_ani_channel_idx(ah, chan);
+ aniState = &ahp->ah_ani[index];
+ ahp->ah_curani = aniState;
+
+ if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA &&
+ ah->ah_opmode != ATH9K_M_IBSS) {
+ ARN_DBG((ARN_DBG_ANI, "arn: ath9k_ani_reset(): "
+ "Reset ANI state opmode %u\n", ah->ah_opmode));
+ ahp->ah_stats.ast_ani_reset++;
+
+ (void) ath9k_hw_ani_control(ah,
+ ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
+ (void) ath9k_hw_ani_control(ah,
+ ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
+ (void) ath9k_hw_ani_control
+ (ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ !ANI_USE_OFDM_WEAK_SIG /* !ATH9K_ANI_USE_OFDM_WEAK_SIG */);
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+ ATH9K_ANI_CCK_WEAK_SIG_THR);
+
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+ ATH9K_RX_FILTER_PHYERR);
+
+ if (ah->ah_opmode == ATH9K_M_HOSTAP) {
+ ahp->ah_curani->ofdmTrigHigh =
+ ah->ah_config.ofdm_trig_high;
+ ahp->ah_curani->ofdmTrigLow =
+ ah->ah_config.ofdm_trig_low;
+ ahp->ah_curani->cckTrigHigh =
+ ah->ah_config.cck_trig_high;
+ ahp->ah_curani->cckTrigLow =
+ ah->ah_config.cck_trig_low;
+ }
+ ath9k_ani_restart(ah);
+ return;
+ }
+
+ if (aniState->noiseImmunityLevel != 0)
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel);
+ if (aniState->spurImmunityLevel != 0)
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel);
+ if (aniState->ofdmWeakSigDetectOff)
+ (void) ath9k_hw_ani_control
+ (ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ !aniState->ofdmWeakSigDetectOff);
+ if (aniState->cckWeakSigThreshold)
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+ aniState->cckWeakSigThreshold);
+ if (aniState->firstepLevel != 0)
+ (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel);
+ if (ahp->ah_hasHwPhyCounters) {
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
+ ~ATH9K_RX_FILTER_PHYERR);
+ ath9k_ani_restart(ah);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ } else {
+ ath9k_ani_restart(ah);
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+ ATH9K_RX_FILTER_PHYERR);
+ }
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_ani_monitor(struct ath_hal *ah, const struct ath9k_node_stats *stats,
+ struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+ int32_t listenTime;
+
+ aniState = ahp->ah_curani;
+ ahp->ah_stats.ast_nodestats = *stats;
+
+ listenTime = ath9k_hw_ani_get_listen_time(ah);
+ if (listenTime < 0) {
+ ahp->ah_stats.ast_ani_lneg++;
+ ath9k_ani_restart(ah);
+ return;
+ }
+
+ aniState->listenTime += listenTime;
+
+ if (ahp->ah_hasHwPhyCounters) {
+ uint32_t phyCnt1, phyCnt2;
+ uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+ phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+
+ if (phyCnt1 < aniState->ofdmPhyErrBase ||
+ phyCnt2 < aniState->cckPhyErrBase) {
+ if (phyCnt1 < aniState->ofdmPhyErrBase) {
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "%s: phyCnt1 0x%x, resetting "
+ "counter value to 0x%x\n",
+ __func__, phyCnt1,
+ aniState->ofdmPhyErrBase));
+ REG_WRITE(ah, AR_PHY_ERR_1,
+ aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1,
+ AR_PHY_ERR_OFDM_TIMING);
+ }
+ if (phyCnt2 < aniState->cckPhyErrBase) {
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "%s: phyCnt2 0x%x, resetting "
+ "counter value to 0x%x\n",
+ __func__, phyCnt2,
+ aniState->cckPhyErrBase));
+ REG_WRITE(ah, AR_PHY_ERR_2,
+ aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2,
+ AR_PHY_ERR_CCK_TIMING);
+ }
+ return;
+ }
+
+ ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ ahp->ah_stats.ast_ani_ofdmerrs +=
+ ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+ aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+ cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+ ahp->ah_stats.ast_ani_cckerrs +=
+ cckPhyErrCnt - aniState->cckPhyErrCount;
+ aniState->cckPhyErrCount = cckPhyErrCnt;
+ }
+
+ if (!DO_ANI(ah))
+ return;
+
+ if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
+ if (aniState->ofdmPhyErrCount <= aniState->listenTime *
+ aniState->ofdmTrigLow / 1000 &&
+ aniState->cckPhyErrCount <= aniState->listenTime *
+ aniState->cckTrigLow / 1000)
+ ath9k_hw_ani_lower_immunity(ah);
+ ath9k_ani_restart(ah);
+ } else if (aniState->listenTime > ahp->ah_aniPeriod) {
+ if (aniState->ofdmPhyErrCount > aniState->listenTime *
+ aniState->ofdmTrigHigh / 1000) {
+ ath9k_hw_ani_ofdm_err_trigger(ah);
+ ath9k_ani_restart(ah);
+ } else if (aniState->cckPhyErrCount >
+ aniState->listenTime * aniState->cckTrigHigh / 1000) {
+ ath9k_hw_ani_cck_err_trigger(ah);
+ ath9k_ani_restart(ah);
+ }
+ }
+}
+
+boolean_t
+ath9k_hw_phycounters(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return (ahp->ah_hasHwPhyCounters ? B_TRUE : B_FALSE);
+}
+
+void
+ath9k_enable_mib_counters(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ ARN_DBG((ARN_DBG_ANI, "arn: ath9k_enable_mib_counters(): "
+ "Enable MIB counters\n"));
+
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+ REG_WRITE(ah, AR_FILT_OFDM, 0);
+ REG_WRITE(ah, AR_FILT_CCK, 0);
+ REG_WRITE(ah, AR_MIBC,
+ ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+}
+
+void
+ath9k_hw_disable_mib_counters(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ ARN_DBG((ARN_DBG_ANI,
+ "arn: ath9k_hw_disable_mib_counters(): "
+ "Disable MIB counters\n"));
+
+ REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
+
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+ REG_WRITE(ah, AR_FILT_OFDM, 0);
+ REG_WRITE(ah, AR_FILT_CCK, 0);
+}
+
+uint32_t
+ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah, uint32_t *rxc_pcnt,
+ uint32_t *rxf_pcnt, uint32_t *txf_pcnt)
+{
+ static uint32_t cycles, rx_clear, rx_frame, tx_frame;
+ uint32_t good = 1;
+
+ uint32_t rc = REG_READ(ah, AR_RCCNT);
+ uint32_t rf = REG_READ(ah, AR_RFCNT);
+ uint32_t tf = REG_READ(ah, AR_TFCNT);
+ uint32_t cc = REG_READ(ah, AR_CCCNT);
+
+ if (cycles == 0 || cycles > cc) {
+ ARN_DBG((ARN_DBG_CHANNEL,
+ "arn: ath9k_hw_GetMibCycleCountsPct(): "
+ "cycle counter wrap. ExtBusy = 0\n"));
+ good = 0;
+ } else {
+ uint32_t cc_d = cc - cycles;
+ uint32_t rc_d = rc - rx_clear;
+ uint32_t rf_d = rf - rx_frame;
+ uint32_t tf_d = tf - tx_frame;
+
+ if (cc_d != 0) {
+ *rxc_pcnt = rc_d * 100 / cc_d;
+ *rxf_pcnt = rf_d * 100 / cc_d;
+ *txf_pcnt = tf_d * 100 / cc_d;
+ } else {
+ good = 0;
+ }
+ }
+
+ cycles = cc;
+ rx_frame = rf;
+ rx_clear = rc;
+ tx_frame = tf;
+
+ return (good);
+}
+
+/*
+ * Process a MIB interrupt. We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
+void
+ath9k_hw_procmibevent(struct ath_hal *ah,
+ const struct ath9k_node_stats *stats)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t phyCnt1, phyCnt2;
+
+ /* Reset these counters regardless */
+ REG_WRITE(ah, AR_FILT_OFDM, 0);
+ REG_WRITE(ah, AR_FILT_CCK, 0);
+ if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
+ REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+
+ /* Clear the mib counters and save them in the stats */
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+ ahp->ah_stats.ast_nodestats = *stats;
+
+ if (!DO_ANI(ah))
+ return;
+
+ /* NB: these are not reset-on-read */
+ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+ phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+ if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
+ ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+ struct ar5416AniState *aniState = ahp->ah_curani;
+ uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+ /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
+ ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ ahp->ah_stats.ast_ani_ofdmerrs +=
+ ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+ aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+ cckPhyErrCnt = phyCnt2 - aniState->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 > aniState->ofdmTrigHigh)
+ ath9k_hw_ani_ofdm_err_trigger(ah);
+ if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
+ ath9k_hw_ani_cck_err_trigger(ah);
+ /* NB: always restart to insure the h/w counters are reset */
+ ath9k_ani_restart(ah);
+ }
+}
+
+void
+ath9k_hw_ani_setup(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+ const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+ const int coarseLow[] = { -64, -64, -64, -64, -70 };
+ const int firpwr[] = { -78, -78, -78, -78, -80 };
+
+ for (i = 0; i < 5; i++) {
+ ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
+ ahp->ah_coarseHigh[i] = coarseHigh[i];
+ ahp->ah_coarseLow[i] = coarseLow[i];
+ ahp->ah_firpwr[i] = firpwr[i];
+ }
+}
+
+void
+ath9k_hw_ani_attach(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ /* For Lint Reasons */
+ boolean_t ANI_USE_OFDM_WEAK_SIG = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+
+ ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_ani_attach(): "
+ "Attach ANI\n"));
+
+ ahp->ah_hasHwPhyCounters = 1;
+
+ (void) memset(ahp->ah_ani, 0, sizeof (ahp->ah_ani));
+ for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
+ ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
+ ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
+ ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
+ ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
+ ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+ ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+ ahp->ah_ani[i].ofdmWeakSigDetectOff =
+ !ANI_USE_OFDM_WEAK_SIG /* !ATH9K_ANI_USE_OFDM_WEAK_SIG */;
+ ahp->ah_ani[i].cckWeakSigThreshold =
+ ATH9K_ANI_CCK_WEAK_SIG_THR;
+ ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+ ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+ if (ahp->ah_hasHwPhyCounters) {
+ ahp->ah_ani[i].ofdmPhyErrBase =
+ AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
+ ahp->ah_ani[i].cckPhyErrBase =
+ AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
+ }
+ }
+ if (ahp->ah_hasHwPhyCounters) {
+ ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_ani_attach(): "
+ "Setting OfdmErrBase = 0x%08x\n",
+ ahp->ah_ani[0].ofdmPhyErrBase));
+ ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_ani_attach(): "
+ "Setting cckErrBase = 0x%08x\n",
+ ahp->ah_ani[0].cckPhyErrBase));
+
+ REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
+ ath9k_enable_mib_counters(ah);
+ }
+ ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
+ if (ah->ah_config.enable_ani)
+ ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
+}
+
+void
+ath9k_hw_ani_detach(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_ani_detach(): "
+ "Detach ANI\n"));
+
+ if (ahp->ah_hasHwPhyCounters) {
+ ath9k_hw_disable_mib_counters(ah);
+ REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ REG_WRITE(ah, AR_PHY_ERR_2, 0);
+ }
+}
diff --git a/usr/src/uts/common/io/arn/arn_ath9k.h b/usr/src/uts/common/io/arn/arn_ath9k.h
new file mode 100644
index 0000000000..9d339c1c7d
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_ath9k.h
@@ -0,0 +1,1100 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARN_ATH9K_H
+#define _ARN_ATH9K_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum ath9k_band {
+ ATH9K_BAND_2GHZ,
+ ATH9K_BAND_5GHZ,
+ ATH9K_NUM_BANDS
+};
+
+#define ATHEROS_VENDOR_ID 0x168c
+
+#define AR5416_DEVID_PCI 0x0023
+#define AR5416_DEVID_PCIE 0x0024
+#define AR9160_DEVID_PCI 0x0027
+#define AR9280_DEVID_PCI 0x0029
+#define AR9280_DEVID_PCIE 0x002a
+#define AR9285_DEVID_PCIE 0x002b
+
+#define AR5416_AR9100_DEVID 0x000b
+
+#define AR_SUBVENDOR_ID_NOG 0x0e11
+#define AR_SUBVENDOR_ID_NEW_A 0x7065
+
+#define ATH9K_TXERR_XRETRY 0x01
+#define ATH9K_TXERR_FILT 0x02
+#define ATH9K_TXERR_FIFO 0x04
+#define ATH9K_TXERR_XTXOP 0x08
+#define ATH9K_TXERR_TIMER_EXPIRED 0x10
+
+#define ATH9K_TX_BA 0x01
+#define ATH9K_TX_PWRMGMT 0x02
+#define ATH9K_TX_DESC_CFG_ERR 0x04
+#define ATH9K_TX_DATA_UNDERRUN 0x08
+#define ATH9K_TX_DELIM_UNDERRUN 0x10
+#define ATH9K_TX_SW_ABORTED 0x40
+#define ATH9K_TX_SW_FILTERED 0x80
+
+/* should be changed later */
+#define BIT(n) (1UL << (n))
+
+struct ath_tx_status {
+ uint32_t ts_tstamp;
+ uint16_t ts_seqnum;
+ uint8_t ts_status;
+ uint8_t ts_ratecode;
+ uint8_t ts_rateindex;
+ int8_t ts_rssi;
+ uint8_t ts_shortretry;
+ uint8_t ts_longretry;
+ uint8_t ts_virtcol;
+ uint8_t ts_antenna;
+ uint8_t ts_flags;
+ int8_t ts_rssi_ctl0;
+ int8_t ts_rssi_ctl1;
+ int8_t ts_rssi_ctl2;
+ int8_t ts_rssi_ext0;
+ int8_t ts_rssi_ext1;
+ int8_t ts_rssi_ext2;
+ uint8_t pad[3];
+ uint32_t ba_low;
+ uint32_t ba_high;
+ uint32_t evm0;
+ uint32_t evm1;
+ uint32_t evm2;
+};
+
+struct ath_rx_status {
+ uint32_t rs_tstamp;
+ uint16_t rs_datalen;
+ uint8_t rs_status;
+ uint8_t rs_phyerr;
+ int8_t rs_rssi;
+ uint8_t rs_keyix;
+ uint8_t rs_rate;
+ uint8_t rs_antenna;
+ uint8_t rs_more;
+ int8_t rs_rssi_ctl0;
+ int8_t rs_rssi_ctl1;
+ int8_t rs_rssi_ctl2;
+ int8_t rs_rssi_ext0;
+ int8_t rs_rssi_ext1;
+ int8_t rs_rssi_ext2;
+ uint8_t rs_isaggr;
+ uint8_t rs_moreaggr;
+ uint8_t rs_num_delims;
+ uint8_t rs_flags;
+ uint32_t evm0;
+ uint32_t evm1;
+ uint32_t evm2;
+};
+
+#define ATH9K_RXERR_CRC 0x01
+#define ATH9K_RXERR_PHY 0x02
+#define ATH9K_RXERR_FIFO 0x04
+#define ATH9K_RXERR_DECRYPT 0x08
+#define ATH9K_RXERR_MIC 0x10
+
+#define ATH9K_RX_MORE 0x01
+#define ATH9K_RX_MORE_AGGR 0x02
+#define ATH9K_RX_GI 0x04
+#define ATH9K_RX_2040 0x08
+#define ATH9K_RX_DELIM_CRC_PRE 0x10
+#define ATH9K_RX_DELIM_CRC_POST 0x20
+#define ATH9K_RX_DECRYPT_BUSY 0x40
+
+#define ATH9K_RXKEYIX_INVALID ((uint8_t)-1)
+#define ATH9K_TXKEYIX_INVALID ((uint32_t)-1)
+
+#pragma pack(1)
+struct ath_desc {
+ uint32_t ds_link;
+ uint32_t ds_data;
+ uint32_t ds_ctl0;
+ uint32_t ds_ctl1;
+ uint32_t ds_hw[20];
+ union {
+ struct ath_tx_status tx;
+ struct ath_rx_status rx;
+ void *stats;
+ } ds_us;
+ void *ds_vdata;
+};
+#pragma pack()
+
+#define ds_txstat ds_us.tx
+#define ds_rxstat ds_us.rx
+#define ds_stat ds_us.stats
+
+#define ATH9K_TXDESC_CLRDMASK 0x0001
+#define ATH9K_TXDESC_NOACK 0x0002
+#define ATH9K_TXDESC_RTSENA 0x0004
+#define ATH9K_TXDESC_CTSENA 0x0008
+/*
+ * ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
+ * the descriptor its marked on. We take a tx interrupt to reap
+ * descriptors when the h/w hits an EOL condition or
+ * when the descriptor is specifically marked to generate
+ * an interrupt with this flag. Descriptors should be
+ * marked periodically to insure timely replenishing of the
+ * supply needed for sending frames. Defering interrupts
+ * reduces system load and potentially allows more concurrent
+ * work to be done but if done to aggressively can cause
+ * senders to backup. When the hardware queue is left too
+ * large rate control information may also be too out of
+ * date. An Alternative for this is TX interrupt mitigation
+ * but this needs more testing.
+ */
+#define ATH9K_TXDESC_INTREQ 0x0010
+#define ATH9K_TXDESC_VEOL 0x0020
+#define ATH9K_TXDESC_EXT_ONLY 0x0040
+#define ATH9K_TXDESC_EXT_AND_CTL 0x0080
+#define ATH9K_TXDESC_VMF 0x0100
+#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
+#define ATH9K_TXDESC_CAB 0x0400
+
+#define ATH9K_RXDESC_INTREQ 0x0020
+
+enum wireless_mode {
+ ATH9K_MODE_11A = 0,
+ ATH9K_MODE_11B = 2,
+ ATH9K_MODE_11G = 3,
+ ATH9K_MODE_11NA_HT20 = 6,
+ ATH9K_MODE_11NG_HT20 = 7,
+ ATH9K_MODE_11NA_HT40PLUS = 8,
+ ATH9K_MODE_11NA_HT40MINUS = 9,
+ ATH9K_MODE_11NG_HT40PLUS = 10,
+ ATH9K_MODE_11NG_HT40MINUS = 11,
+ ATH9K_MODE_MAX
+};
+
+enum ath9k_hw_caps {
+ ATH9K_HW_CAP_CHAN_SPREAD = BIT(0),
+ ATH9K_HW_CAP_MIC_AESCCM = BIT(1),
+ ATH9K_HW_CAP_MIC_CKIP = BIT(2),
+ ATH9K_HW_CAP_MIC_TKIP = BIT(3),
+ ATH9K_HW_CAP_CIPHER_AESCCM = BIT(4),
+ ATH9K_HW_CAP_CIPHER_CKIP = BIT(5),
+ ATH9K_HW_CAP_CIPHER_TKIP = BIT(6),
+ ATH9K_HW_CAP_VEOL = BIT(7),
+ ATH9K_HW_CAP_BSSIDMASK = BIT(8),
+ ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(9),
+ ATH9K_HW_CAP_CHAN_HALFRATE = BIT(10),
+ ATH9K_HW_CAP_CHAN_QUARTERRATE = BIT(11),
+ ATH9K_HW_CAP_HT = BIT(12),
+ ATH9K_HW_CAP_GTT = BIT(13),
+ ATH9K_HW_CAP_FASTCC = BIT(14),
+ ATH9K_HW_CAP_RFSILENT = BIT(15),
+ ATH9K_HW_CAP_WOW = BIT(16),
+ ATH9K_HW_CAP_CST = BIT(17),
+ ATH9K_HW_CAP_ENHANCEDPM = BIT(18),
+ ATH9K_HW_CAP_AUTOSLEEP = BIT(19),
+ ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(20),
+ ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT = BIT(21),
+};
+
+enum ath9k_capability_type {
+ ATH9K_CAP_CIPHER = 0,
+ ATH9K_CAP_TKIP_MIC,
+ ATH9K_CAP_TKIP_SPLIT,
+ ATH9K_CAP_PHYCOUNTERS,
+ ATH9K_CAP_DIVERSITY,
+ ATH9K_CAP_TXPOW,
+ ATH9K_CAP_PHYDIAG,
+ ATH9K_CAP_MCAST_KEYSRCH,
+ ATH9K_CAP_TSF_ADJUST,
+ ATH9K_CAP_WME_TKIPMIC,
+ ATH9K_CAP_RFSILENT,
+ ATH9K_CAP_ANT_CFG_2GHZ,
+ ATH9K_CAP_ANT_CFG_5GHZ
+};
+
+struct ath9k_hw_capabilities {
+ uint32_t hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
+ uint8_t wireless_modes[4]; /* ATH9K_MODE_* */
+ uint16_t total_queues;
+ uint16_t keycache_size;
+ uint16_t low_5ghz_chan, high_5ghz_chan;
+ uint16_t low_2ghz_chan, high_2ghz_chan;
+ uint16_t num_mr_retries;
+ uint16_t rts_aggr_limit;
+ uint8_t tx_chainmask;
+ uint8_t rx_chainmask;
+ uint16_t tx_triglevel_max;
+ uint16_t reg_cap;
+ uint8_t num_gpio_pins;
+ uint8_t num_antcfg_2ghz;
+ uint8_t num_antcfg_5ghz;
+};
+
+struct ath9k_ops_config {
+ int dma_beacon_response_time;
+ int sw_beacon_response_time;
+ int additional_swba_backoff;
+ int ack_6mb;
+ int cwm_ignore_extcca;
+ uint8_t pcie_powersave_enable;
+ uint8_t pcie_l1skp_enable;
+ uint8_t pcie_clock_req;
+ uint32_t pcie_waen;
+ int pcie_power_reset;
+ uint8_t pcie_restore;
+ uint8_t analog_shiftreg;
+ uint8_t ht_enable;
+ uint32_t ofdm_trig_low;
+ uint32_t ofdm_trig_high;
+ uint32_t cck_trig_high;
+ uint32_t cck_trig_low;
+ uint32_t enable_ani;
+ uint8_t noise_immunity_level;
+ uint32_t ofdm_weaksignal_det;
+ uint32_t cck_weaksignal_thr;
+ uint8_t spur_immunity_level;
+ uint8_t firstep_level;
+ int8_t rssi_thr_high;
+ int8_t rssi_thr_low;
+ uint16_t diversity_control;
+ uint16_t antenna_switch_swap;
+ int serialize_regmode;
+ int intr_mitigation;
+#define SPUR_DISABLE 0
+#define SPUR_ENABLE_IOCTL 1
+#define SPUR_ENABLE_EEPROM 2
+#define AR_EEPROM_MODAL_SPURS 5
+#define AR_SPUR_5413_1 1640
+#define AR_SPUR_5413_2 1200
+#define AR_NO_SPUR 0x8000
+#define AR_BASE_FREQ_2GHZ 2300
+#define AR_BASE_FREQ_5GHZ 4900
+#define AR_SPUR_FEEQ_BOUND_HT40 19
+#define AR_SPUR_FEEQ_BOUND_HT20 10
+ int spurmode;
+ uint16_t spurchans[AR_EEPROM_MODAL_SPURS][2];
+};
+
+enum ath9k_tx_queue {
+ ATH9K_TX_QUEUE_INACTIVE = 0,
+ ATH9K_TX_QUEUE_DATA,
+ ATH9K_TX_QUEUE_BEACON,
+ ATH9K_TX_QUEUE_CAB,
+ ATH9K_TX_QUEUE_UAPSD,
+ ATH9K_TX_QUEUE_PSPOLL
+};
+
+#define ATH9K_NUM_TX_QUEUES 10
+
+enum ath9k_tx_queue_subtype {
+ ATH9K_WME_AC_BK = 0,
+ ATH9K_WME_AC_BE,
+ ATH9K_WME_AC_VI,
+ ATH9K_WME_AC_VO,
+ ATH9K_WME_UPSD
+};
+
+enum ath9k_tx_queue_flags {
+ TXQ_FLAG_TXOKINT_ENABLE = 0x0001,
+ TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
+ TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
+ TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
+ TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
+ TXQ_FLAG_BACKOFF_DISABLE = 0x0010,
+ TXQ_FLAG_COMPRESSION_ENABLE = 0x0020,
+ TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040,
+ TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080,
+};
+
+#define ATH9K_TXQ_USEDEFAULT ((uint32_t)(-1))
+
+#define ATH9K_DECOMP_MASK_SIZE 128
+#define ATH9K_READY_TIME_LO_BOUND 50
+#define ATH9K_READY_TIME_HI_BOUND 96
+
+enum ath9k_pkt_type {
+ ATH9K_PKT_TYPE_NORMAL = 0,
+ ATH9K_PKT_TYPE_ATIM,
+ ATH9K_PKT_TYPE_PSPOLL,
+ ATH9K_PKT_TYPE_BEACON,
+ ATH9K_PKT_TYPE_PROBE_RESP,
+ ATH9K_PKT_TYPE_CHIRP,
+ ATH9K_PKT_TYPE_GRP_POLL,
+};
+
+struct ath9k_tx_queue_info {
+ uint32_t tqi_ver;
+ enum ath9k_tx_queue tqi_type;
+ enum ath9k_tx_queue_subtype tqi_subtype;
+ enum ath9k_tx_queue_flags tqi_qflags;
+ uint32_t tqi_priority;
+ uint32_t tqi_aifs;
+ uint32_t tqi_cwmin;
+ uint32_t tqi_cwmax;
+ uint16_t tqi_shretry;
+ uint16_t tqi_lgretry;
+ uint32_t tqi_cbrPeriod;
+ uint32_t tqi_cbrOverflowLimit;
+ uint32_t tqi_burstTime;
+ uint32_t tqi_readyTime;
+ uint32_t tqi_physCompBuf;
+ uint32_t tqi_intFlags;
+};
+
+enum ath9k_rx_filter {
+ ATH9K_RX_FILTER_UCAST = 0x00000001,
+ ATH9K_RX_FILTER_MCAST = 0x00000002,
+ ATH9K_RX_FILTER_BCAST = 0x00000004,
+ ATH9K_RX_FILTER_CONTROL = 0x00000008,
+ ATH9K_RX_FILTER_BEACON = 0x00000010,
+ ATH9K_RX_FILTER_PROM = 0x00000020,
+ ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
+ ATH9K_RX_FILTER_PSPOLL = 0x00004000,
+ ATH9K_RX_FILTER_PHYERR = 0x00000100,
+ ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
+};
+
+enum ath9k_int {
+ ATH9K_INT_RX = 0x00000001,
+ ATH9K_INT_RXDESC = 0x00000002,
+ ATH9K_INT_RXNOFRM = 0x00000008,
+ ATH9K_INT_RXEOL = 0x00000010,
+ ATH9K_INT_RXORN = 0x00000020,
+ ATH9K_INT_TX = 0x00000040,
+ ATH9K_INT_TXDESC = 0x00000080,
+ ATH9K_INT_TIM_TIMER = 0x00000100,
+ ATH9K_INT_TXURN = 0x00000800,
+ ATH9K_INT_MIB = 0x00001000,
+ ATH9K_INT_RXPHY = 0x00004000,
+ ATH9K_INT_RXKCM = 0x00008000,
+ ATH9K_INT_SWBA = 0x00010000,
+ ATH9K_INT_BMISS = 0x00040000,
+ ATH9K_INT_BNR = 0x00100000,
+ ATH9K_INT_TIM = 0x00200000,
+ ATH9K_INT_DTIM = 0x00400000,
+ ATH9K_INT_DTIMSYNC = 0x00800000,
+ ATH9K_INT_GPIO = 0x01000000,
+ ATH9K_INT_CABEND = 0x02000000,
+ ATH9K_INT_CST = 0x10000000,
+ ATH9K_INT_GTT = 0x20000000,
+ ATH9K_INT_FATAL = 0x40000000,
+ ATH9K_INT_GLOBAL = INT_MIN,
+ ATH9K_INT_BMISC = ATH9K_INT_TIM |
+ ATH9K_INT_DTIM |
+ ATH9K_INT_DTIMSYNC |
+ ATH9K_INT_CABEND,
+ ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM |
+ ATH9K_INT_RXDESC |
+ ATH9K_INT_RXEOL |
+ ATH9K_INT_RXORN |
+ ATH9K_INT_TXURN |
+ ATH9K_INT_TXDESC |
+ ATH9K_INT_MIB |
+ ATH9K_INT_RXPHY |
+ ATH9K_INT_RXKCM |
+ ATH9K_INT_SWBA |
+ ATH9K_INT_BMISS |
+ ATH9K_INT_GPIO,
+ ATH9K_INT_NOCARD = -1
+};
+
+#define ATH9K_RATESERIES_RTS_CTS 0x0001
+#define ATH9K_RATESERIES_2040 0x0002
+#define ATH9K_RATESERIES_HALFGI 0x0004
+
+struct ath9k_11n_rate_series {
+ uint32_t Tries;
+ uint32_t Rate;
+ uint32_t PktDuration;
+ uint32_t ChSel;
+ uint32_t RateFlags;
+};
+
+#define CHANNEL_CW_INT 0x00002
+#define CHANNEL_CCK 0x00020
+#define CHANNEL_OFDM 0x00040
+#define CHANNEL_2GHZ 0x00080
+#define CHANNEL_5GHZ 0x00100
+#define CHANNEL_PASSIVE 0x00200
+#define CHANNEL_DYN 0x00400
+#define CHANNEL_HALF 0x04000
+#define CHANNEL_QUARTER 0x08000
+#define CHANNEL_HT20 0x10000
+#define CHANNEL_HT40PLUS 0x20000
+#define CHANNEL_HT40MINUS 0x40000
+
+#define CHANNEL_INTERFERENCE 0x01
+#define CHANNEL_DFS 0x02
+#define CHANNEL_4MS_LIMIT 0x04
+#define CHANNEL_DFS_CLEAR 0x08
+#define CHANNEL_DISALLOW_ADHOC 0x10
+#define CHANNEL_PER_11D_ADHOC 0x20
+
+#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
+#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
+#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
+#define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20)
+#define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20)
+#define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS)
+#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS)
+#define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS)
+#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS)
+#define CHANNEL_ALL \
+ (CHANNEL_OFDM| \
+ CHANNEL_CCK| \
+ CHANNEL_2GHZ | \
+ CHANNEL_5GHZ | \
+ CHANNEL_HT20 | \
+ CHANNEL_HT40PLUS | \
+ CHANNEL_HT40MINUS)
+
+struct ath9k_channel {
+ uint16_t channel;
+ uint32_t channelFlags;
+ uint8_t privFlags;
+ int8_t maxRegTxPower;
+ int8_t maxTxPower;
+ int8_t minTxPower;
+ uint32_t chanmode;
+ int32_t CalValid;
+ boolean_t oneTimeCalsDone;
+ int8_t iCoff;
+ int8_t qCoff;
+ int16_t rawNoiseFloor;
+ int8_t antennaMax;
+ uint32_t regDmnFlags;
+ uint32_t conformanceTestLimit[3]; /* 0:11a, 1: 11b, 2:11g */
+#ifdef ARN_NF_PER_CHAN
+ struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+#endif
+};
+
+#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \
+ (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \
+ (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \
+ (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS))
+#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
+ (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
+ (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
+ (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
+#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
+#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
+#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
+#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0)
+#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
+#define IS_CHAN_QUARTER_RATE(_c) \
+ (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
+
+/* These macros check chanmode and not channelFlags */
+#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
+#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \
+ ((_c)->chanmode == CHANNEL_G_HT20))
+#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \
+ ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \
+ ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \
+ ((_c)->chanmode == CHANNEL_G_HT40MINUS))
+#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
+
+#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990)
+#define IS_CHAN_A_5MHZ_SPACED(_c) \
+ ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \
+ (((_c)->channel % 20) != 0) && \
+ (((_c)->channel % 10) != 0))
+
+struct ath9k_keyval {
+ uint8_t kv_type;
+ uint8_t kv_pad;
+ uint16_t kv_len;
+ uint8_t kv_val[16];
+ uint8_t kv_mic[8];
+ uint8_t kv_txmic[8];
+};
+
+enum ath9k_key_type {
+ ATH9K_KEY_TYPE_CLEAR,
+ ATH9K_KEY_TYPE_WEP,
+ ATH9K_KEY_TYPE_AES,
+ ATH9K_KEY_TYPE_TKIP,
+};
+
+enum ath9k_cipher {
+ ATH9K_CIPHER_WEP = 0,
+ ATH9K_CIPHER_AES_OCB = 1,
+ ATH9K_CIPHER_AES_CCM = 2,
+ ATH9K_CIPHER_CKIP = 3,
+ ATH9K_CIPHER_TKIP = 4,
+ ATH9K_CIPHER_CLR = 5,
+ ATH9K_CIPHER_MIC = 127
+};
+
+#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001
+#define AR_EEPROM_EEPCAP_AES_DIS 0x0002
+#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004
+#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008
+#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0
+#define AR_EEPROM_EEPCAP_MAXQCU_S 4
+#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200
+#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000
+#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12
+
+#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080
+#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100
+#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800
+
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000
+
+#define SD_NO_CTL 0xE0
+#define NO_CTL 0xff
+#define CTL_MODE_M 7
+#define CTL_11A 0
+#define CTL_11B 1
+#define CTL_11G 2
+#define CTL_2GHT20 5
+#define CTL_5GHT20 6
+#define CTL_2GHT40 7
+#define CTL_5GHT40 8
+
+#define AR_EEPROM_MAC(i) (0x1d+(i))
+
+#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 CTRY_DEBUG 0x1ff
+#define CTRY_DEFAULT 0
+
+enum reg_ext_bitmap {
+ REG_EXT_JAPAN_MIDBAND = 1,
+ REG_EXT_FCC_DFS_HT40 = 2,
+ REG_EXT_JAPAN_NONDFS_HT40 = 3,
+ REG_EXT_JAPAN_DFS_HT40 = 4
+};
+
+struct ath9k_country_entry {
+ uint16_t countryCode;
+ uint16_t regDmnEnum;
+ uint16_t regDmn5G;
+ uint16_t regDmn2G;
+ uint8_t isMultidomain;
+ uint8_t iso[3];
+};
+
+/* Register read/write primitives */
+#define REG_WRITE(_ah, _reg, _val) arn_iowrite32((_ah), (_reg), (_val))
+#define REG_READ(_ah, _reg) arn_ioread32((_ah), (_reg))
+#define FLASH_READ(_ah, _reg) \
+ ddi_get16((_ah->ah_sc)->sc_io_handle, \
+ (uint16_t *)((uintptr_t)(_ah)->ah_sh + (_reg)))
+
+#define SM(_v, _f) (((_v) << _f##_S) & _f)
+#define MS(_v, _f) (((_v) & _f) >> _f##_S)
+#define REG_RMW(_a, _r, _set, _clr) \
+ REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set))
+#define REG_RMW_FIELD(_a, _r, _f, _v) \
+ REG_WRITE(_a, _r, \
+ (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f))
+#define REG_SET_BIT(_a, _r, _f) \
+ REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)
+#define REG_CLR_BIT(_a, _r, _f) \
+ REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
+
+#define ATH9K_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
+
+#define WLAN_CTRL_FRAME_SIZE (2+2+6+4)
+
+#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
+#define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX
+
+#define IEEE80211_WEP_IVLEN 3
+#define IEEE80211_WEP_KIDLEN 1
+#define IEEE80211_WEP_CRCLEN 4
+#define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \
+ (IEEE80211_WEP_IVLEN + \
+ IEEE80211_WEP_KIDLEN + \
+ IEEE80211_WEP_CRCLEN))
+#define MAX_RATE_POWER 63
+
+enum ath9k_power_mode {
+ ATH9K_PM_AWAKE = 0,
+ ATH9K_PM_FULL_SLEEP,
+ ATH9K_PM_NETWORK_SLEEP,
+ ATH9K_PM_UNDEFINED
+};
+
+struct ath9k_mib_stats {
+ uint32_t ackrcv_bad;
+ uint32_t rts_bad;
+ uint32_t rts_good;
+ uint32_t fcs_bad;
+ uint32_t beacons;
+};
+
+enum ath9k_ant_setting {
+ ATH9K_ANT_VARIABLE = 0,
+ ATH9K_ANT_FIXED_A,
+ ATH9K_ANT_FIXED_B
+};
+
+
+enum ath9k_opmode {
+ ATH9K_M_STA = 1,
+ ATH9K_M_IBSS = 0,
+ ATH9K_M_HOSTAP = 6,
+ ATH9K_M_MONITOR = 8
+};
+
+
+#define ATH9K_SLOT_TIME_6 6
+#define ATH9K_SLOT_TIME_9 9
+#define ATH9K_SLOT_TIME_20 20
+
+enum ath9k_ht_macmode {
+ ATH9K_HT_MACMODE_20 = 0,
+ ATH9K_HT_MACMODE_2040 = 1,
+};
+
+enum ath9k_ht_extprotspacing {
+ ATH9K_HT_EXTPROTSPACING_20 = 0,
+ ATH9K_HT_EXTPROTSPACING_25 = 1,
+};
+
+struct ath9k_ht_cwm {
+ enum ath9k_ht_macmode ht_macmode;
+ enum ath9k_ht_extprotspacing ht_extprotspacing;
+};
+
+enum ath9k_ani_cmd {
+ ATH9K_ANI_PRESENT = 0x1,
+ ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4,
+ ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8,
+ ATH9K_ANI_FIRSTEP_LEVEL = 0x10,
+ ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20,
+ ATH9K_ANI_MODE = 0x40,
+ ATH9K_ANI_PHYERR_RESET = 0x80,
+ ATH9K_ANI_ALL = 0xff
+};
+
+enum {
+ WLAN_RC_PHY_OFDM,
+ WLAN_RC_PHY_CCK,
+ WLAN_RC_PHY_HT_20_SS,
+ WLAN_RC_PHY_HT_20_DS,
+ WLAN_RC_PHY_HT_40_SS,
+ WLAN_RC_PHY_HT_40_DS,
+ WLAN_RC_PHY_HT_20_SS_HGI,
+ WLAN_RC_PHY_HT_20_DS_HGI,
+ WLAN_RC_PHY_HT_40_SS_HGI,
+ WLAN_RC_PHY_HT_40_DS_HGI,
+ WLAN_RC_PHY_MAX
+};
+
+enum ath9k_tp_scale {
+ ATH9K_TP_SCALE_MAX = 0,
+ ATH9K_TP_SCALE_50,
+ ATH9K_TP_SCALE_25,
+ ATH9K_TP_SCALE_12,
+ ATH9K_TP_SCALE_MIN
+};
+
+enum ser_reg_mode {
+ SER_REG_MODE_OFF = 0,
+ SER_REG_MODE_ON = 1,
+ SER_REG_MODE_AUTO = 2,
+};
+
+#define AR_PHY_CCA_MAX_GOOD_VALUE -85
+#define AR_PHY_CCA_MAX_HIGH_VALUE -62
+#define AR_PHY_CCA_MIN_BAD_VALUE -121
+#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
+#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5
+
+#define ATH9K_NF_CAL_HIST_MAX 5
+#define NUM_NF_READINGS 6
+
+struct ath9k_nfcal_hist {
+ int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX];
+ uint8_t currIndex;
+ int16_t privNF;
+ uint8_t invalidNFcount;
+};
+
+struct ath9k_beacon_state {
+ uint32_t bs_nexttbtt;
+ uint32_t bs_nextdtim;
+ uint32_t bs_intval;
+#define ATH9K_BEACON_PERIOD 0x0000ffff
+#define ATH9K_BEACON_ENA 0x00800000
+#define ATH9K_BEACON_RESET_TSF 0x01000000
+ uint32_t bs_dtimperiod;
+ uint16_t bs_cfpperiod;
+ uint16_t bs_cfpmaxduration;
+ uint32_t bs_cfpnext;
+ uint16_t bs_timoffset;
+ uint16_t bs_bmissthreshold;
+ uint32_t bs_sleepduration;
+};
+
+struct ath9k_node_stats {
+ uint32_t ns_avgbrssi;
+ uint32_t ns_avgrssi;
+ uint32_t ns_avgtxrssi;
+ uint32_t ns_avgtxrate;
+};
+
+#define ATH9K_RSSI_EP_MULTIPLIER (1<<7)
+
+#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
+
+enum {
+ ATH9K_RESET_POWER_ON,
+ ATH9K_RESET_WARM,
+ ATH9K_RESET_COLD,
+};
+
+#define AH_USE_EEPROM 0x1
+
+struct ath_hal {
+ uint32_t ah_magic;
+ uint16_t ah_devid;
+ uint16_t ah_subvendorid;
+ uint32_t ah_macVersion;
+ uint16_t ah_macRev;
+ uint16_t ah_phyRev;
+ uint16_t ah_analog5GhzRev;
+ uint16_t ah_analog2GhzRev;
+
+ caddr_t ah_sh;
+ struct arn_softc *ah_sc;
+ enum ath9k_opmode ah_opmode;
+ struct ath9k_ops_config ah_config;
+ struct ath9k_hw_capabilities ah_caps;
+
+ uint16_t ah_countryCode;
+ uint32_t ah_flags;
+ int16_t ah_powerLimit;
+ uint16_t ah_maxPowerLevel;
+ uint32_t ah_tpScale;
+ uint16_t ah_currentRD;
+ uint16_t ah_currentRDExt;
+ uint16_t ah_currentRDInUse;
+ uint16_t ah_currentRD5G;
+ uint16_t ah_currentRD2G;
+ char ah_iso[4];
+
+ struct ath9k_channel ah_channels[150];
+ struct ath9k_channel *ah_curchan;
+ uint32_t ah_nchan;
+
+ boolean_t ah_isPciExpress;
+ uint16_t ah_txTrigLevel;
+ uint16_t ah_rfsilent;
+ uint32_t ah_rfkill_gpio;
+ uint32_t ah_rfkill_polarity;
+
+#ifndef ARN_NF_PER_CHAN
+ struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+#endif
+};
+
+struct chan_centers {
+ uint16_t synth_center;
+ uint16_t ctl_center;
+ uint16_t ext_center;
+};
+
+struct ath_rate_table;
+
+/* Helpers */
+
+enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
+ const struct ath9k_channel *chan);
+boolean_t ath9k_hw_wait(struct ath_hal *ah, uint32_t reg, uint32_t mask,
+ uint32_t val);
+uint32_t ath9k_hw_reverse_bits(uint32_t val, uint32_t n);
+boolean_t ath9k_get_channel_edges(struct ath_hal *ah,
+ uint16_t flags, uint16_t *low, uint16_t *high);
+uint16_t ath9k_hw_computetxtime(struct ath_hal *ah,
+ struct ath_rate_table *rates,
+ uint32_t frameLen, uint16_t rateix,
+ boolean_t shortPreamble);
+uint32_t ath9k_hw_mhz2ieee(struct ath_hal *ah, uint32_t freq, uint32_t flags);
+void ath9k_hw_get_channel_centers(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct chan_centers *centers);
+
+/* Attach, Detach */
+
+const char *ath9k_hw_probe(uint16_t vendorid, uint16_t devid);
+void ath9k_hw_detach(struct ath_hal *ah);
+struct ath_hal *ath9k_hw_attach(uint16_t devid, struct arn_softc *sc,
+ caddr_t mem, int *error);
+void ath9k_hw_rfdetach(struct ath_hal *ah);
+
+
+/* HW Reset */
+
+boolean_t ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode,
+ uint8_t txchainmask, uint8_t rxchainmask,
+ enum ath9k_ht_extprotspacing extprotspacing,
+ boolean_t bChannelChange, int *status);
+
+/* Key Cache Management */
+
+boolean_t ath9k_hw_keyreset(struct ath_hal *ah, uint16_t entry);
+boolean_t ath9k_hw_keysetmac(struct ath_hal *ah, uint16_t entry,
+ const uint8_t *mac);
+boolean_t ath9k_hw_set_keycache_entry(struct ath_hal *ah, uint16_t entry,
+ const struct ath9k_keyval *k, const uint8_t *mac, int xorKey);
+boolean_t ath9k_hw_keyisvalid(struct ath_hal *ah, uint16_t entry);
+
+/* Power Management */
+
+boolean_t ath9k_hw_setpower(struct ath_hal *ah,
+ enum ath9k_power_mode mode);
+void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
+
+/* Beacon timers */
+
+void ath9k_hw_beaconinit(struct ath_hal *ah, uint32_t next_beacon,
+ uint32_t beacon_period);
+void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
+ const struct ath9k_beacon_state *bs);
+/* HW Capabilities */
+
+boolean_t ath9k_hw_fill_cap_info(struct ath_hal *ah);
+boolean_t ath9k_hw_getcapability(struct ath_hal *ah,
+ enum ath9k_capability_type type,
+ uint32_t capability, uint32_t *result);
+boolean_t ath9k_hw_setcapability(struct ath_hal *ah,
+ enum ath9k_capability_type type,
+ uint32_t capability, uint32_t setting,
+ int *status);
+
+/* GPIO / RFKILL / Antennae */
+
+void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, uint32_t gpio);
+uint32_t ath9k_hw_gpio_get(struct ath_hal *ah, uint32_t gpio);
+void ath9k_hw_cfg_output(struct ath_hal *ah, uint32_t gpio,
+ uint32_t ah_signal_type);
+void ath9k_hw_set_gpio(struct ath_hal *ah, uint32_t gpio, uint32_t val);
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+void ath9k_enable_rfkill(struct ath_hal *ah);
+#endif
+int ath9k_hw_select_antconfig(struct ath_hal *ah, uint32_t cfg);
+uint32_t ath9k_hw_getdefantenna(struct ath_hal *ah);
+void ath9k_hw_setantenna(struct ath_hal *ah, uint32_t antenna);
+boolean_t ath9k_hw_setantennaswitch(struct ath_hal *ah,
+ enum ath9k_ant_setting settings,
+ struct ath9k_channel *chan,
+ uint8_t *tx_chainmask,
+ uint8_t *rx_chainmask,
+ uint8_t *antenna_cfgd);
+
+/* General Operation */
+
+uint32_t ath9k_hw_getrxfilter(struct ath_hal *ah);
+void ath9k_hw_setrxfilter(struct ath_hal *ah, uint32_t bits);
+boolean_t ath9k_hw_phy_disable(struct ath_hal *ah);
+boolean_t ath9k_hw_disable(struct ath_hal *ah);
+boolean_t ath9k_hw_set_txpowerlimit(struct ath_hal *ah, uint32_t limit);
+void ath9k_hw_getmac(struct ath_hal *ah, uint8_t *mac);
+boolean_t ath9k_hw_setmac(struct ath_hal *ah, const uint8_t *mac);
+void ath9k_hw_setopmode(struct ath_hal *ah);
+void ath9k_hw_setmcastfilter(struct ath_hal *ah, uint32_t filter0,
+ uint32_t filter1);
+void ath9k_hw_getbssidmask(struct ath_hal *ah, uint8_t *mask);
+boolean_t ath9k_hw_setbssidmask(struct ath_hal *ah, const uint8_t *mask);
+void ath9k_hw_write_associd(struct ath_hal *ah, const uint8_t *bssid,
+ uint16_t assocId);
+uint64_t ath9k_hw_gettsf64(struct ath_hal *ah);
+void ath9k_hw_reset_tsf(struct ath_hal *ah);
+boolean_t ath9k_hw_set_tsfadjust(struct ath_hal *ah, uint32_t setting);
+boolean_t ath9k_hw_setslottime(struct ath_hal *ah, uint32_t us);
+void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
+
+/* Regulatory */
+
+boolean_t ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
+struct ath9k_channel *ath9k_regd_check_channel(struct ath_hal *ah,
+ const struct ath9k_channel *c);
+uint32_t ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
+uint32_t ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+boolean_t ath9k_regd_init_channels(struct ath_hal *ah,
+ uint32_t maxchans, uint32_t *nchans, uint8_t *regclassids,
+ uint32_t maxregids, uint32_t *nregids, uint16_t cc,
+ boolean_t enableOutdoor, boolean_t enableExtendedChannels);
+
+/* ANI */
+
+void ath9k_ani_reset(struct ath_hal *ah);
+void ath9k_hw_ani_monitor(struct ath_hal *ah,
+ const struct ath9k_node_stats *stats,
+ struct ath9k_channel *chan);
+boolean_t ath9k_hw_phycounters(struct ath_hal *ah);
+void ath9k_enable_mib_counters(struct ath_hal *ah);
+void ath9k_hw_disable_mib_counters(struct ath_hal *ah);
+uint32_t ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
+ uint32_t *rxc_pcnt,
+ uint32_t *rxf_pcnt,
+ uint32_t *txf_pcnt);
+void ath9k_hw_procmibevent(struct ath_hal *ah,
+ const struct ath9k_node_stats *stats);
+void ath9k_hw_ani_setup(struct ath_hal *ah);
+void ath9k_hw_ani_attach(struct ath_hal *ah);
+void ath9k_hw_ani_detach(struct ath_hal *ah);
+
+/* Calibration */
+
+void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
+ boolean_t *isCalDone);
+void ath9k_hw_start_nfcal(struct ath_hal *ah);
+void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan);
+int16_t ath9k_hw_getnf(struct ath_hal *ah, struct ath9k_channel *chan);
+void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah);
+signed short ath9k_hw_getchan_noise(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+boolean_t ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
+ uint8_t rxchainmask, boolean_t longcal, boolean_t *isCalDone);
+boolean_t ath9k_hw_init_cal(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+
+
+/* EEPROM */
+
+int ath9k_hw_set_txpower(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ uint16_t cfgCtl,
+ uint8_t twiceAntennaReduction,
+ uint8_t twiceMaxRegulatoryPower,
+ uint8_t powerLimit);
+void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan);
+boolean_t ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ uint16_t cfgCtl,
+ uint8_t AntennaReduction,
+ uint8_t twiceMaxRegulatoryPower,
+ uint8_t powerLimit);
+boolean_t ath9k_hw_set_power_cal_table(struct ath_hal *ah,
+ struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset);
+boolean_t ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
+ struct ath9k_channel *chan, uint8_t index, uint16_t *config);
+
+uint8_t ath9k_hw_get_num_ant_config(struct ath_hal *ah,
+ enum ath9k_band freq_band);
+
+uint16_t ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, uint16_t i,
+ boolean_t is2GHz);
+int ath9k_hw_eeprom_attach(struct ath_hal *ah);
+
+/* Interrupt Handling */
+
+boolean_t ath9k_hw_intrpend(struct ath_hal *ah);
+boolean_t ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
+enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
+enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints);
+
+/* MAC (PCU/QCU) */
+
+void ath9k_hw_dmaRegDump(struct ath_hal *ah);
+uint32_t ath9k_hw_gettxbuf(struct ath_hal *ah, uint32_t q);
+boolean_t ath9k_hw_puttxbuf(struct ath_hal *ah, uint32_t q, uint32_t txdp);
+boolean_t ath9k_hw_txstart(struct ath_hal *ah, uint32_t q);
+uint32_t ath9k_hw_numtxpending(struct ath_hal *ah, uint32_t q);
+boolean_t ath9k_hw_updatetxtriglevel(struct ath_hal *ah,
+ boolean_t bIncTrigLevel);
+boolean_t ath9k_hw_stoptxdma(struct ath_hal *ah, uint32_t q);
+boolean_t ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t segLen, boolean_t firstSeg,
+ boolean_t lastSeg, const struct ath_desc *ds0);
+void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
+int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t pktLen, enum ath9k_pkt_type type, uint32_t txPower,
+ uint32_t keyIx, enum ath9k_key_type keyType, uint32_t flags);
+void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
+ struct ath_desc *lastds,
+ uint32_t durUpdateEn, uint32_t rtsctsRate,
+ uint32_t rtsctsDuration,
+ struct ath9k_11n_rate_series series[],
+ uint32_t nseries, uint32_t flags);
+void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t aggrLen);
+void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t numDelims);
+void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t burstDuration);
+void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t vmf);
+void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, uint32_t *txqs);
+boolean_t ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
+ const struct ath9k_tx_queue_info *qinfo);
+boolean_t ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
+ struct ath9k_tx_queue_info *qinfo);
+int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
+ const struct ath9k_tx_queue_info *qinfo);
+boolean_t ath9k_hw_releasetxqueue(struct ath_hal *ah, uint32_t q);
+boolean_t ath9k_hw_resettxqueue(struct ath_hal *ah, uint32_t q);
+int ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t pa, struct ath_desc *nds, uint64_t tsf);
+boolean_t ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t size, uint32_t flags);
+boolean_t ath9k_hw_setrxabort(struct ath_hal *ah, boolean_t set);
+void ath9k_hw_putrxbuf(struct ath_hal *ah, uint32_t rxdp);
+void ath9k_hw_rxena(struct ath_hal *ah);
+void ath9k_hw_startpcureceive(struct ath_hal *ah);
+void ath9k_hw_stoppcurecv(struct ath_hal *ah);
+boolean_t ath9k_hw_stopdmarecv(struct ath_hal *ah);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARN_ATH9K_H */
diff --git a/usr/src/uts/common/io/arn/arn_beacon.c b/usr/src/uts/common/io/arn/arn_beacon.c
new file mode 100644
index 0000000000..3ba0ec4241
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_beacon.c
@@ -0,0 +1,515 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/strsun.h>
+#include <inet/common.h>
+#include <inet/nd.h>
+#include <inet/mi.h>
+#include <inet/wifi_ioctl.h>
+
+#include "arn_core.h"
+
+/*
+ * This function will modify certain transmit queue properties depending on
+ * the operating mode of the station (AP or AdHoc). Parameters are AIFS
+ * settings and channel width min/max
+ */
+static int
+arn_beaconq_config(struct arn_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath9k_tx_queue_info qi;
+
+ (void) ath9k_hw_get_txq_props(ah, sc->sc_beaconq, &qi);
+ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
+ /* Always burst out beacon and CAB traffic. */
+ qi.tqi_aifs = 1;
+ qi.tqi_cwmin = 0;
+ qi.tqi_cwmax = 0;
+ } else {
+ /* Adhoc mode; important thing is to use 2x cwmin. */
+ qi.tqi_aifs = sc->sc_beacon_qi.tqi_aifs;
+ qi.tqi_cwmin = 2*sc->sc_beacon_qi.tqi_cwmin;
+ qi.tqi_cwmax = sc->sc_beacon_qi.tqi_cwmax;
+ }
+
+ if (!ath9k_hw_set_txq_props(ah, sc->sc_beaconq, &qi)) {
+ arn_problem("unable to update h/w beacon queue parameters\n");
+ return (0);
+ } else {
+ /* push to h/w */
+ (void) ath9k_hw_resettxqueue(ah, sc->sc_beaconq);
+ return (1);
+ }
+}
+
+/*
+ * Associates the beacon frame buffer with a transmit descriptor. Will set
+ * up all required antenna switch parameters, rate codes, and channel flags.
+ * Beacons are always sent out at the lowest rate, and are not retried.
+ */
+
+static void
+arn_beacon_setup(struct arn_softc *sc, struct ath_buf *bf)
+{
+#define USE_SHPREAMBLE(_ic) \
+ (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
+ == IEEE80211_F_SHPREAMBLE)
+ mblk_t *mp = bf->bf_m;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_desc *ds;
+ /* LINTED E_FUNC_SET_NOT_USED */
+ int flags, antenna = 0;
+ struct ath_rate_table *rt;
+ uint8_t rix, rate;
+ struct ath9k_11n_rate_series series[4];
+ int ctsrate = 0;
+ int ctsduration = 0;
+
+ /* set up descriptors */
+ ds = bf->bf_desc;
+
+ flags = ATH9K_TXDESC_NOACK;
+ if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
+ (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
+ ds->ds_link = bf->bf_daddr; /* self-linked */
+ flags |= ATH9K_TXDESC_VEOL;
+ /*
+ * Let hardware handle antenna switching.
+ */
+ antenna = 0;
+ } else {
+ ds->ds_link = 0;
+ /*
+ * Switch antenna every 4 beacons.
+ * NB: assumes two antenna
+ */
+ antenna = ((sc->ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1);
+ }
+
+ ds->ds_data = bf->bf_dma.cookie.dmac_address;
+ /*
+ * Calculate rate code.
+ * XXX everything at min xmit rate
+ */
+ rix = 0;
+ rt = sc->hw_rate_table[sc->sc_curmode];
+ rate = rt->info[rix].ratecode;
+ if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+ rate |= rt->info[rix].short_preamble;
+
+ ath9k_hw_set11n_txdesc(ah, ds,
+ MBLKL(mp) + IEEE80211_CRC_LEN, /* frame length */
+ ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
+ MAX_RATE_POWER, /* FIXME */
+ ATH9K_TXKEYIX_INVALID, /* no encryption */
+ ATH9K_KEY_TYPE_CLEAR, /* no encryption */
+ flags); /* no ack, veol for beacons */
+
+ /* NB: beacon's BufLen must be a multiple of 4 bytes */
+ (void) ath9k_hw_filltxdesc(ah, ds,
+ roundup(MBLKL(mp), 4), /* buffer length */
+ B_TRUE, /* first segment */
+ B_TRUE, /* last segment */
+ ds); /* first descriptor */
+
+ (void) memset(series, 0, sizeof (struct ath9k_11n_rate_series) * 4);
+ series[0].Tries = 1;
+ series[0].Rate = rate;
+ series[0].ChSel = sc->sc_tx_chainmask;
+ series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
+ ath9k_hw_set11n_ratescenario(ah, ds, ds, 0,
+ ctsrate, ctsduration, series, 4, 0);
+#undef USE_SHPREAMBLE
+}
+
+/*
+ * Startup beacon transmission for adhoc mode when they are sent entirely
+ * by the hardware using the self-linked descriptor + veol trick.
+ */
+static void
+arn_beacon_start_adhoc(struct arn_softc *sc)
+
+{
+ struct ath_buf *bf = list_head(&sc->sc_bcbuf_list);
+ struct ieee80211_node *in = bf->bf_in;
+ struct ieee80211com *ic = in->in_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ mblk_t *mp;
+
+ mp = bf->bf_m;
+ if (ieee80211_beacon_update(ic, bf->bf_in, &sc->asc_boff, mp, 0))
+ bcopy(mp->b_rptr, bf->bf_dma.mem_va, MBLKL(mp));
+
+ /* Construct tx descriptor. */
+ arn_beacon_setup(sc, bf);
+
+ /*
+ * Stop any current dma and put the new frame on the queue.
+ * This should never fail since we check above that no frames
+ * are still pending on the queue.
+ */
+ if (!ath9k_hw_stoptxdma(ah, sc->sc_beaconq)) {
+ arn_problem("ath: beacon queue %d did not stop?\n",
+ sc->sc_beaconq);
+ }
+ ARN_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV);
+
+ /* NB: caller is known to have already stopped tx dma */
+ (void) ath9k_hw_puttxbuf(ah, sc->sc_beaconq, bf->bf_daddr);
+ (void) ath9k_hw_txstart(ah, sc->sc_beaconq);
+
+ ARN_DBG((ARN_DBG_BEACON, "arn: arn_bstuck_process(): "
+ "TXDP%u = %llx (%p)\n", sc->sc_beaconq,
+ ito64(bf->bf_daddr), bf->bf_desc));
+}
+
+uint32_t
+arn_beaconq_setup(struct ath_hal *ah)
+{
+ struct ath9k_tx_queue_info qi;
+
+ (void) memset(&qi, 0, sizeof (qi));
+ qi.tqi_aifs = 1;
+ qi.tqi_cwmin = 0;
+ qi.tqi_cwmax = 0;
+ /* NB: don't enable any interrupts */
+ return (ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi));
+}
+
+int
+arn_beacon_alloc(struct arn_softc *sc, struct ieee80211_node *in)
+{
+ ieee80211com_t *ic = in->in_ic;
+ struct ath_buf *bf;
+ mblk_t *mp;
+
+ mutex_enter(&sc->sc_bcbuflock);
+ bf = list_head(&sc->sc_bcbuf_list);
+ if (bf == NULL) {
+ arn_problem("arn: arn_beacon_alloc():"
+ "no dma buffers");
+ mutex_exit(&sc->sc_bcbuflock);
+ return (ENOMEM);
+ }
+
+ mp = ieee80211_beacon_alloc(ic, in, &sc->asc_boff);
+ if (mp == NULL) {
+ arn_problem("ath: arn_beacon_alloc():"
+ "cannot get mbuf\n");
+ mutex_exit(&sc->sc_bcbuflock);
+ return (ENOMEM);
+ }
+ ASSERT(mp->b_cont == NULL);
+ bf->bf_m = mp;
+ bcopy(mp->b_rptr, bf->bf_dma.mem_va, MBLKL(mp));
+ bf->bf_in = ieee80211_ref_node(in);
+ mutex_exit(&sc->sc_bcbuflock);
+
+ return (0);
+}
+
+
+void
+arn_beacon_return(struct arn_softc *sc)
+{
+ struct ath_buf *bf;
+
+ mutex_enter(&sc->sc_bcbuflock);
+ bf = list_head(&sc->sc_bcbuf_list);
+ while (bf != NULL) {
+ if (bf->bf_m != NULL) {
+ freemsg(bf->bf_m);
+ bf->bf_m = NULL;
+ }
+ if (bf->bf_in != NULL) {
+ ieee80211_free_node(bf->bf_in);
+ bf->bf_in = NULL;
+ }
+ bf = list_next(&sc->sc_bcbuf_list, bf);
+ }
+ mutex_exit(&sc->sc_bcbuflock);
+}
+
+void
+arn_beacon_config(struct arn_softc *sc)
+
+{
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_beacon_config conf;
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ieee80211_node *in = ic->ic_bss;
+ uint32_t nexttbtt, intval;
+
+ (void) memset(&conf, 0, sizeof (struct ath_beacon_config));
+
+ /* XXX fix me */
+ conf.beacon_interval = in->in_intval ?
+ in->in_intval : ATH_DEFAULT_BINTVAL;
+ conf.listen_interval = 1;
+ conf.dtim_period = conf.beacon_interval;
+ conf.dtim_count = 1;
+ conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
+
+ /* extract tstamp from last beacon and convert to TU */
+ // nexttbtt = TSF_TO_TU(sc->bc_tstamp >> 32, sc->bc_tstamp);
+ /* XXX fix me */
+ nexttbtt = (ARN_LE_READ_32(in->in_tstamp.data + 4) << 22) |
+ (ARN_LE_READ_32(in->in_tstamp.data) >> 10);
+
+ /* XXX conditionalize multi-bss support? */
+ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
+ /*
+ * For multi-bss ap support beacons are either staggered
+ * evenly over N slots or burst together. For the former
+ * arrange for the SWBA to be delivered for each slot.
+ * Slots that are not occupied will generate nothing.
+ */
+ /* NB: the beacon interval is kept internally in TU's */
+ intval = conf.beacon_interval & ATH9K_BEACON_PERIOD;
+ intval /= ATH_BCBUF; /* for staggered beacons */
+ } else {
+ intval = conf.beacon_interval & ATH9K_BEACON_PERIOD;
+ }
+
+ if (nexttbtt == 0) /* e.g. for ap mode */
+ nexttbtt = intval;
+ else if (intval) /* NB: can be 0 for monitor mode */
+ nexttbtt = roundup(nexttbtt, intval);
+
+ ARN_DBG((ARN_DBG_BEACON, "arn: arn_beacon_config(): "
+ "nexttbtt %u intval %u (%u)\n",
+ nexttbtt, intval, conf.beacon_interval));
+
+ /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */
+ if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
+ struct ath9k_beacon_state bs;
+ uint64_t tsf;
+ uint32_t tsftu;
+ int dtimperiod, dtimcount, sleepduration;
+ int cfpperiod, cfpcount;
+
+ /*
+ * Setup dtim and cfp parameters according to
+ * last beacon we received (which may be none).
+ */
+ dtimperiod = conf.dtim_period;
+ if (dtimperiod <= 0) /* NB: 0 if not known */
+ dtimperiod = 1;
+ dtimcount = conf.dtim_count;
+ if (dtimcount >= dtimperiod) /* NB: sanity check */
+ dtimcount = 0;
+ cfpperiod = 1; /* NB: no PCF support yet */
+ cfpcount = 0;
+
+ sleepduration = conf.listen_interval * intval;
+ if (sleepduration <= 0)
+ sleepduration = intval;
+
+#define FUDGE 2
+ /*
+ * Pull nexttbtt forward to reflect the current
+ * TSF and calculate dtim+cfp state for the result.
+ */
+ tsf = ath9k_hw_gettsf64(ah);
+ tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
+ do {
+ nexttbtt += intval;
+ if (--dtimcount < 0) {
+ dtimcount = dtimperiod - 1;
+ if (--cfpcount < 0)
+ cfpcount = cfpperiod - 1;
+ }
+ } while (nexttbtt < tsftu);
+#undef FUDGE
+ (void) memset(&bs, 0, sizeof (bs));
+ bs.bs_intval = intval;
+ bs.bs_nexttbtt = nexttbtt;
+ bs.bs_dtimperiod = dtimperiod*intval;
+ bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
+ bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
+ bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
+ bs.bs_cfpmaxduration = 0;
+
+ /*
+ * Calculate the number of consecutive beacons to miss
+ * before taking a BMISS interrupt. The configuration
+ * is specified in TU so we only need calculate based
+ * on the beacon interval. Note that we clamp the
+ * result to at most 15 beacons.
+ */
+ if (sleepduration > intval) {
+ bs.bs_bmissthreshold = conf.listen_interval *
+ ATH_DEFAULT_BMISS_LIMIT / 2;
+ } else {
+ bs.bs_bmissthreshold =
+ DIV_ROUND_UP(conf.bmiss_timeout, intval);
+ if (bs.bs_bmissthreshold > 15)
+ bs.bs_bmissthreshold = 15;
+ /* LINTED E_SUSPICIOUS_COMPARISON */
+ else if (bs.bs_bmissthreshold <= 0)
+ bs.bs_bmissthreshold = 1;
+ }
+
+ /*
+ * Calculate sleep duration. The configuration is
+ * given in ms. We insure a multiple of the beacon
+ * period is used. Also, if the sleep duration is
+ * greater than the DTIM period then it makes senses
+ * to make it a multiple of that.
+ *
+ * XXX fixed at 100ms
+ */
+
+ bs.bs_sleepduration =
+ roundup(IEEE80211_MS_TO_TU(100), sleepduration);
+ if (bs.bs_sleepduration > bs.bs_dtimperiod)
+ bs.bs_sleepduration = bs.bs_dtimperiod;
+
+ ARN_DBG((ARN_DBG_BEACON, "arn: arn_beacon_config(): "
+ "tsf %llu "
+ "tsf:tu %u "
+ "intval %u "
+ "nexttbtt %u "
+ "dtim %u "
+ "nextdtim %u "
+ "bmiss %u "
+ "sleep %u "
+ "cfp:period %u "
+ "maxdur %u "
+ "next %u "
+ "timoffset %u\n",
+ (unsigned long long)tsf, tsftu,
+ bs.bs_intval,
+ bs.bs_nexttbtt,
+ bs.bs_dtimperiod,
+ bs.bs_nextdtim,
+ bs.bs_bmissthreshold,
+ bs.bs_sleepduration,
+ bs.bs_cfpperiod,
+ bs.bs_cfpmaxduration,
+ bs.bs_cfpnext,
+ bs.bs_timoffset));
+
+ (void) ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_set_sta_beacon_timers(ah, &bs);
+ sc->sc_imask |= ATH9K_INT_BMISS;
+ (void) ath9k_hw_set_interrupts(ah, sc->sc_imask);
+ } else {
+ uint64_t tsf;
+ uint32_t tsftu;
+ (void) ath9k_hw_set_interrupts(ah, 0);
+ if (nexttbtt == intval)
+ intval |= ATH9K_BEACON_RESET_TSF;
+ if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
+ /*
+ * Pull nexttbtt forward to reflect the current
+ * TSF
+ */
+#define FUDGE 2
+ if (!(intval & ATH9K_BEACON_RESET_TSF)) {
+ tsf = ath9k_hw_gettsf64(ah);
+ tsftu = TSF_TO_TU((uint32_t)(tsf>>32),
+ (uint32_t)tsf) + FUDGE;
+ do {
+ nexttbtt += intval;
+ } while (nexttbtt < tsftu);
+ }
+#undef FUDGE
+ ARN_DBG((ARN_DBG_BEACON, "arn: arn_beacon_config(): "
+ "IBSS nexttbtt %u intval %u (%u)\n",
+ nexttbtt, intval & ~ATH9K_BEACON_RESET_TSF,
+ conf.beacon_interval));
+
+ /*
+ * In IBSS mode enable the beacon timers but only
+ * enable SWBA interrupts if we need to manually
+ * prepare beacon frames. Otherwise we use a
+ * self-linked tx descriptor and let the hardware
+ * deal with things.
+ */
+ intval |= ATH9K_BEACON_ENA;
+ if (!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL))
+ sc->sc_imask |= ATH9K_INT_SWBA;
+ (void) arn_beaconq_config(sc);
+ } else if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
+ /*
+ * In AP mode we enable the beacon timers and
+ * SWBA interrupts to prepare beacon frames.
+ */
+ intval |= ATH9K_BEACON_ENA;
+ sc->sc_imask |= ATH9K_INT_SWBA; /* beacon prepare */
+ (void) arn_beaconq_config(sc);
+ }
+ ath9k_hw_beaconinit(ah, nexttbtt, intval);
+ sc->sc_bmisscount = 0;
+ (void) ath9k_hw_set_interrupts(ah, sc->sc_imask);
+ /*
+ * When using a self-linked beacon descriptor in
+ * ibss mode load it once here.
+ */
+ if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
+ (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL))
+ arn_beacon_start_adhoc(sc);
+ }
+ sc->sc_bsync = 0;
+}
+
+void
+ath_beacon_sync(struct arn_softc *sc)
+{
+ /*
+ * Resync beacon timers using the tsf of the
+ * beacon frame we just received.
+ */
+ arn_beacon_config(sc);
+ sc->sc_flags |= SC_OP_BEACONS;
+}
+
+void
+arn_bmiss_proc(void *arg)
+{
+ struct arn_softc *sc = (struct arn_softc *)arg;
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ uint64_t tsf, lastrx;
+ uint_t bmisstimeout;
+
+ if (ic->ic_opmode != IEEE80211_M_STA ||
+ ic->ic_state != IEEE80211_S_RUN) {
+ return;
+ }
+
+ ARN_LOCK(sc);
+ lastrx = sc->sc_lastrx;
+ tsf = ath9k_hw_gettsf64(sc->sc_ah);
+ bmisstimeout = ic->ic_bmissthreshold * ic->ic_bss->in_intval * 1024;
+
+ ARN_DBG((ARN_DBG_BEACON, "arn_bmiss_proc():"
+ " tsf %llu, lastrx %llu (%lld), bmiss %u\n",
+ (unsigned long long)tsf, (unsigned long long)sc->sc_lastrx,
+ (long long)(tsf - lastrx), bmisstimeout));
+ ARN_UNLOCK(sc);
+
+ /* temp workaround */
+ if (tsf - lastrx > bmisstimeout)
+ ieee80211_beacon_miss(ic);
+}
diff --git a/usr/src/uts/common/io/arn/arn_calib.c b/usr/src/uts/common/io/arn/arn_calib.c
new file mode 100644
index 0000000000..14097c791b
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_calib.c
@@ -0,0 +1,1069 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include "arn_core.h"
+#include "arn_hw.h"
+#include "arn_reg.h"
+#include "arn_phy.h"
+
+static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
+
+/* We can tune this as we go by monitoring really low values */
+#define ATH9K_NF_TOO_LOW -60
+
+/*
+ * AR5416 may return very high value (like -31 dBm), in those cases the nf
+ * is incorrect and we should use the static NF value. Later we can try to
+ * find out why they are reporting these values
+ */
+
+/* ARGSUSED */
+static boolean_t
+ath9k_hw_nf_in_range(struct ath_hal *ah, signed short nf)
+{
+ if (nf > ATH9K_NF_TOO_LOW) {
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: noise floor value detected (%d) is "
+ "lower than what we think is a "
+ "reasonable value (%d)\n",
+ __func__, nf, ATH9K_NF_TOO_LOW));
+
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
+static int16_t
+ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
+{
+ int16_t nfval;
+ int16_t sort[ATH9K_NF_CAL_HIST_MAX];
+ int i, j;
+
+ for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
+ sort[i] = nfCalBuffer[i];
+
+ for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
+ for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
+ if (sort[j] > sort[j - 1]) {
+ nfval = sort[j];
+ sort[j] = sort[j - 1];
+ sort[j - 1] = nfval;
+ }
+ }
+ }
+ nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
+
+ return (nfval);
+}
+
+static void
+ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
+ int16_t *nfarray)
+{
+ int i;
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+ if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
+ h[i].currIndex = 0;
+
+ if (h[i].invalidNFcount > 0) {
+ if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
+ nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
+ h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
+ } else {
+ h[i].invalidNFcount--;
+ h[i].privNF = nfarray[i];
+ }
+ } else {
+ h[i].privNF =
+ ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
+ }
+ }
+}
+
+static void
+ath9k_hw_do_getnf(struct ath_hal *ah,
+ int16_t nfarray[NUM_NF_READINGS])
+{
+ int16_t nf;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
+ else
+ nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
+
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "NF calibrated [ctl] [chain 0] is %d\n", nf));
+ nfarray[0] = nf;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
+ AR9280_PHY_CH1_MINCCA_PWR);
+ else
+ nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
+ AR_PHY_CH1_MINCCA_PWR);
+
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "NF calibrated [ctl] [chain 1] is %d\n", nf));
+ nfarray[1] = nf;
+
+ if (!AR_SREV_9280(ah)) {
+ nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
+ AR_PHY_CH2_MINCCA_PWR);
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "NF calibrated [ctl] [chain 2] is %d\n", nf));
+ nfarray[2] = nf;
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
+ AR9280_PHY_EXT_MINCCA_PWR);
+ else
+ nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
+ AR_PHY_EXT_MINCCA_PWR);
+
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "NF calibrated [ext] [chain 0] is %d\n", nf));
+ nfarray[3] = nf;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
+ AR9280_PHY_CH1_EXT_MINCCA_PWR);
+ else
+ nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
+ AR_PHY_CH1_EXT_MINCCA_PWR);
+
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "NF calibrated [ext] [chain 1] is %d\n", nf));
+ nfarray[4] = nf;
+
+ if (!AR_SREV_9280(ah)) {
+ nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
+ AR_PHY_CH2_EXT_MINCCA_PWR);
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "NF calibrated [ext] [chain 2] is %d\n", nf));
+ nfarray[5] = nf;
+ }
+}
+
+static boolean_t
+getNoiseFloorThresh(struct ath_hal *ah,
+ const struct ath9k_channel *chan,
+ int16_t *nft)
+{
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
+ break;
+ case CHANNEL_B:
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
+ break;
+ default:
+ ARN_DBG((ARN_DBG_CHANNEL,
+ "%s: invalid channel flags 0x%x\n", __func__,
+ chan->channelFlags));
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+static void
+ath9k_hw_setup_calibration(struct ath_hal *ah,
+ struct hal_cal_list *currCal)
+{
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+ currCal->calData->calCountMax);
+
+ switch (currCal->calData->calType) {
+ case IQ_MISMATCH_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: starting IQ Mismatch Calibration\n",
+ __func__));
+ break;
+ case ADC_GAIN_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: starting ADC Gain Calibration\n", __func__));
+ break;
+ case ADC_DC_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: starting ADC DC Calibration\n", __func__));
+ break;
+ case ADC_DC_INIT_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: starting Init ADC DC Calibration\n",
+ __func__));
+ break;
+ }
+
+ REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+static void
+ath9k_hw_reset_calibration(struct ath_hal *ah,
+ struct hal_cal_list *currCal)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ ath9k_hw_setup_calibration(ah, currCal);
+
+ currCal->calState = CAL_RUNNING;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ahp->ah_Meas0.sign[i] = 0;
+ ahp->ah_Meas1.sign[i] = 0;
+ ahp->ah_Meas2.sign[i] = 0;
+ ahp->ah_Meas3.sign[i] = 0;
+ }
+
+ ahp->ah_CalSamples = 0;
+}
+
+static void
+ath9k_hw_per_calibration(struct ath_hal *ah,
+ struct ath9k_channel *ichan,
+ uint8_t rxchainmask,
+ struct hal_cal_list *currCal,
+ boolean_t *isCalDone)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ *isCalDone = B_FALSE;
+
+ if (currCal->calState == CAL_RUNNING) {
+ if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+ AR_PHY_TIMING_CTRL4_DO_CAL)) {
+
+ currCal->calData->calCollect(ah);
+ ahp->ah_CalSamples++;
+
+ if (ahp->ah_CalSamples >=
+ currCal->calData->calNumSamples) {
+ int i, numChains = 0;
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (rxchainmask & (1 << i))
+ numChains++;
+ }
+
+ currCal->calData->calPostProc(ah, numChains);
+ ichan->CalValid |= currCal->calData->calType;
+ currCal->calState = CAL_DONE;
+ *isCalDone = B_TRUE;
+ } else {
+ ath9k_hw_setup_calibration(ah, currCal);
+ }
+ }
+ } else if (!(ichan->CalValid & currCal->calData->calType)) {
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
+}
+
+static boolean_t
+ath9k_hw_iscal_supported(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ enum hal_cal_types calType)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ boolean_t retval = B_FALSE;
+
+ switch (calType & ahp->ah_suppCals) {
+ case IQ_MISMATCH_CAL:
+ if (!IS_CHAN_B(chan))
+ retval = B_TRUE;
+ break;
+ case ADC_GAIN_CAL:
+ case ADC_DC_CAL:
+ if (!IS_CHAN_B(chan) &&
+ !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
+ retval = B_TRUE;
+ break;
+ }
+
+ return (retval);
+}
+
+static void
+ath9k_hw_iqcal_collect(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ahp->ah_totalPowerMeasI[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ahp->ah_totalPowerMeasQ[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ahp->ah_totalIqCorrMeas[i] +=
+ (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+ ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
+ ahp->ah_totalPowerMeasQ[i],
+ ahp->ah_totalIqCorrMeas[i]));
+ }
+}
+
+static void
+ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ahp->ah_totalAdcIOddPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ahp->ah_totalAdcIEvenPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ahp->ah_totalAdcQOddPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ ahp->ah_totalAdcQEvenPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
+ "oddq=0x%08x; evenq=0x%08x;\n",
+ ahp->ah_CalSamples, i,
+ ahp->ah_totalAdcIOddPhase[i],
+ ahp->ah_totalAdcIEvenPhase[i],
+ ahp->ah_totalAdcQOddPhase[i],
+ ahp->ah_totalAdcQEvenPhase[i]));
+ }
+}
+
+static void
+ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
+ (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
+ (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
+ (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
+ (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
+ "oddq=0x%08x; evenq=0x%08x;\n",
+ ahp->ah_CalSamples, i,
+ ahp->ah_totalAdcDcOffsetIOddPhase[i],
+ ahp->ah_totalAdcDcOffsetIEvenPhase[i],
+ ahp->ah_totalAdcDcOffsetQOddPhase[i],
+ ahp->ah_totalAdcDcOffsetQEvenPhase[i]));
+ }
+}
+
+static void
+ath9k_hw_iqcalibrate(struct ath_hal *ah, uint8_t numChains)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t powerMeasQ, powerMeasI, iqCorrMeas;
+ uint32_t qCoffDenom, iCoffDenom;
+ int32_t qCoff, iCoff;
+ int iqCorrNeg, i;
+
+ for (i = 0; i < numChains; i++) {
+ powerMeasI = ahp->ah_totalPowerMeasI[i];
+ powerMeasQ = ahp->ah_totalPowerMeasQ[i];
+ iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Starting IQ Cal and Correction for Chain %d\n",
+ i));
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Orignal: Chn %diq_corr_meas = 0x%08x\n",
+ i, ahp->ah_totalIqCorrMeas[i]));
+
+ iqCorrNeg = 0;
+
+ if (iqCorrMeas > 0x80000000) {
+ iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+ iqCorrNeg = 1;
+ }
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ));
+ ARN_DBG((ARN_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
+ iqCorrNeg));
+
+ iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
+ qCoffDenom = powerMeasQ / 64;
+
+ if (powerMeasQ != 0) {
+ iCoff = iqCorrMeas / iCoffDenom;
+ qCoff = powerMeasI / qCoffDenom - 64;
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d iCoff = 0x%08x\n", i, iCoff));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d qCoff = 0x%08x\n", i, qCoff));
+
+ iCoff = iCoff & 0x3f;
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "New: Chn %d iCoff = 0x%08x\n", i, iCoff));
+
+ if (iqCorrNeg == 0x0)
+ iCoff = 0x40 - iCoff;
+
+ if (qCoff > 15)
+ qCoff = 15;
+ else if (qCoff <= -16)
+ qCoff = 16;
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
+ i, iCoff, qCoff));
+
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+ iCoff);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+ qCoff);
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "IQ Cal and Correction done for Chain %d\n",
+ i));
+ }
+ }
+
+ REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
+
+static void
+ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, uint8_t numChains)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset,
+ qEvenMeasOffset;
+ uint32_t qGainMismatch, iGainMismatch, val, i;
+
+ for (i = 0; i < numChains; i++) {
+ iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
+ iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
+ qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
+ qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Starting ADC Gain Cal for Chain %d\n", i));
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
+ iOddMeasOffset));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_even_i = 0x%08x\n", i,
+ iEvenMeasOffset));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
+ qOddMeasOffset));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_even_q = 0x%08x\n", i,
+ qEvenMeasOffset));
+
+ if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
+ iGainMismatch =
+ ((iEvenMeasOffset * 32) /
+ iOddMeasOffset) & 0x3f;
+ qGainMismatch =
+ ((qOddMeasOffset * 32) /
+ qEvenMeasOffset) & 0x3f;
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d gain_mismatch_i = 0x%08x\n", i,
+ iGainMismatch));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d gain_mismatch_q = 0x%08x\n", i,
+ qGainMismatch));
+
+ val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+ val &= 0xfffff000;
+ val |= (qGainMismatch) | (iGainMismatch << 6);
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "ADC Gain Cal done for Chain %d\n", i));
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+ REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+ AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
+
+static void
+ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, uint8_t numChains)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t iOddMeasOffset, iEvenMeasOffset, val, i;
+ int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
+ const struct hal_percal_data *calData =
+ ahp->ah_cal_list_curr->calData;
+ uint32_t numSamples =
+ (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
+
+ for (i = 0; i < numChains; i++) {
+ iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
+ iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
+ qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
+ qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Starting ADC DC Offset Cal for Chain %d\n", i));
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_odd_i = %d\n", i,
+ iOddMeasOffset));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_even_i = %d\n", i,
+ iEvenMeasOffset));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_odd_q = %d\n", i,
+ qOddMeasOffset));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d pwr_meas_even_q = %d\n", i,
+ qEvenMeasOffset));
+
+ iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
+ numSamples) & 0x1ff;
+ qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
+ numSamples) & 0x1ff;
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
+ iDcMismatch));
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
+ qDcMismatch));
+
+ val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+ val &= 0xc0000fff;
+ val |= (qDcMismatch << 12) | (iDcMismatch << 21);
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "ADC DC Offset Cal done for Chain %d\n", i));
+ }
+
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+ REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+ AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
+
+void
+ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
+ boolean_t *isCalDone)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *ichan =
+ ath9k_regd_check_channel(ah, chan);
+ struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
+
+ *isCalDone = B_TRUE;
+
+ if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
+ return;
+
+ if (currCal == NULL)
+ return;
+
+ if (ichan == NULL) {
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: invalid channel %u/0x%x; no mapping\n",
+ __func__, chan->channel, chan->channelFlags));
+ return;
+ }
+
+
+ if (currCal->calState != CAL_DONE) {
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: Calibration state incorrect, %d\n",
+ __func__, currCal->calState));
+ return;
+ }
+
+
+ if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
+ return;
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: Resetting Cal %d state for channel %u/0x%x\n",
+ __func__, currCal->calData->calType, chan->channel,
+ chan->channelFlags));
+
+ ichan->CalValid &= ~currCal->calData->calType;
+ currCal->calState = CAL_WAITING;
+
+ *isCalDone = B_FALSE;
+}
+
+void
+ath9k_hw_start_nfcal(struct ath_hal *ah)
+{
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_ENABLE_NF);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath9k_nfcal_hist *h;
+ int i, j;
+ int32_t val;
+ const uint32_t ar5416_cca_regs[6] = {
+ AR_PHY_CCA,
+ AR_PHY_CH1_CCA,
+ AR_PHY_CH2_CCA,
+ AR_PHY_EXT_CCA,
+ AR_PHY_CH1_EXT_CCA,
+ AR_PHY_CH2_EXT_CCA
+ };
+ uint8_t chainmask;
+
+ if (AR_SREV_9280(ah))
+ chainmask = 0x1B;
+ else
+ chainmask = 0x3F;
+
+#ifdef ARN_NF_PER_CHAN
+ h = chan->nfCalHist;
+#else
+ h = ah->nfCalHist;
+#endif
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (chainmask & (1 << i)) {
+ val = REG_READ(ah, ar5416_cca_regs[i]);
+ val &= 0xFFFFFE00;
+ val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff);
+ REG_WRITE(ah, ar5416_cca_regs[i], val);
+ }
+ }
+
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_ENABLE_NF);
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+ for (j = 0; j < 1000; j++) {
+ if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
+ AR_PHY_AGC_CONTROL_NF) == 0)
+ break;
+ drv_usecwait(10);
+ }
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (chainmask & (1 << i)) {
+ val = REG_READ(ah, ar5416_cca_regs[i]);
+ val &= 0xFFFFFE00;
+ val |= (((uint32_t)(-50) << 1) & 0x1ff);
+ REG_WRITE(ah, ar5416_cca_regs[i], val);
+ }
+ }
+}
+
+int16_t
+ath9k_hw_getnf(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ int16_t nf, nfThresh;
+ int16_t nfarray[NUM_NF_READINGS] = { 0 };
+ struct ath9k_nfcal_hist *h;
+ /* LINTED E_FUNC_SET_NOT_USED */
+ uint8_t chainmask;
+
+ if (AR_SREV_9280(ah))
+ chainmask = 0x1B;
+ else
+ chainmask = 0x3F;
+
+ chan->channelFlags &= (~CHANNEL_CW_INT);
+ if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+ ARN_DBG((ARN_DBG_CALIBRATE, "arn: "
+ "%s: NF did not complete in calibration window\n",
+ __func__));
+ nf = 0;
+ chan->rawNoiseFloor = nf;
+ return (chan->rawNoiseFloor);
+ } else {
+ ath9k_hw_do_getnf(ah, nfarray);
+ nf = nfarray[0];
+ if (getNoiseFloorThresh(ah, chan, &nfThresh) &&
+ nf > nfThresh) {
+ ARN_DBG((ARN_DBG_CALIBRATE, "arn: "
+ "%s: noise floor failed detected; "
+ "detected %d, threshold %d\n", __func__,
+ nf, nfThresh));
+ chan->channelFlags |= CHANNEL_CW_INT;
+ }
+ }
+
+#ifdef ARN_NF_PER_CHAN
+ h = chan->nfCalHist;
+#else
+ h = ah->nfCalHist;
+#endif
+
+ ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
+ chan->rawNoiseFloor = h[0].privNF;
+
+ return (chan->rawNoiseFloor);
+}
+
+void
+ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
+{
+ int i, j;
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ ah->nfCalHist[i].currIndex = 0;
+ ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
+ ah->nfCalHist[i].invalidNFcount =
+ AR_PHY_CCA_FILTERWINDOW_LENGTH;
+ for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
+ ah->nfCalHist[i].nfCalBuffer[j] =
+ AR_PHY_CCA_MAX_GOOD_VALUE;
+ }
+ }
+}
+
+signed short
+ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath9k_channel *ichan;
+ signed short nf;
+
+ ichan = ath9k_regd_check_channel(ah, chan);
+ if (ichan == NULL) {
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: invalid channel %u/0x%x; no mapping\n",
+ __func__, chan->channel, chan->channelFlags));
+ return (ATH_DEFAULT_NOISE_FLOOR);
+ }
+ if (ichan->rawNoiseFloor == 0) {
+ enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
+ nf = NOISE_FLOOR[mode];
+ } else
+ nf = ichan->rawNoiseFloor;
+
+ if (!ath9k_hw_nf_in_range(ah, nf))
+ nf = ATH_DEFAULT_NOISE_FLOOR;
+
+ return (nf);
+}
+
+boolean_t
+ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
+ uint8_t rxchainmask, boolean_t longcal,
+ boolean_t *isCalDone)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
+ struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
+
+ *isCalDone = B_TRUE;
+
+ if (ichan == NULL) {
+ ARN_DBG((ARN_DBG_CHANNEL,
+ "%s: invalid channel %u/0x%x; no mapping\n",
+ __func__, chan->channel, chan->channelFlags));
+ return (B_FALSE);
+ }
+
+ if (currCal &&
+ (currCal->calState == CAL_RUNNING ||
+ currCal->calState == CAL_WAITING)) {
+ ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
+ isCalDone);
+ if (*isCalDone) {
+ ahp->ah_cal_list_curr = currCal = currCal->calNext;
+
+ if (currCal->calState == CAL_WAITING) {
+ *isCalDone = B_FALSE;
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
+ }
+ }
+
+ if (longcal) {
+ (void) ath9k_hw_getnf(ah, ichan);
+ ath9k_hw_loadnf(ah, ah->ah_curchan);
+ ath9k_hw_start_nfcal(ah);
+
+ if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
+ chan->channelFlags |= CHANNEL_CW_INT;
+ ichan->channelFlags &= ~CHANNEL_CW_INT;
+ }
+ }
+
+ return (B_TRUE);
+}
+
+/* AR9285 */
+static inline void
+ath9k_hw_9285_pa_cal(struct ath_hal *ah)
+{
+
+ uint32_t regVal;
+ int i, offset, offs_6_1, offs_0;
+ uint32_t ccomp_org, reg_field;
+ uint32_t regList[][2] = {
+ { 0x786c, 0 },
+ { 0x7854, 0 },
+ { 0x7820, 0 },
+ { 0x7824, 0 },
+ { 0x7868, 0 },
+ { 0x783c, 0 },
+ { 0x7838, 0 },
+ };
+
+ if (AR_SREV_9285_11(ah)) {
+ REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
+ drv_usecwait(10);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ regList[i][1] = REG_READ(ah, regList[i][0]);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1));
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal |= (0x1 << 27);
+ REG_WRITE(ah, 0x9808, regVal);
+
+ REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+ ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7);
+
+ REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
+ drv_usecwait(30);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
+
+ for (i = 6; i > 0; i--) {
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= (1 << (19 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ drv_usecwait(1);
+ regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1 << (19 + i)));
+ reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
+ regVal |= (reg_field << (19 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ }
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
+ drv_usecwait(1);
+ reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
+ offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
+ offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
+
+ offset = (offs_6_1<<1) | offs_0;
+ offset = offset - 0;
+ offs_6_1 = offset>>1;
+ offs_0 = offset & 1;
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= 0x1;
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal &= (~(0x1 << 27));
+ REG_WRITE(ah, 0x9808, regVal);
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ REG_WRITE(ah, regList[i][0], regList[i][1]);
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
+
+ if (AR_SREV_9285_11(ah))
+ REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+
+}
+
+boolean_t
+ath9k_hw_init_cal(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
+
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
+ AR_PHY_AGC_CONTROL_CAL);
+
+ if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: offset calibration failed to complete in 1ms; "
+ "noisy environment?\n", __func__));
+ return (B_FALSE);
+ }
+
+ if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
+ ath9k_hw_9285_pa_cal(ah);
+
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
+ AR_PHY_AGC_CONTROL_NF);
+
+ ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
+
+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
+ if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
+ /* LINTED: E_CONSTANT_CONDITION */
+ INIT_CAL(&ahp->ah_adcGainCalData);
+ /* LINTED: E_CONSTANT_CONDITION */
+ INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: enabling ADC Gain Calibration.\n",
+ __func__));
+ }
+ if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
+ /* LINTED: E_CONSTANT_CONDITION */
+ INIT_CAL(&ahp->ah_adcDcCalData);
+ /* LINTED: E_CONSTANT_CONDITION */
+ INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: enabling ADC DC Calibration.\n",
+ __func__));
+ }
+ if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
+ /* LINTED: E_CONSTANT_CONDITION */
+ INIT_CAL(&ahp->ah_iqCalData);
+ /* LINTED: E_CONSTANT_CONDITION */
+ INSERT_CAL(ahp, &ahp->ah_iqCalData);
+ ARN_DBG((ARN_DBG_CALIBRATE,
+ "%s: enabling IQ Calibration.\n",
+ __func__));
+ }
+
+ ahp->ah_cal_list_curr = ahp->ah_cal_list;
+
+ if (ahp->ah_cal_list_curr)
+ ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
+ }
+
+ ichan->CalValid = 0;
+
+ return (B_TRUE);
+}
+
+const struct hal_percal_data iq_cal_multi_sample = {
+ IQ_MISMATCH_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ath9k_hw_iqcal_collect,
+ ath9k_hw_iqcalibrate
+};
+const struct hal_percal_data iq_cal_single_sample = {
+ IQ_MISMATCH_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ath9k_hw_iqcal_collect,
+ ath9k_hw_iqcalibrate
+};
+const struct hal_percal_data adc_gain_cal_multi_sample = {
+ ADC_GAIN_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ath9k_hw_adc_gaincal_collect,
+ ath9k_hw_adc_gaincal_calibrate
+};
+const struct hal_percal_data adc_gain_cal_single_sample = {
+ ADC_GAIN_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ath9k_hw_adc_gaincal_collect,
+ ath9k_hw_adc_gaincal_calibrate
+};
+const struct hal_percal_data adc_dc_cal_multi_sample = {
+ ADC_DC_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ath9k_hw_adc_dccal_collect,
+ ath9k_hw_adc_dccal_calibrate
+};
+const struct hal_percal_data adc_dc_cal_single_sample = {
+ ADC_DC_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ath9k_hw_adc_dccal_collect,
+ ath9k_hw_adc_dccal_calibrate
+};
+const struct hal_percal_data adc_init_dc_cal = {
+ ADC_DC_INIT_CAL,
+ MIN_CAL_SAMPLES,
+ INIT_LOG_COUNT,
+ ath9k_hw_adc_dccal_collect,
+ ath9k_hw_adc_dccal_calibrate
+};
diff --git a/usr/src/uts/common/io/arn/arn_core.h b/usr/src/uts/common/io/arn/arn_core.h
new file mode 100644
index 0000000000..01b7df10b3
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_core.h
@@ -0,0 +1,877 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARN_CORE_H
+#define _ARN_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/note.h>
+#include <sys/list.h>
+#include <sys/net80211.h>
+
+#include "arn_ath9k.h"
+#include "arn_rc.h"
+
+struct ath_node;
+
+/*
+ * Node type of wifi device
+ */
+#ifndef DDI_NT_NET_WIFI
+#define DDI_NT_NET_WIFI "ddi_network:wifi"
+#endif
+#define ARN_NODENAME "arn"
+
+#define ARN_LOCK(_sc) mutex_enter(&(_sc)->sc_genlock)
+#define ARN_UNLOCK(_sc) mutex_exit(&(_sc)->sc_genlock)
+#define ARN_LOCK_ASSERT(_sc) ASSERT(mutex_owned(&(_sc)->sc_genlock))
+
+#define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#define ARN_MIN(a, b) ((a) < (b) ? (a) : (b))
+#define ARN_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define abs(x) ((x) >= 0 ? (x) : -(x))
+
+enum ath9k_key_len {
+ ATH9K_LEN_WEP40 = 5,
+ ATH9K_LEN_WEP104 = 13,
+};
+
+/*
+ * Sync a DMA area described by a dma_area_t
+ */
+#define ARN_DMA_SYNC(area, flag) ((void) ddi_dma_sync((area).dma_hdl, \
+ (area).offset, (area).alength, (flag)))
+
+#define list_empty(a) ((a)->list_head.list_next == &(a)->list_head)
+
+#define ARN_LE_READ_16(p) \
+ ((uint16_t) \
+ ((((uint8_t *)(p))[0]) | (((uint8_t *)(p))[1] << 8)))
+
+#define ARN_LE_READ_32(p) \
+ ((uint32_t) \
+ ((((uint8_t *)(p))[0]) | (((uint8_t *)(p))[1] << 8) | \
+ (((uint8_t *)(p))[2] << 16) | (((uint8_t *)(p))[3] << 24)))
+
+#define swab16(value) \
+ ((((value) & 0xff) << 8) | ((value) >> 8))
+
+#define swab32(value) \
+ (((uint32_t)swab16((uint16_t)((value) & 0xffff)) << 16) | \
+ (uint32_t)swab16((uint16_t)((value) >> 16)))
+
+#define swab64(value) \
+ (((uint64_t)swab32((uint32_t)((value) & 0xffffffff)) \
+ << 32) | \
+ (uint64_t)swab32((uint32_t)((value) >> 32)))
+
+/* Bit map related macros. */
+#define set_bit(i, a) ((a)[(i)/NBBY] |= (1 << ((i)%NBBY)))
+#define clr_bit(i, a) ((a)[(i)/NBBY] &= ~(1 << ((i)%NBBY)))
+#define is_set(i, a) ((a)[(i)/NBBY] & (1 << ((i)%NBBY)))
+#define is_clr(i, a) (!((a)[(i)/NBBY] & (1 << ((i)%NBBY))))
+
+/* Macro to expand scalars to 64-bit objects */
+
+#define ito64(x) (sizeof (x) == 8) ? \
+ (((unsigned long long int)(x)) & (0xff)) : \
+ (sizeof (x) == 16) ? \
+ (((unsigned long long int)(x)) & 0xffff) : \
+ ((sizeof (x) == 32) ? \
+ (((unsigned long long int)(x)) & 0xffffffff) : \
+ (unsigned long long int)(x))
+
+/* increment with wrap-around */
+#define INCR(_l, _sz) do { \
+ (_l)++; \
+ (_l) &= ((_sz) - 1); \
+ } while (0)
+
+/* decrement with wrap-around */
+#define DECR(_l, _sz) do { \
+ (_l)--; \
+ (_l) &= ((_sz) - 1); \
+ } while (0)
+
+#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define TSF_TO_TU(_h, _l) \
+ ((((uint32_t)(_h)) << 22) | (((uint32_t)(_l)) >> 10))
+
+#define ARN_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i))
+
+// static const uint8_t ath_bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+/* Debugging */
+enum ARN_DEBUG {
+ ARN_DBG_HW = 0x00000001,
+ ARN_DBG_REG_IO = 0x00000002,
+ ARN_DBG_QUEUE = 0x00000004,
+ ARN_DBG_EEPROM = 0x00000008,
+ ARN_DBG_XMIT = 0x00000010,
+ ARN_DBG_RECV = 0x00000020,
+ ARN_DBG_CALIBRATE = 0x00000040,
+ ARN_DBG_CHANNEL = 0x00000080,
+ ARN_DBG_INTERRUPT = 0x00000100,
+ ARN_DBG_REGULATORY = 0x00000200,
+ ARN_DBG_ANI = 0x00000400,
+ ARN_DBG_POWER_MGMT = 0x00000800,
+ ARN_DBG_KEYCACHE = 0x00001000,
+ ARN_DBG_BEACON = 0x00002000,
+ ARN_DBG_RATE = 0x00004000,
+ ARN_DBG_INIT = 0x00008000,
+ ARN_DBG_ATTACH = 0x00010000,
+ ARN_DBG_DEATCH = 0x00020000,
+ ARN_DBG_AGGR = 0x00040000,
+ ARN_DBG_RESET = 0x00080000,
+ ARN_DBG_FATAL = 0x00100000,
+ ARN_DBG_ANY = 0x00200000,
+ ARN_DBG_ALL = 0x00FFFFFF,
+};
+
+/* Debug and log functions */
+void arn_dbg(uint32_t dbg_flags, const int8_t *fmt, ...); /* debug function */
+void arn_log(const int8_t *fmt, ...); /* event log function */
+void arn_problem(const int8_t *fmt, ...); /* run-time problem function */
+
+#ifdef DEBUG
+#define ARN_DDB(command) do { \
+ { command; } \
+ _NOTE(CONSTANTCONDITION)\
+ } while (0)
+#else
+#define ARN_DDB(command)
+#endif /* DEBUG */
+
+#define ARN_DBG(args) ARN_DDB(arn_dbg args)
+
+struct ath_stats {
+ uint32_t ast_hardware; /* fatal hardware error interrupts */
+ uint32_t ast_rxorn; /* rx overrun interrupts */
+ uint32_t ast_rxeol; /* rx eol interrupts */
+ uint32_t ast_txurn; /* tx underrun interrupts */
+ uint32_t ast_tx_mgmt; /* management frames transmitted */
+ uint32_t ast_tx_discard; /* frames discarded prior to assoc */
+ uint32_t ast_tx_invalid; /* frames discarded 'cuz device gone */
+ uint32_t ast_tx_qstop; /* tx queue stopped 'cuz full */
+ uint32_t ast_tx_nobuf; /* tx failed 'cuz no tx buffer (data) */
+ uint32_t ast_tx_nobufmgt; /* tx failed 'cuz no tx buffer(mgmt) */
+ uint32_t ast_tx_xretries; /* tx failed 'cuz too many retries */
+ uint32_t ast_tx_fifoerr; /* tx failed 'cuz FIFO underrun */
+ uint32_t ast_tx_filtered; /* tx failed 'cuz xmit filtered */
+ uint32_t ast_tx_shortretry; /* tx on-chip retries (short) */
+ uint32_t ast_tx_longretry; /* tx on-chip retries (long) */
+ uint32_t ast_tx_noack; /* tx frames with no ack marked */
+ uint32_t ast_tx_rts; /* tx frames with rts enabled */
+ uint32_t ast_tx_shortpre; /* tx frames with short preamble */
+ uint32_t ast_tx_altrate; /* tx frames with alternate rate */
+ uint32_t ast_tx_protect; /* tx frames with protection */
+ int16_t ast_tx_rssi; /* tx rssi of last ack */
+ int16_t ast_tx_rssidelta; /* tx rssi delta */
+ uint32_t ast_rx_crcerr; /* rx failed 'cuz of bad CRC */
+ uint32_t ast_rx_fifoerr; /* rx failed 'cuz of FIFO overrun */
+ uint32_t ast_rx_badcrypt; /* rx failed 'cuz decryption */
+ uint32_t ast_rx_phyerr; /* rx PHY error summary count */
+ uint32_t ast_rx_phy[32]; /* rx PHY error per-code counts */
+ uint32_t ast_rx_tooshort; /* rx discarded 'cuz frame too short */
+ uint32_t ast_per_cal; /* periodic calibration calls */
+ uint32_t ast_per_calfail; /* periodic calibration failed */
+ uint32_t ast_per_rfgain; /* periodic calibration rfgain reset */
+ uint32_t ast_rate_calls; /* rate control checks */
+ uint32_t ast_rate_raise; /* rate control raised xmit rate */
+ uint32_t ast_rate_drop; /* rate control dropped xmit rate */
+};
+
+struct dma_area {
+ ddi_acc_handle_t acc_hdl; /* handle for memory */
+ caddr_t mem_va; /* CPU VA of memory */
+ uint32_t nslots; /* number of slots */
+ uint32_t size; /* size per slot */
+ size_t alength; /* allocated size */
+ /* >= product of above */
+
+ ddi_dma_handle_t dma_hdl; /* DMA handle */
+ offset_t offset; /* relative to handle */
+ ddi_dma_cookie_t cookie; /* associated cookie */
+ uint32_t ncookies; /* must be 1 */
+ uint32_t token; /* arbitrary identifier */
+};
+typedef struct dma_area dma_area_t;
+
+/* Load-time Configuration */
+
+/*
+ * Per-instance load-time (note: NOT run-time)
+ * configurations for Atheros Device
+ */
+struct ath_config {
+ uint32_t ath_aggr_prot;
+ uint16_t txpowlimit;
+ uint16_t txpowlimit_override;
+ uint8_t cabqReadytime; /* Cabq Readytime % */
+ uint8_t swBeaconProcess; /* Process received beacons in SW (vs HW) */
+};
+
+/* Descriptor Management */
+
+#define ATH_TXBUF_RESET(_bf) do { \
+ (_bf)->bf_status = 0; \
+ (_bf)->bf_lastbf = NULL; \
+ (_bf)->bf_lastfrm = NULL; \
+ (_bf)->bf_next = NULL; \
+ memset(&((_bf)->bf_state), 0, \
+ sizeof (struct ath_buf_state)); \
+ } while (0)
+
+enum buffer_type {
+ BUF_DATA = BIT(0),
+ BUF_AGGR = BIT(1),
+ BUF_AMPDU = BIT(2),
+ BUF_HT = BIT(3),
+ BUF_RETRY = BIT(4),
+ BUF_XRETRY = BIT(5),
+ BUF_SHORT_PREAMBLE = BIT(6),
+ BUF_BAR = BIT(7),
+ BUF_PSPOLL = BIT(8),
+ BUF_AGGR_BURST = BIT(9),
+ BUF_CALC_AIRTIME = BIT(10),
+};
+
+struct ath_buf_state {
+ int bfs_nframes; /* # frames in aggregate */
+ uint16_t bfs_al; /* length of aggregate */
+ uint16_t bfs_frmlen; /* length of frame */
+ int bfs_seqno; /* sequence number */
+ int bfs_tidno; /* tid of this frame */
+ int bfs_retries; /* current retries */
+ uint32_t bf_type; /* BUF_* (enum buffer_type) */
+ /* key type used to encrypt this frame */
+ uint32_t bfs_keyix;
+ enum ath9k_key_type bfs_keytype;
+};
+
+#define bf_nframes bf_state.bfs_nframes
+#define bf_al bf_state.bfs_al
+#define bf_frmlen bf_state.bfs_frmlen
+#define bf_retries bf_state.bfs_retries
+#define bf_seqno bf_state.bfs_seqno
+#define bf_tidno bf_state.bfs_tidno
+#define bf_rcs bf_state.bfs_rcs
+#define bf_keyix bf_state.bfs_keyix
+#define bf_keytype bf_state.bfs_keytype
+#define bf_isdata(bf) (bf->bf_state.bf_type & BUF_DATA)
+#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
+#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
+#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT)
+#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY)
+#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
+#define bf_isshpreamble(bf) (bf->bf_state.bf_type & BUF_SHORT_PREAMBLE)
+#define bf_isbar(bf) (bf->bf_state.bf_type & BUF_BAR)
+#define bf_ispspoll(bf) (bf->bf_state.bf_type & BUF_PSPOLL)
+#define bf_isaggrburst(bf) (bf->bf_state.bf_type & BUF_AGGR_BURST)
+
+/*
+ * Abstraction of a contiguous buffer to transmit/receive.
+ * There is only a single hw descriptor encapsulated here.
+ */
+struct ath_buf {
+ /* last buf of this unit (a frame or an aggregate) */
+ struct ath_buf *bf_lastbf;
+ struct ath_buf *bf_lastfrm; /* last buf of this frame */
+ struct ath_buf *bf_next; /* next subframe in the aggregate */
+ mblk_t *bf_m;
+ struct ath_desc *bf_desc; /* virtual addr of desc */
+ uint32_t bf_daddr; /* physical addr of desc */
+ dma_area_t bf_dma; /* dma area for buf */
+ struct ieee80211_node *bf_in; /* pointer to the node */
+ uint32_t bf_status;
+ uint16_t bf_flags; /* tx descriptor flags */
+ struct ath_buf_state bf_state; /* buffer state */
+
+ /* we're in list of sc->sc_txbuf_list or asc->asc_rxbuf_list */
+ list_node_t bf_node;
+};
+
+/*
+ * reset the rx buffer.
+ * any new fields added to the athbuf and require
+ * reset need to be added to this macro.
+ * currently bf_status is the only one requires that
+ * requires reset.
+ */
+#define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0)
+
+/* hw processing complete, desc processed by hal */
+#define ATH_BUFSTATUS_DONE 0x00000001
+/* hw processing complete, desc hold for hw */
+#define ATH_BUFSTATUS_STALE 0x00000002
+/* Rx-only: OS is done with this packet and it's ok to queued it to hw */
+#define ATH_BUFSTATUS_FREE 0x00000004
+
+/* RX / TX */
+
+#define ATH_MAX_ANTENNA 3
+#define ATH_RXBUF 512
+#define WME_NUM_TID 16
+
+void arn_rx_buf_link(struct arn_softc *sc, struct ath_buf *bf);
+int arn_startrecv(struct arn_softc *sc);
+boolean_t arn_stoprecv(struct arn_softc *sc);
+void arn_flushrecv(struct arn_softc *sc);
+uint32_t arn_calcrxfilter(struct arn_softc *sc);
+int arn_rx_init(struct arn_softc *sc, int nbufs);
+void arn_rx_cleanup(struct arn_softc *sc);
+uint_t arn_softint_handler(caddr_t data);
+void arn_setdefantenna(struct arn_softc *sc, uint32_t antenna);
+
+#define ATH_TXBUF 512
+/* max number of transmit attempts (tries) */
+#define ATH_TXMAXTRY 13
+/* max number of 11n transmit attempts (tries) */
+#define ATH_11N_TXMAXTRY 10
+/* max number of tries for management and control frames */
+#define ATH_MGT_TXMAXTRY 4
+#define WME_BA_BMP_SIZE 64
+#define WME_MAX_BA WME_BA_BMP_SIZE
+#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
+#define TID_TO_WME_AC(_tid) \
+ ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
+ (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
+ (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
+ WME_AC_VO)
+
+/* Wireless Multimedia Extension Defines */
+#define WME_AC_BE 0 /* best effort */
+#define WME_AC_BK 1 /* background */
+#define WME_AC_VI 2 /* video */
+#define WME_AC_VO 3 /* voice */
+#define WME_NUM_AC 4
+
+/*
+ * Data transmit queue state. One of these exists for each
+ * hardware transmit queue. Packets sent to us from above
+ * are assigned to queues based on their priority. Not all
+ * devices support a complete set of hardware transmit queues.
+ * For those devices the array sc_ac2q will map multiple
+ * priorities to fewer hardware queues (typically all to one
+ * hardware queue).
+ */
+
+struct ath_txq {
+ uint_t axq_qnum; /* hardware q number */
+ uint32_t *axq_link; /* link ptr in last TX desc */
+ list_t axq_list; /* transmit queue */
+ kmutex_t axq_lock; /* lock on q and link */
+ unsigned long axq_lockflags; /* intr state when must cli */
+ uint_t axq_depth; /* queue depth (stat only) */
+ uint8_t axq_aggr_depth; /* aggregates queued */
+ uint32_t axq_totalqueued; /* total ever queued */
+ struct ath_buf *axq_linkbuf; /* virtual addr of last buffer */
+ /* first desc of the last descriptor that contains CTS */
+ struct ath_desc *axq_lastdsWithCTS;
+ uint_t axq_intrcnt; /* interrupt count */
+};
+
+
+#define AGGR_CLEANUP BIT(1)
+#define AGGR_ADDBA_COMPLETE BIT(2)
+#define AGGR_ADDBA_PROGRESS BIT(3)
+
+/* per TID aggregate tx state for a destination */
+struct ath_atx_tid {
+ list_node_t list;
+ list_node_t buf_q;
+ struct ath_node *an;
+ struct ath_atx_ac *ac;
+ struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; /* active tx frames */
+ uint16_t seq_start;
+ uint16_t seq_next;
+ uint16_t baw_size;
+ int tidno;
+ int baw_head; /* first un-acked tx buffer */
+ int baw_tail; /* next unused tx buffer slot */
+ int sched;
+ int paused;
+ uint8_t state;
+ int addba_exchangeattempts;
+};
+
+/* per access-category aggregate tx state for a destination */
+struct ath_atx_ac {
+ int sched; /* dest-ac is scheduled */
+ int qnum; /* H/W queue number associated with this AC */
+ list_node_t list;
+ list_node_t tid_q;
+};
+
+/* per dest tx state */
+struct ath_atx {
+ struct ath_atx_tid tid[WME_NUM_TID];
+ struct ath_atx_ac ac[WME_NUM_AC];
+};
+
+/* per-frame tx control block */
+struct ath_tx_control {
+ struct ath_txq *txq;
+ int if_id;
+};
+
+/* per frame tx status block */
+struct ath_xmit_status {
+ /* number of retries to successufully transmit this frame */
+ int retries;
+ int flags; /* status of transmit */
+#define ATH_TX_ERROR 0x01
+#define ATH_TX_XRETRY 0x02
+#define ATH_TX_BAR 0x04
+};
+
+struct ath_tx_stat {
+ int rssi; /* RSSI (noise floor ajusted) */
+ int rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */
+ int rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */
+ int rateieee; /* data rate xmitted (IEEE rate code) */
+ int rateKbps; /* data rate xmitted (Kbps) */
+ int ratecode; /* phy rate code */
+ int flags; /* validity flags */
+/* if any of ctl,extn chain rssis are valid */
+#define ATH_TX_CHAIN_RSSI_VALID 0x01
+/* if extn chain rssis are valid */
+#define ATH_TX_RSSI_EXTN_VALID 0x02
+ uint32_t airtime; /* time on air per final tx rate */
+};
+
+struct ath_txq *arn_txq_setup(struct arn_softc *sc, int qtype, int subtype);
+void arn_tx_cleanupq(struct arn_softc *sc, struct ath_txq *txq);
+int arn_tx_setup(struct arn_softc *sc, int haltype);
+void arn_draintxq(struct arn_softc *sc, boolean_t retry_tx);
+void arn_tx_draintxq(struct arn_softc *sc, struct ath_txq *txq);
+int arn_tx(ieee80211com_t *ic, mblk_t *mp, uint8_t type);
+int arn_txq_update(struct arn_softc *sc, int qnum,
+ struct ath9k_tx_queue_info *qinfo);
+void arn_tx_int_proc(void *arg);
+
+/* Node / Aggregation */
+
+#define ADDBA_EXCHANGE_ATTEMPTS 10
+#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */
+#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
+/* number of delimiters for encryption padding */
+#define ATH_AGGR_ENCRYPTDELIM 10
+/* minimum h/w qdepth to be sustained to maximize aggregation */
+#define ATH_AGGR_MIN_QDEPTH 2
+#define ATH_AMPDU_SUBFRAME_DEFAULT 32
+#define IEEE80211_SEQ_SEQ_SHIFT 4
+#define IEEE80211_SEQ_MAX 4096
+#define IEEE80211_MIN_AMPDU_BUF 0x8
+#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
+
+/*
+ * return whether a bit at index _n in bitmap _bm is set
+ * _sz is the size of the bitmap
+ */
+#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \
+ ((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
+
+/* return block-ack bitmap index given sequence and starting sequence */
+#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
+
+/* returns delimiter padding required given the packet length */
+#define ATH_AGGR_GET_NDELIM(_len) \
+ (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \
+ (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
+
+#define BAW_WITHIN(_start, _bawsz, _seqno) \
+ ((((_seqno) - (_start)) & 4095) < (_bawsz))
+
+#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum)
+#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low)
+#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
+#define ATH_AN_2_TID(_an, _tidno) (&(_an)->an_aggr.tx.tid[(_tidno)])
+
+enum ATH_AGGR_STATUS {
+ ATH_AGGR_DONE,
+ ATH_AGGR_BAW_CLOSED,
+ ATH_AGGR_LIMITED,
+ ATH_AGGR_SHORTPKT,
+ ATH_AGGR_8K_LIMITED,
+};
+
+struct aggr_rifs_param {
+ int param_max_frames;
+ int param_max_len;
+ int param_rl;
+ int param_al;
+ struct ath_rc_series *param_rcs;
+};
+
+/* driver-specific node state */
+struct ath_node {
+ struct ieee80211_node an_node; /* base class */
+ uint32_t an_tx_times; /* rate ctl times on one rate */
+ uint32_t an_tx_ok; /* tx ok pkt */
+ uint32_t an_tx_err; /* tx !ok pkt */
+ uint32_t an_tx_retr; /* tx retry count */
+ int32_t an_tx_upper; /* tx upper rate req cnt */
+ uint32_t an_tx_antenna; /* antenna for last good frame */
+ uint8_t an_tx_rix0; /* series 0 rate index */
+ uint8_t an_tx_try0; /* series 0 try count */
+ uint8_t an_tx_mgtrate; /* h/w rate for management/ctl frames */
+ uint8_t an_tx_mgtratesp; /* short preamble h/w rate for " " */
+ uint8_t an_tx_rate0; /* series 0 h/w rate */
+ uint8_t an_tx_rate1; /* series 1 h/w rate */
+ uint8_t an_tx_rate2; /* series 2 h/w rate */
+ uint8_t an_tx_rate3; /* series 3 h/w rate */
+ uint8_t an_tx_rate0sp; /* series 0 short preamble h/w rate */
+ uint8_t an_tx_rate1sp; /* series 1 short preamble h/w rate */
+ uint8_t an_tx_rate2sp; /* series 2 short preamble h/w rate */
+ uint8_t an_tx_rate3sp; /* series 3 short preamble h/w rate */
+ struct arn_softc *an_sc;
+#ifdef ARN_11N
+ struct ath_node_aggr an_aggr;
+#endif
+ uint16_t maxampdu;
+ uint8_t mpdudensity;
+};
+#define ATH_NODE(_n) ((struct ath_node *)(_n))
+
+/*
+ * Define the scheme that we select MAC address for multiple
+ * BSS on the same radio. The very first VAP will just use the MAC
+ * address from the EEPROM. For the next 3 VAPs, we set the
+ * U/L bit (bit 1) in MAC address, and use the next two bits as the
+ * index of the VAP.
+ */
+
+#define ATH_SET_VAP_BSSID_MASK(bssid_mask) \
+ ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02))
+
+
+/* driver-specific vap state */
+struct ath_vap {
+ int av_bslot; /* beacon slot index */
+ enum ath9k_opmode av_opmode; /* VAP operational mode */
+ struct ath_buf *av_bcbuf; /* beacon buffer */
+ struct ath_tx_control av_btxctl; /* txctl information for beacon */
+};
+
+/* Beacon Handling */
+
+/*
+ * Regardless of the number of beacons we stagger, (i.e. regardless of the
+ * number of BSSIDs) if a given beacon does not go out even after waiting this
+ * number of beacon intervals, the game's up.
+ */
+#define BSTUCK_THRESH (9 * ATH_BCBUF)
+#define ATH_BCBUF 4 /* number of beacon buffers */
+#define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */
+#define ATH_DEFAULT_BMISS_LIMIT 10
+#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
+
+/* beacon configuration */
+struct ath_beacon_config {
+ uint16_t beacon_interval;
+ uint16_t listen_interval;
+ uint16_t dtim_period;
+ uint16_t bmiss_timeout;
+ uint8_t dtim_count;
+ uint8_t tim_offset;
+ union {
+ uint64_t last_tsf;
+ uint8_t last_tstamp[8];
+ } u; /* last received beacon/probe response timestamp of this BSS. */
+};
+
+uint32_t arn_beaconq_setup(struct ath_hal *ah);
+int arn_beacon_alloc(struct arn_softc *sc, struct ieee80211_node *in);
+void arn_beacon_config(struct arn_softc *sc);
+void arn_beacon_return(struct arn_softc *sc);
+void arn_beacon_sync(struct arn_softc *sc);
+void arn_bmiss_proc(void *arg);
+
+void arn_recv_mgmt(struct ieee80211com *ic, mblk_t *mp,
+ struct ieee80211_node *in, int subtype, int rssi, uint32_t rstamp);
+
+/* ANI */
+
+/*
+ * ANI values for STA only.
+ * FIXME: Add appropriate values for AP later
+ */
+
+#define ATH_ANI_POLLINTERVAL 100 /* 100 milliseconds between ANI poll */
+#define ATH_SHORT_CALINTERVAL 1000 /* 1 second between calibrations */
+#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds between calibrations */
+#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes between calibrations */
+
+struct ath_ani {
+ boolean_t sc_caldone;
+ int16_t sc_noise_floor;
+ unsigned int sc_longcal_timer;
+ unsigned int sc_shortcal_timer;
+ unsigned int sc_resetcal_timer;
+ unsigned int sc_checkani_timer;
+};
+
+/* LED Control */
+#define ATH_LED_PIN 1
+
+enum ath_led_type {
+ ATH_LED_RADIO,
+ ATH_LED_ASSOC,
+ ATH_LED_TX,
+ ATH_LED_RX
+};
+
+struct ath_led {
+ struct arn_softc *sc;
+ enum ath_led_type led_type;
+ char name[32];
+ boolean_t registered;
+};
+
+/* Rfkill */
+#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */
+
+/* Main driver core */
+/*
+ * Default cache line size, in bytes.
+ * Used when PCI device not fully initialized by bootrom/BIOS
+ */
+#define DEFAULT_CACHELINE 32
+#define ATH_DEFAULT_NOISE_FLOOR -95
+#define ATH_REGCLASSIDS_MAX 10
+#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
+#define ATH_MAX_SW_RETRIES 10
+#define ATH_CHAN_MAX 255
+#define IEEE80211_WEP_NKID 4 /* number of key ids */
+#define IEEE80211_RATE_VAL 0x7f
+/*
+ * The key cache is used for h/w cipher state and also for
+ * tracking station state such as the current tx antenna.
+ * We also setup a mapping table between key cache slot indices
+ * and station state to short-circuit node lookups on rx.
+ * Different parts have different size key caches. We handle
+ * up to ATH_KEYMAX entries (could dynamically allocate state).
+ */
+#define ATH_KEYMAX 128 /* max key cache size we handle */
+
+#define ATH_IF_ID_ANY 0xff
+#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
+#define ATH_RSSI_DUMMY_MARKER 0x127
+#define ATH_RATE_DUMMY_MARKER 0
+
+enum PROT_MODE {
+ PROT_M_NONE = 0,
+ PROT_M_RTSCTS,
+ PROT_M_CTSONLY
+};
+
+#define SC_OP_INVALID BIT(0)
+#define SC_OP_BEACONS BIT(1)
+#define SC_OP_RXAGGR BIT(2)
+#define SC_OP_TXAGGR BIT(3)
+#define SC_OP_CHAINMASK_UPDATE BIT(4)
+#define SC_OP_FULL_RESET BIT(5)
+#define SC_OP_NO_RESET BIT(6)
+#define SC_OP_PREAMBLE_SHORT BIT(7)
+#define SC_OP_PROTECT_ENABLE BIT(8)
+#define SC_OP_RXFLUSH BIT(9)
+#define SC_OP_LED_ASSOCIATED BIT(10)
+#define SC_OP_RFKILL_REGISTERED BIT(11)
+#define SC_OP_RFKILL_SW_BLOCKED BIT(12)
+#define SC_OP_RFKILL_HW_BLOCKED BIT(13)
+
+struct arn_softc {
+ ieee80211com_t sc_isc; /* IEEE 802.11 common */
+ dev_info_t *sc_dev; /* back pointer to dev_info_t */
+ ddi_taskq_t *sc_tq; /* private task queue */
+ struct ath_hal *sc_ah;
+ struct ath_config sc_config;
+ caddr_t mem;
+
+ uint8_t sc_isrunning; /* device is operational */
+ uint8_t sc_mrretry; /* multi-rate retry support */
+ uint8_t sc_have11g; /* have 11g support */
+ uint8_t sc_bsync; /* beacon sync */
+
+ ddi_acc_handle_t sc_cfg_handle; /* DDI I/O handle */
+ ddi_acc_handle_t sc_io_handle; /* DDI I/O handle */
+ ddi_acc_handle_t sc_EEPROM_handle; /* DDI I/O handle */
+ ddi_iblock_cookie_t sc_iblock;
+ ddi_softintr_t sc_softint_id;
+
+ /* TX/RX descriptors */
+ struct ath_desc *sc_desc;
+ /* descriptor structure */
+ dma_area_t sc_desc_dma;
+ /* pointer to the first "struct ath_buf" */
+ struct ath_buf *sc_vbufptr;
+ /* length of all allocated "struct ath_buf" */
+ uint32_t sc_vbuflen;
+ /* size of one DMA TX/RX buffer based on 802.11 MTU */
+ int32_t sc_dmabuf_size;
+
+ uint8_t sc_curbssid[6];
+ uint8_t sc_myaddr[6];
+ uint8_t sc_bssidmask[6];
+
+ int sc_debug;
+ uint32_t sc_intrstatus;
+ uint32_t sc_flags; /* SC_OP_* */
+ unsigned int rx_filter;
+ uint16_t sc_curtxpow;
+ uint16_t sc_curaid;
+ uint16_t sc_cachelsz;
+ int sc_slotupdate; /* slot to next advance fsm */
+ int sc_slottime;
+ int sc_bslot[ATH_BCBUF];
+ uint8_t sc_tx_chainmask;
+ uint8_t sc_rx_chainmask;
+ enum ath9k_int sc_imask;
+ enum PROT_MODE sc_protmode;
+
+ uint8_t sc_nbcnvaps; /* # of vaps sending beacons */
+ uint16_t sc_nvaps; /* # of active virtual ap's */
+
+ uint8_t sc_mcastantenna;
+ uint8_t sc_defant; /* current default antenna */
+ uint8_t sc_rxotherant; /* rx's on non-default antenna */
+
+ struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
+ enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
+ enum ath9k_ht_macmode tx_chan_width;
+
+ enum {
+ OK, /* no change needed */
+ UPDATE, /* update pending */
+ COMMIT /* beacon sent, commit change */
+ } sc_updateslot; /* slot time update fsm */
+
+ /* Crypto */
+ uint32_t sc_keymax; /* size of key cache */
+ uint8_t sc_keymap[16]; /* bit map of key cache use */
+ uint8_t sc_splitmic; /* split TKIP MIC keys */
+
+ /* RX */
+ list_t sc_rxbuf_list;
+ int sc_rxbufsize; /* rx size based on mtu */
+ uint32_t *sc_rxlink; /* link ptr in last RX desc */
+ uint32_t sc_rx_pend;
+ uint64_t sc_lastrx; /* tsf at last rx'd frame */
+
+ /* TX */
+ list_t sc_txbuf_list;
+ struct ath_txq sc_txq[ATH9K_NUM_TX_QUEUES];
+ uint32_t sc_txqsetup;
+ int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */
+ uint16_t seq_no; /* TX sequence number */
+
+ /* Beacon */
+ struct ath9k_tx_queue_info sc_beacon_qi;
+ struct ath_txq *sc_cabq;
+ list_t sc_bcbuf_list; /* beacon buffer */
+ uint32_t sc_beaconq;
+ uint32_t sc_bmisscount;
+ uint32_t ast_be_xmit; /* beacons transmitted */
+ uint64_t bc_tstamp;
+ struct ieee80211_beacon_offsets asc_boff; /* dynamic update state */
+
+ /* Rate */
+ struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
+ struct ath_rate_table *sc_currates; /* current rate table */
+ uint8_t asc_rixmap[256]; /* IEEE to h/w rate table ix */
+ uint8_t sc_protrix; /* protection rate index */
+
+ /* mode */
+ enum wireless_mode sc_curmode; /* current phy mode */
+
+ /* Channel, Band */
+ struct ath9k_channel sc_curchan;
+
+ /* Locks */
+ kmutex_t sc_genlock;
+ kmutex_t sc_serial_rw;
+ kmutex_t sc_rxbuflock; /* recv lock */
+ kmutex_t sc_txbuflock; /* txbuf lock */
+ kmutex_t sc_rxflushlock;
+ kmutex_t sc_resetlock;
+ kmutex_t sc_bcbuflock; /* beacon buffer lock */
+ kmutex_t sc_resched_lock;
+ boolean_t sc_resched_needed;
+
+ /* LEDs */
+ struct ath_led radio_led;
+ struct ath_led assoc_led;
+ struct ath_led tx_led;
+ struct ath_led rx_led;
+
+ uint8_t sc_mcast_refs[64]; /* refer count */
+ uint32_t sc_mcast_hash[2]; /* multicast hash table */
+
+ /* Rfkill */
+
+ /* ANI */
+ struct ath_ani sc_ani;
+
+ /* interface statistics */
+ struct ath_stats sc_stats;
+
+ boolean_t sc_promisc; /* Promiscuous mode enabled */
+
+ timeout_id_t sc_scan_timer;
+ timeout_id_t sc_cal_timer;
+
+ int (*sc_newstate)(ieee80211com_t *, enum ieee80211_state, int);
+ void (*sc_recv_mgmt)(ieee80211com_t *, mblk_t *, ieee80211_node_t *,
+ int, int, uint32_t);
+};
+
+int arn_reset(ieee80211com_t *ic);
+
+int arn_get_hal_qnum(uint16_t queue, struct arn_softc *sc);
+
+int ath_cabq_update(struct arn_softc *);
+
+/*
+ * Read and write, they both share the same lock. We do this to serialize
+ * reads and writes on Atheros 802.11n PCI devices only. This is required
+ * as the FIFO on these devices can only accept sanely 2 requests. After
+ * that the device goes bananas. Serializing the reads/writes prevents this
+ * from happening.
+ */
+void
+arn_iowrite32(struct ath_hal *ah, uint32_t reg_offset, uint32_t val);
+unsigned int
+arn_ioread32(struct ath_hal *ah, uint32_t reg_offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARN_CORE_H */
diff --git a/usr/src/uts/common/io/arn/arn_eeprom.c b/usr/src/uts/common/io/arn/arn_eeprom.c
new file mode 100644
index 0000000000..74c9825662
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_eeprom.c
@@ -0,0 +1,2912 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/stream.h>
+#include <sys/termio.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <sys/cmn_err.h>
+#include <sys/stropts.h>
+#include <sys/strsubr.h>
+#include <sys/strtty.h>
+#include <sys/kbio.h>
+#include <sys/cred.h>
+#include <sys/stat.h>
+#include <sys/consdev.h>
+#include <sys/kmem.h>
+#include <sys/modctl.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/pci.h>
+#include <sys/errno.h>
+#include <sys/gld.h>
+#include <sys/dlpi.h>
+#include <sys/ethernet.h>
+#include <sys/list.h>
+#include <sys/byteorder.h>
+#include <sys/strsun.h>
+#include <inet/common.h>
+#include <inet/nd.h>
+#include <inet/mi.h>
+#include <inet/wifi_ioctl.h>
+
+#include "arn_core.h"
+#include "arn_hw.h"
+#include "arn_reg.h"
+#include "arn_phy.h"
+
+static void
+ath9k_hw_analog_shift_rmw(struct ath_hal *ah,
+ uint32_t reg, uint32_t mask,
+ uint32_t shift, uint32_t val)
+{
+ uint32_t regVal;
+
+ regVal = REG_READ(ah, reg) & ~mask;
+ regVal |= (val << shift) & mask;
+
+ REG_WRITE(ah, reg, regVal);
+
+ if (ah->ah_config.analog_shiftreg)
+ drv_usecwait(100);
+}
+
+static inline uint16_t
+ath9k_hw_fbin2freq(uint8_t fbin, boolean_t is2GHz)
+{
+
+ if (fbin == AR5416_BCHAN_UNUSED)
+ return (fbin);
+
+ return ((uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)));
+}
+
+static inline int16_t
+ath9k_hw_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 inline boolean_t
+ath9k_hw_get_lower_upper_index(uint8_t target, uint8_t *pList,
+ uint16_t listSize, uint16_t *indexL, uint16_t *indexR)
+{
+ uint16_t i;
+
+ if (target <= pList[0]) {
+ *indexL = *indexR = 0;
+ return (B_TRUE);
+ }
+ if (target >= pList[listSize - 1]) {
+ *indexL = *indexR = (uint16_t)(listSize - 1);
+ return (B_TRUE);
+ }
+
+ for (i = 0; i < listSize - 1; i++) {
+ if (pList[i] == target) {
+ *indexL = *indexR = i;
+ return (B_TRUE);
+ }
+ if (target < pList[i + 1]) {
+ *indexL = i;
+ *indexR = (uint16_t)(i + 1);
+ return (B_FALSE);
+ }
+ }
+ return (B_FALSE);
+}
+
+static boolean_t
+ath9k_hw_eeprom_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
+{
+ (void) REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+
+ if (!ath9k_hw_wait(ah, AR_EEPROM_STATUS_DATA,
+ AR_EEPROM_STATUS_DATA_BUSY |
+ AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
+ return (B_FALSE);
+ }
+
+ *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
+ AR_EEPROM_STATUS_DATA_VAL);
+
+ return (B_TRUE);
+}
+
+/* ARGSUSED */
+static int
+ath9k_hw_flash_map(struct ath_hal *ah)
+{
+ ARN_DBG((ARN_DBG_EEPROM, "arn: ath9k_hw_flash_map(): "
+ "using flash but eepom\n"));
+
+ return (0);
+}
+
+static boolean_t
+ath9k_hw_flash_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
+{
+ *data = FLASH_READ(ah, off);
+
+ return (B_TRUE);
+}
+
+static inline boolean_t
+ath9k_hw_nvram_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
+{
+ if (ath9k_hw_use_flash(ah))
+ return (ath9k_hw_flash_read(ah, off, data));
+ else
+ return (ath9k_hw_eeprom_read(ah, off, data));
+}
+
+static boolean_t
+ath9k_hw_fill_4k_eeprom(struct ath_hal *ah)
+{
+#define SIZE_EEPROM_4K (sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t))
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ uint16_t *eep_data;
+ int addr, eep_start_loc = 0;
+
+ eep_start_loc = 64;
+
+ if (!ath9k_hw_use_flash(ah)) {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Reading from EEPROM, not flash\n"));
+ }
+
+ eep_data = (uint16_t *)eep;
+
+ for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
+ if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Unable to read eeprom region \n"));
+ return (B_FALSE);
+ }
+ eep_data++;
+ }
+ return (B_TRUE);
+#undef SIZE_EEPROM_4K
+}
+
+static boolean_t
+ath9k_hw_fill_def_eeprom(struct ath_hal *ah)
+{
+#define SIZE_EEPROM_DEF (sizeof (struct ar5416_eeprom_def) / sizeof (uint16_t))
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ uint16_t *eep_data;
+ int addr, ar5416_eep_start_loc = 0x100;
+
+ eep_data = (uint16_t *)eep;
+
+ for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
+ if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
+ eep_data)) {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Unable to read eeprom region\n"));
+ return (B_FALSE);
+ }
+ eep_data++;
+ }
+ return (B_TRUE);
+#undef SIZE_EEPROM_DEF
+}
+
+static boolean_t (*ath9k_fill_eeprom[]) (struct ath_hal *) = {
+ ath9k_hw_fill_def_eeprom,
+ ath9k_hw_fill_4k_eeprom
+};
+
+static inline boolean_t
+ath9k_hw_fill_eeprom(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return (ath9k_fill_eeprom[ahp->ah_eep_map](ah));
+}
+
+static int
+ath9k_hw_check_def_eeprom(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep =
+ (struct ar5416_eeprom_def *)&ahp->ah_eeprom.def;
+ uint16_t *eepdata, temp, magic, magic2;
+ uint32_t sum = 0, el;
+ boolean_t need_swap = B_FALSE;
+ int i, addr, size;
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+ ARN_DBG((ARN_DBG_EEPROM, "arn: "
+ "%s: Reading Magic # failed\n", __func__));
+ return (B_FALSE);
+ }
+
+ if (!ath9k_hw_use_flash(ah)) {
+ ARN_DBG((ARN_DBG_EEPROM, "ath9k: "
+ "%s: Read Magic = 0x%04X\n", __func__, magic));
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ size = sizeof (struct ar5416_eeprom_def);
+ need_swap = B_TRUE;
+ eepdata = (uint16_t *)(&ahp->ah_eeprom);
+
+ for (addr = 0; addr < size / sizeof (uint16_t);
+ addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+
+ ARN_DBG((ARN_DBG_EEPROM,
+ "0x%04X ", *eepdata));
+
+ if (((addr + 1) % 6) == 0)
+ ARN_DBG((ARN_DBG_EEPROM,
+ "arn: "
+ "%s\n", __func__));
+ }
+ } else {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Invalid EEPROM Magic. "
+ "endianness mismatch.\n"));
+ return (EINVAL);
+ }
+ }
+ }
+
+ ARN_DBG((ARN_DBG_EEPROM, "need_swap = %s.\n",
+ need_swap ? "TRUE" : "FALSE"));
+
+ if (need_swap)
+ el = swab16(ahp->ah_eeprom.def.baseEepHeader.length);
+ else
+ el = ahp->ah_eeprom.def.baseEepHeader.length;
+
+ if (el > sizeof (struct ar5416_eeprom_def))
+ el = sizeof (struct ar5416_eeprom_def) / sizeof (uint16_t);
+ else
+ el = el / sizeof (uint16_t);
+
+ eepdata = (uint16_t *)(&ahp->ah_eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ uint32_t integer, j;
+ uint16_t word;
+
+ ARN_DBG((ARN_DBG_EEPROM,
+ "EEPROM Endianness is not native.. Changing \n"));
+
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
+ struct modal_eep_header *pModal =
+ &eep->modalHeader[j];
+ integer = swab32(pModal->antCtrlCommon);
+ pModal->antCtrlCommon = integer;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ integer = swab32(pModal->antCtrlChain[i]);
+ pModal->antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(pModal->spurChans[i].spurChan);
+ pModal->spurChans[i].spurChan = word;
+ }
+ }
+ }
+
+ if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER ||
+ ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ar5416_get_eep_ver(ahp)));
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+ath9k_hw_check_4k_eeprom(struct ath_hal *ah)
+{
+#define EEPROM_4K_SIZE (sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t))
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep =
+ (struct ar5416_eeprom_4k *)&ahp->ah_eeprom.map4k;
+ uint16_t *eepdata, temp, magic, magic2;
+ uint32_t sum = 0, el;
+ boolean_t need_swap = B_FALSE;
+ int i, addr;
+
+
+ if (!ath9k_hw_use_flash(ah)) {
+
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
+ &magic)) {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Reading Magic # failed\n"));
+ return (B_FALSE);
+ }
+
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Read Magic = 0x%04X\n", magic));
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ need_swap = B_TRUE;
+ eepdata = (uint16_t *)(&ahp->ah_eeprom);
+
+ for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+
+ ARN_DBG((ARN_DBG_EEPROM,
+ "0x%04X ", *eepdata));
+
+ if (((addr + 1) % 6) == 0)
+ ARN_DBG((ARN_DBG_EEPROM, "\n"));
+ }
+ } else {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Invalid EEPROM Magic. "
+ "endianness mismatch.\n"));
+ return (EINVAL);
+ }
+ }
+ }
+
+ ARN_DBG((ARN_DBG_EEPROM, "need_swap = %s.\n",
+ need_swap ? "True" : "False"));
+
+ if (need_swap)
+ el = swab16(ahp->ah_eeprom.map4k.baseEepHeader.length);
+ else
+ el = ahp->ah_eeprom.map4k.baseEepHeader.length;
+
+ if (el > sizeof (struct ar5416_eeprom_def))
+ el = sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t);
+ else
+ el = el / sizeof (uint16_t);
+
+ eepdata = (uint16_t *)(&ahp->ah_eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ uint32_t integer;
+ uint16_t word;
+
+ ARN_DBG((ARN_DBG_EEPROM,
+ "EEPROM Endianness is not native.. Changing \n"));
+
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ integer = swab32(eep->modalHeader.antCtrlCommon);
+ eep->modalHeader.antCtrlCommon = integer;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ integer = swab32(eep->modalHeader.antCtrlChain[i]);
+ eep->modalHeader.antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(eep->modalHeader.spurChans[i].spurChan);
+ eep->modalHeader.spurChans[i].spurChan = word;
+ }
+ }
+
+ if (sum != 0xffff || ar5416_get_eep4k_ver(ahp) != AR5416_EEP_VER ||
+ ar5416_get_eep4k_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ar5416_get_eep4k_ver(ahp)));
+ return (EINVAL);
+ }
+
+ return (0);
+#undef EEPROM_4K_SIZE
+}
+
+static int
+(*ath9k_check_eeprom[]) (struct ath_hal *) = {
+ ath9k_hw_check_def_eeprom,
+ ath9k_hw_check_4k_eeprom
+};
+
+static inline int
+ath9k_hw_check_eeprom(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return (ath9k_check_eeprom[ahp->ah_eep_map](ah));
+}
+
+static inline boolean_t
+ath9k_hw_fill_vpd_table(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;
+
+ for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
+ (void) ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
+ numIntercepts, &(idxL), &(idxR));
+ if (idxR < 1)
+ idxR = 1;
+ if (idxL == numIntercepts - 1)
+ idxL = (uint16_t)(numIntercepts - 2);
+ 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]));
+ pRetVpdList[i] = (uint8_t)k;
+ currPwr += 2;
+ }
+
+ return (B_TRUE);
+}
+
+static void
+ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct cal_data_per_freq_4k *pRawDataSet,
+ uint8_t *bChans, uint16_t availPiers,
+ uint16_t tPdGainOverlap, int16_t *pMinCalPower,
+ uint16_t *pPdGainBoundaries, uint8_t *pPDADCValues,
+ uint16_t numXpdGains)
+{
+#define TMP_VAL_VPD_TABLE \
+ ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
+ int i, j, k;
+ int16_t ss;
+ uint16_t idxL = 0, idxR = 0, numPiers;
+ static uint8_t vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static uint8_t vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static uint8_t vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+ uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+ uint8_t minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
+ uint8_t maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
+ int16_t vpdStep;
+ int16_t tmpVal;
+ uint16_t sizeCurrVpdTable, maxIndex, tgtIndex;
+ boolean_t match;
+ int16_t minDelta = 0;
+ struct chan_centers centers;
+#define PD_GAIN_BOUNDARY_DEFAULT 58;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index(
+ (uint8_t)FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan)), bChans, numPiers,
+ &idxL, &idxR);
+
+ if (match) {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+ (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pRawDataSet[idxL].pwrPdg[i],
+ pRawDataSet[idxL].vpdPdg[i],
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableI[i]);
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ pVpdL = pRawDataSet[idxL].vpdPdg[i];
+ pPwrL = pRawDataSet[idxL].pwrPdg[i];
+ pVpdR = pRawDataSet[idxR].vpdPdg[i];
+ pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+ minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+ maxPwrT4[i] =
+ min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
+ pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
+
+
+ (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrL, pVpdL,
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableL[i]);
+ (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrR, pVpdR,
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableR[i]);
+
+ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+ vpdTableI[i][j] =
+ (uint8_t)(ath9k_hw_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;
+
+ 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] =
+ min((uint16_t)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+ if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
+ minDelta = pPdGainBoundaries[0] - 23;
+ pPdGainBoundaries[0] = 23;
+ } else {
+ minDelta = 0;
+ }
+
+ if (i == 0) {
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ss = (int16_t)(0 - (minPwrT4[i] / 2));
+ else
+ ss = 0;
+ } else {
+ ss = (int16_t)((pPdGainBoundaries[i - 1] -
+ (minPwrT4[i] / 2)) -
+ tPdGainOverlap + 1 + minDelta);
+ }
+ vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+ pPDADCValues[k++] =
+ (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);
+
+ if (tgtIndex > maxIndex) {
+ while ((ss <= tgtIndex) &&
+ (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)TMP_VAL_VPD_TABLE;
+ pPDADCValues[k++] = (uint8_t)
+ ((tmpVal > 255) ? 255 : tmpVal);
+ ss++;
+ }
+ }
+ }
+
+ while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
+ pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
+ i++;
+ }
+
+ while (k < AR5416_NUM_PDADC_VALUES) {
+ pPDADCValues[k] = pPDADCValues[k - 1];
+ k++;
+ }
+
+ return;
+#undef TMP_VAL_VPD_TABLE
+}
+
+static void
+ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct 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;
+ uint16_t idxL = 0, idxR = 0, numPiers;
+ static uint8_t vpdTableL[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static uint8_t vpdTableR[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ 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;
+ boolean_t match;
+ int16_t minDelta = 0;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+ }
+
+ match =
+ ath9k_hw_get_lower_upper_index(
+ (uint8_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+ bChans, numPiers, &idxL, &idxR);
+
+ if (match) {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+ (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pRawDataSet[idxL].pwrPdg[i],
+ pRawDataSet[idxL].vpdPdg[i],
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableI[i]);
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ pVpdL = pRawDataSet[idxL].vpdPdg[i];
+ pPwrL = pRawDataSet[idxL].pwrPdg[i];
+ pVpdR = pRawDataSet[idxR].vpdPdg[i];
+ pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+ minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+ maxPwrT4[i] =
+ min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
+ pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
+
+
+ (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrL, pVpdL,
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableL[i]);
+ (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrR, pVpdR,
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableR[i]);
+
+ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+ vpdTableI[i][j] =
+ (uint8_t)(ath9k_hw_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;
+
+ 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] =
+ min((uint16_t)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+ if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
+ minDelta = pPdGainBoundaries[0] - 23;
+ pPdGainBoundaries[0] = 23;
+ } else {
+ minDelta = 0;
+ }
+
+ if (i == 0) {
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ss = (int16_t)(0 - (minPwrT4[i] / 2));
+ else
+ ss = 0;
+ } else {
+ ss = (int16_t)((pPdGainBoundaries[i - 1] -
+ (minPwrT4[i] / 2)) -
+ tPdGainOverlap + 1 + minDelta);
+ }
+ vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+ pPDADCValues[k++] =
+ (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);
+
+ if (tgtIndex > maxIndex) {
+ while ((ss <= tgtIndex) &&
+ (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal =
+ (int16_t)
+ ((vpdTableI[i][sizeCurrVpdTable - 1] +
+ (ss - maxIndex + 1) * vpdStep));
+ pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ?
+ 255 : tmpVal);
+ ss++;
+ }
+ }
+ }
+
+ while (i < AR5416_PD_GAINS_IN_MASK) {
+ pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
+ i++;
+ }
+
+ while (k < AR5416_NUM_PDADC_VALUES) {
+ pPDADCValues[k] = pPDADCValues[k - 1];
+ k++;
+ }
+}
+
+static void
+ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_leg *powInfo,
+ uint16_t numChannels,
+ struct cal_target_power_leg *pNewPower,
+ uint16_t numRates, boolean_t isExtTarget)
+{
+ struct chan_centers centers;
+ uint16_t clo, chi;
+ int i;
+ int matchIndex = -1, lowIndex = -1;
+ uint16_t freq;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
+
+ if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = 0;
+ } else {
+ for (i = 0; (i < numChannels) &&
+ (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = i;
+ break;
+ } else if ((freq <
+ ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) &&
+ (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+ IS_CHAN_2GHZ(chan)))) {
+ lowIndex = i - 1;
+ break;
+ }
+ }
+ if ((matchIndex == -1) && (lowIndex == -1))
+ matchIndex = i - 1;
+ }
+
+ if (matchIndex != -1) {
+ *pNewPower = powInfo[matchIndex];
+ } else {
+ clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+ IS_CHAN_2GHZ(chan));
+ chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+ IS_CHAN_2GHZ(chan));
+
+ for (i = 0; i < numRates; i++) {
+ pNewPower->tPow2x[i] =
+ (uint8_t)ath9k_hw_interpolate(freq, clo, chi,
+ powInfo[lowIndex].tPow2x[i],
+ powInfo[lowIndex + 1].tPow2x[i]);
+ }
+ }
+}
+
+static void
+ath9k_hw_get_target_powers(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_ht *powInfo,
+ uint16_t numChannels,
+ struct cal_target_power_ht *pNewPower,
+ uint16_t numRates, boolean_t isHt40Target)
+{
+ struct chan_centers centers;
+ uint16_t clo, chi;
+ int i;
+ int matchIndex = -1, lowIndex = -1;
+ uint16_t freq;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+
+ if (freq <=
+ ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+ matchIndex = 0;
+ } else {
+ for (i = 0; (i < numChannels) &&
+ (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = i;
+ break;
+ } else
+ if ((freq <
+ ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) &&
+ (freq > ath9k_hw_fbin2freq
+ (powInfo[i - 1].bChannel,
+ IS_CHAN_2GHZ(chan)))) {
+ lowIndex = i - 1;
+ break;
+ }
+ }
+ if ((matchIndex == -1) && (lowIndex == -1))
+ matchIndex = i - 1;
+ }
+
+ if (matchIndex != -1) {
+ *pNewPower = powInfo[matchIndex];
+ } else {
+ clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+ IS_CHAN_2GHZ(chan));
+ chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+ IS_CHAN_2GHZ(chan));
+
+ for (i = 0; i < numRates; i++) {
+ pNewPower->tPow2x[i] =
+ (uint8_t)ath9k_hw_interpolate(freq,
+ clo, chi,
+ powInfo[lowIndex].tPow2x[i],
+ powInfo[lowIndex + 1].tPow2x[i]);
+ }
+ }
+}
+
+static uint16_t
+ath9k_hw_get_max_edge_power(uint16_t freq,
+ struct cal_ctl_edges *pRdEdgesPower,
+ boolean_t is2GHz, int num_band_edges)
+{
+ uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ int i;
+
+ for (i = 0; (i < num_band_edges) &&
+ (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
+ is2GHz)) {
+ twiceMaxEdgePower = pRdEdgesPower[i].tPower;
+ break;
+ } else if ((i > 0) &&
+ (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
+ is2GHz))) {
+ if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
+ is2GHz) < freq &&
+ pRdEdgesPower[i - 1].flag) {
+ twiceMaxEdgePower =
+ pRdEdgesPower[i - 1].tPower;
+ }
+ break;
+ }
+ }
+
+ return (twiceMaxEdgePower);
+}
+
+static boolean_t
+ath9k_hw_set_def_power_cal_table(struct ath_hal *ah,
+ struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
+ struct cal_data_per_freq *pRawDataset;
+ uint8_t *pCalBChans = 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] = { 0, 0, 0, 0 };
+ uint32_t reg32, regOffset, regChainOffset;
+ int16_t modalIdx;
+
+ modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
+ xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader[modalIdx].pdGainOverlap;
+ } else {
+ pdGainOverlap_t2 =
+ (uint16_t)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_NUM_2G_CAL_PIERS;
+ } else {
+ pCalBChans = pEepData->calFreqPier5G;
+ numPiers = AR5416_NUM_5G_CAL_PIERS;
+ }
+
+ numXpdGain = 0;
+
+ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+ xpdGainValues[2]);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_V20_OR_LATER(ah) &&
+ (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
+ (i != 0)) {
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ } else
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ if (IS_CHAN_2GHZ(chan))
+ pRawDataset = pEepData->calPierData2G[i];
+ else
+ pRawDataset = pEepData->calPierData5G[i];
+
+ ath9k_hw_get_def_gain_boundaries_pdadcs(ah, chan,
+ pRawDataset, pCalBChans,
+ numPiers, pdGainOverlap_t2,
+ &tMinCalPower, gainBoundaries,
+ pdadcValues, numXpdGain);
+
+ if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+ SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
+ SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
+ SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
+ SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+ }
+
+ regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+ ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+ ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+ ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ REG_WRITE(ah, regOffset, reg32);
+
+ ARN_DBG((ARN_DBG_REG_IO,
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "PDADC: Chain %d | PDADC %3d "
+ "Value %3d | PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | PDADC %3d "
+ "Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1, pdadcValues[4 * j + 1],
+ 4 * j + 2, pdadcValues[4 * j + 2],
+ 4 * j + 3,
+ pdadcValues[4 * j + 3]));
+
+ regOffset += 4;
+ }
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+
+ return (B_TRUE);
+}
+
+static boolean_t
+ath9k_hw_set_4k_power_cal_table(struct ath_hal *ah,
+ struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
+ struct cal_data_per_freq_4k *pRawDataset;
+ uint8_t *pCalBChans = 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] = { 0, 0, 0, 0 };
+ uint32_t reg32, regOffset, regChainOffset;
+
+ xpdMask = pEepData->modalHeader.xpdGain;
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader.pdGainOverlap;
+ } else {
+ pdGainOverlap_t2 = (uint16_t)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+ }
+
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_NUM_2G_CAL_PIERS;
+
+ numXpdGain = 0;
+
+ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+ xpdGainValues[2]);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_V20_OR_LATER(ah) &&
+ (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
+ (i != 0)) {
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ } else
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ pRawDataset = pEepData->calPierData2G[i];
+
+ ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
+ pRawDataset, pCalBChans,
+ numPiers, pdGainOverlap_t2,
+ &tMinCalPower, gainBoundaries,
+ pdadcValues, numXpdGain);
+
+ if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+ SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
+ SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
+ SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
+ SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+ }
+
+ regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+ ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+ ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+ ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ REG_WRITE(ah, regOffset, reg32);
+
+ ARN_DBG((ARN_DBG_REG_IO,
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "PDADC: Chain %d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1, pdadcValues[4 * j + 1],
+ 4 * j + 2, pdadcValues[4 * j + 2],
+ 4 * j + 3,
+ pdadcValues[4 * j + 3]));
+
+ regOffset += 4;
+ }
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+
+ return (B_TRUE);
+}
+
+static boolean_t
+ath9k_hw_set_def_power_per_rate_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ uint16_t cfgCtl,
+ uint16_t AntennaReduction,
+ uint16_t twiceMaxRegulatoryPower,
+ uint16_t powerLimit)
+{
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
+ uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ static const uint16_t tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+
+ int i;
+ int8_t twiceLargestAntenna;
+ struct cal_ctl_data *rep;
+ struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 0, { 0, 0, 0, 0}
+ };
+ struct cal_target_power_leg targetPowerOfdmExt = {
+ 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+ 0, { 0, 0, 0, 0 }
+ };
+ struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 0, {0, 0, 0, 0}
+ };
+ uint16_t scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ uint16_t ctlModesFor11a[] =
+ { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
+ uint16_t ctlModesFor11g[] =
+ { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+ CTL_2GHT40
+ };
+ uint16_t numCtlModes, *pCtlMode, ctlMode, freq;
+ struct chan_centers centers;
+ int tx_chainmask;
+ uint16_t twiceMinEdgePower;
+
+ tx_chainmask = ahp->ah_txchainmask;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = max(
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+
+ twiceLargestAntenna =
+ max((uint8_t)twiceLargestAntenna,
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+
+ twiceLargestAntenna =
+ (int16_t)min(AntennaReduction - twiceLargestAntenna, 0);
+
+ maxRegAllowedPower =
+ twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+ if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+
+ switch (ar5416_get_ntxchains(tx_chainmask)) {
+ case 1:
+ break;
+ case 2:
+ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+ break;
+ case 3:
+ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+ break;
+ }
+
+ scaledPower = max((uint16_t)0, scaledPower);
+
+ if (IS_CHAN_2GHZ(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
+ SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, B_FALSE);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, B_FALSE);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, B_FALSE);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, B_TRUE);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, B_TRUE);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, B_TRUE);
+ }
+ } else {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+ SUB_NUM_CTL_MODES_AT_5G_40;
+ pCtlMode = ctlModesFor11a;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, B_FALSE);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower5GHT20,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, B_FALSE);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower5GHT40,
+ AR5416_NUM_5G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, B_TRUE);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, B_TRUE);
+ }
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ boolean_t isHt40CtlMode =
+ (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ar5416_get_eep_ver(ahp) == 14 &&
+ ar5416_get_eep_rev(ahp) <= 2)
+ twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+ ARN_DBG((ARN_DBG_EEPROM, "arn: "
+ "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
+ "EXT_ADDITIVE %d\n",
+ ctlMode, numCtlModes, isHt40CtlMode,
+ (pCtlMode[ctlMode] & EXT_ADDITIVE)));
+
+ for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i];
+ i++) {
+
+ ARN_DBG((ARN_DBG_EEPROM, "arn: "
+ "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
+ "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
+ "chan %d\n",
+ i, cfgCtl, pCtlMode[ctlMode],
+ pEepData->ctlIndex[i], chan->channel));
+
+ if ((((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ pEepData->ctlIndex[i]) ||
+ (((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) |
+ SD_NO_CTL))) {
+ rep = &(pEepData->ctlData[i]);
+
+ twiceMinEdgePower =
+ ath9k_hw_get_max_edge_power(freq,
+ rep->ctlEdges[ar5416_get_ntxchains
+ (tx_chainmask) - 1],
+ IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
+
+ ARN_DBG((ARN_DBG_EEPROM, "arn: "
+ "MATCH-EE_IDX %d: ch %d is2 %d "
+ "2xMinEdge %d chainmask %d chains %d\n",
+ i, freq, IS_CHAN_2GHZ(chan),
+ twiceMinEdgePower, tx_chainmask,
+ ar5416_get_ntxchains(tx_chainmask)));
+
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower =
+ min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = min(twiceMaxEdgePower, scaledPower);
+
+ ARN_DBG((ARN_DBG_EEPROM, "arn: "
+ "SEL-Min ctlMode %d pCtlMode %d "
+ "2xMaxEdge %d sP %d minCtlPwr %d\n",
+ ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+ scaledPower, minCtlPower));
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
+ i++) {
+ targetPowerCck.tPow2x[i] =
+ min((uint16_t)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11A:
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
+ i++) {
+ targetPowerOfdm.tPow2x[i] =
+ min((uint16_t)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_5GHT20:
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
+ i++) {
+ targetPowerHt20.tPow2x[i] =
+ min((uint16_t)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] =
+ min((uint16_t)targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11A_EXT:
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] =
+ min((uint16_t)targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_5GHT40:
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
+ i++) {
+ targetPowerHt40.tPow2x[i] =
+ min((uint16_t)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+ ratesArray[rate18mb] = ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] =
+ targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] =
+ targetPowerCck.tPow2x[2];
+ ;
+ ratesArray[rate11s] = ratesArray[rate11l] =
+ targetPowerCck.tPow2x[3];
+ ;
+ }
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ ratesArray[rateHt40_0 + i] =
+ targetPowerHt40.tPow2x[i];
+ }
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rateExtCck] =
+ targetPowerCckExt.tPow2x[0];
+ }
+ }
+ return (B_TRUE);
+}
+
+static boolean_t
+ath9k_hw_set_4k_power_per_rate_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ uint16_t cfgCtl,
+ uint16_t AntennaReduction,
+ uint16_t twiceMaxRegulatoryPower,
+ uint16_t powerLimit)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
+ uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ static const uint16_t tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+
+ int i;
+ int16_t twiceLargestAntenna;
+ struct cal_ctl_data_4k *rep;
+ struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 0, { 0, 0, 0, 0}
+ };
+ struct cal_target_power_leg targetPowerOfdmExt = {
+ 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+ 0, { 0, 0, 0, 0 }
+ };
+ struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 0, {0, 0, 0, 0}
+ };
+ uint16_t scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ uint16_t ctlModesFor11g[] =
+ { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+ CTL_2GHT40
+ };
+ uint16_t numCtlModes, *pCtlMode, ctlMode, freq;
+ struct chan_centers centers;
+ int tx_chainmask;
+ uint16_t twiceMinEdgePower;
+
+ tx_chainmask = ahp->ah_txchainmask;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
+
+ twiceLargestAntenna =
+ (int16_t)min(AntennaReduction - twiceLargestAntenna, 0);
+
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+ if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = max((uint16_t)0, scaledPower);
+
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, B_FALSE);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, B_FALSE);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, B_FALSE);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, B_TRUE);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, B_TRUE);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, B_TRUE);
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ boolean_t isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ar5416_get_eep_ver(ahp) == 14 &&
+ ar5416_get_eep_rev(ahp) <= 2)
+ twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+ ARN_DBG((ARN_DBG_POWER_MGMT,
+ "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
+ "EXT_ADDITIVE %d\n",
+ ctlMode, numCtlModes, isHt40CtlMode,
+ (pCtlMode[ctlMode] & EXT_ADDITIVE)));
+
+ for (i = 0; (i < AR5416_NUM_CTLS) &&
+ pEepData->ctlIndex[i]; i++) {
+ ARN_DBG((ARN_DBG_POWER_MGMT,
+ " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
+ "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
+ "chan %d\n",
+ i, cfgCtl, pCtlMode[ctlMode],
+ pEepData->ctlIndex[i], chan->channel));
+
+ if ((((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ pEepData->ctlIndex[i]) ||
+ (((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) |
+ SD_NO_CTL))) {
+ rep = &(pEepData->ctlData[i]);
+
+ twiceMinEdgePower =
+ ath9k_hw_get_max_edge_power(freq,
+ rep->ctlEdges[ar5416_get_ntxchains
+ (tx_chainmask) - 1],
+ IS_CHAN_2GHZ(chan),
+ AR5416_EEP4K_NUM_BAND_EDGES);
+
+ ARN_DBG((ARN_DBG_POWER_MGMT,
+ " MATCH-EE_IDX %d: ch %d is2 %d "
+ "2xMinEdge %d chainmask %d chains %d\n",
+ i, freq, IS_CHAN_2GHZ(chan),
+ twiceMinEdgePower, tx_chainmask,
+ ar5416_get_ntxchains
+ (tx_chainmask)));
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower =
+ min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = (uint8_t)min(twiceMaxEdgePower, scaledPower);
+
+ ARN_DBG((ARN_DBG_POWER_MGMT,
+ " SEL-Min ctlMode %d pCtlMode %d "
+ "2xMaxEdge %d sP %d minCtlPwr %d\n",
+ ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+ scaledPower, minCtlPower));
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
+ i++) {
+ targetPowerCck.tPow2x[i] =
+ min((uint16_t)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
+ i++) {
+ targetPowerOfdm.tPow2x[i] =
+ min((uint16_t)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
+ i++) {
+ targetPowerHt20.tPow2x[i] =
+ min((uint16_t)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] = min((uint16_t)
+ targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] = min((uint16_t)
+ targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
+ i++) {
+ targetPowerHt40.tPow2x[i] =
+ min((uint16_t)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+ ratesArray[rate18mb] = ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+ ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ ratesArray[rateHt40_0 + i] =
+ targetPowerHt40.tPow2x[i];
+ }
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+ }
+ return (B_TRUE);
+}
+
+static int
+ath9k_hw_def_set_txpower(struct ath_hal *ah, struct ath9k_channel *chan,
+ uint16_t cfgCtl, uint8_t twiceAntennaReduction,
+ uint8_t twiceMaxRegulatoryPower, uint8_t powerLimit)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
+ struct modal_eep_header *pModal =
+ &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ uint8_t ht40PowerIncForPdadc = 2;
+ int i;
+
+ (void) memset(ratesArray, 0, sizeof (ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+ }
+
+ if (!ath9k_hw_set_def_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit)) {
+
+ ARN_DBG((ARN_DBG_EEPROM,
+ "ath9k_hw_set_txpower: unable to set "
+ "tx power per rate table\n"));
+
+ return (EIO);
+ }
+
+ if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) {
+ ARN_DBG((ARN_DBG_EEPROM, "ath9k: "
+ "ath9k_hw_set_txpower: unable to set power table\n"));
+ return (EIO);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+ ratesArray[i] = AR5416_MAX_RATE_POWER;
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24) |
+ ATH9K_POW_SM(ratesArray[rate12mb], 16) |
+ ATH9K_POW_SM(ratesArray[rate9mb], 8) |
+ ATH9K_POW_SM(ratesArray[rate6mb], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24) |
+ ATH9K_POW_SM(ratesArray[rate48mb], 16) |
+ ATH9K_POW_SM(ratesArray[rate36mb], 8) |
+ ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24) |
+ ATH9K_POW_SM(ratesArray[rate2l], 16) |
+ ATH9K_POW_SM(ratesArray[rateXr], 8) |
+ ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24) |
+ ATH9K_POW_SM(ratesArray[rate11l], 16) |
+ ATH9K_POW_SM(ratesArray[rate5_5s], 8) |
+ ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24) |
+ ATH9K_POW_SM(ratesArray[rateHt20_2], 16) |
+ ATH9K_POW_SM(ratesArray[rateHt20_1], 8) |
+ ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24) |
+ ATH9K_POW_SM(ratesArray[rateHt20_6], 16) |
+ ATH9K_POW_SM(ratesArray[rateHt20_5], 8) |
+ ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ if (IS_CHAN_HT40(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24) |
+ ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16) |
+ ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8) |
+ ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24) |
+ ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16) |
+ ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8) |
+ ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
+ ATH9K_POW_SM(ratesArray[rateExtCck], 16) |
+ ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
+ ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+ ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) |
+ ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+
+ i = rate6mb;
+
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ah->ah_maxPowerLevel =
+ ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
+ else
+ ah->ah_maxPowerLevel = ratesArray[i];
+
+ return (0);
+}
+
+static int
+ath9k_hw_4k_set_txpower(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ uint16_t cfgCtl,
+ uint8_t twiceAntennaReduction,
+ uint8_t twiceMaxRegulatoryPower,
+ uint8_t powerLimit)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ uint8_t ht40PowerIncForPdadc = 2;
+ int i;
+
+ (void) memset(ratesArray, 0, sizeof (ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+ }
+
+ if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit)) {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "ath9k_hw_set_txpower: unable to set "
+ "tx power per rate table\n"));
+ return (EIO);
+ }
+
+ if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) {
+ ARN_DBG((ARN_DBG_EEPROM,
+ "ath9k_hw_set_txpower: unable to set power table\n"));
+ return (EIO);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+ ratesArray[i] = AR5416_MAX_RATE_POWER;
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24) |
+ ATH9K_POW_SM(ratesArray[rate12mb], 16) |
+ ATH9K_POW_SM(ratesArray[rate9mb], 8) |
+ ATH9K_POW_SM(ratesArray[rate6mb], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24) |
+ ATH9K_POW_SM(ratesArray[rate48mb], 16) |
+ ATH9K_POW_SM(ratesArray[rate36mb], 8) |
+ ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24) |
+ ATH9K_POW_SM(ratesArray[rate2l], 16) |
+ ATH9K_POW_SM(ratesArray[rateXr], 8) |
+ ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24) |
+ ATH9K_POW_SM(ratesArray[rate11l], 16) |
+ ATH9K_POW_SM(ratesArray[rate5_5s], 8) |
+ ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24) |
+ ATH9K_POW_SM(ratesArray[rateHt20_2], 16) |
+ ATH9K_POW_SM(ratesArray[rateHt20_1], 8) |
+ ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24) |
+ ATH9K_POW_SM(ratesArray[rateHt20_6], 16) |
+ ATH9K_POW_SM(ratesArray[rateHt20_5], 8) |
+ ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ if (IS_CHAN_HT40(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24) |
+ ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16) |
+ ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8) |
+ ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24) |
+ ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16) |
+ ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8) |
+ ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
+ ATH9K_POW_SM(ratesArray[rateExtCck], 16) |
+ ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
+ ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+
+ i = rate6mb;
+
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ah->ah_maxPowerLevel =
+ ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
+ else
+ ah->ah_maxPowerLevel = ratesArray[i];
+
+ return (0);
+}
+
+int
+ath9k_hw_set_txpower(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ uint16_t cfgCtl,
+ uint8_t twiceAntennaReduction,
+ uint8_t twiceMaxRegulatoryPower,
+ uint8_t powerLimit)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int val;
+
+ if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
+ val = ath9k_hw_def_set_txpower(ah, chan, cfgCtl,
+ twiceAntennaReduction, twiceMaxRegulatoryPower,
+ powerLimit);
+ else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ val = ath9k_hw_4k_set_txpower(ah, chan, cfgCtl,
+ twiceAntennaReduction, twiceMaxRegulatoryPower,
+ powerLimit);
+ return (val);
+}
+
+static void
+ath9k_hw_set_def_addac(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
+ struct modal_eep_header *pModal;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ uint8_t biaslevel;
+
+ if (ah->ah_macVersion != AR_SREV_VERSION_9160)
+ return;
+
+ if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
+ return;
+
+ pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+ if (pModal->xpaBiasLvl != 0xff) {
+ biaslevel = pModal->xpaBiasLvl;
+ } else {
+ uint16_t resetFreqBin, freqBin, freqCount = 0;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ resetFreqBin =
+ FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan));
+ freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
+ biaslevel = (uint8_t)(XPA_LVL_FREQ(0) >> 14);
+
+ freqCount++;
+
+ while (freqCount < 3) {
+ if (XPA_LVL_FREQ(freqCount) == 0x0)
+ break;
+
+ freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
+ if (resetFreqBin >= freqBin) {
+ biaslevel =
+ (uint8_t)
+ (XPA_LVL_FREQ(freqCount) >> 14);
+ } else {
+ break;
+ }
+ freqCount++;
+ }
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ INI_RA(&ahp->ah_iniAddac, 7, 1) =
+ (INI_RA(&ahp->ah_iniAddac, 7, 1) &
+ (~0x18)) | biaslevel << 3;
+ } else {
+ INI_RA(&ahp->ah_iniAddac, 6, 1) =
+ (INI_RA(&ahp->ah_iniAddac, 6, 1) &
+ (~0xc0)) | biaslevel << 6;
+ }
+#undef XPA_LVL_FREQ
+}
+
+/* ARGSUSED */
+static void
+ath9k_hw_set_4k_addac(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct modal_eep_4k_header *pModal;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ uint8_t biaslevel;
+
+ if (ah->ah_macVersion != AR_SREV_VERSION_9160)
+ return;
+
+ if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
+ return;
+
+ pModal = &eep->modalHeader;
+
+ if (pModal->xpaBiasLvl != 0xff) {
+ biaslevel = pModal->xpaBiasLvl;
+ INI_RA(&ahp->ah_iniAddac, 7, 1) =
+ (INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) |
+ biaslevel << 3;
+ }
+}
+
+void
+ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
+ ath9k_hw_set_def_addac(ah, chan);
+ else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ ath9k_hw_set_4k_addac(ah, chan);
+}
+
+/* XXX: Clean me up, make me more legible */
+static boolean_t
+ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_header *pModal;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ int i, regChainOffset;
+ uint8_t txRxAttenLocal;
+ uint16_t ant_config;
+
+ pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+ txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
+
+ (void) ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_9280(ah)) {
+ if (i >= 2)
+ break;
+ }
+
+ if (AR_SREV_5416_V20_OR_LATER(ah) &&
+ (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
+ (i != 0))
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ else
+ regChainOffset = i * 0x1000;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+ pModal->antCtrlChain[i]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
+ ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
+ if ((eep->baseEepHeader.version &
+ AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[i];
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ pModal->
+ bswMargin[i]);
+ REG_RMW_FIELD(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ pModal->
+ bswAtten[i]);
+ REG_RMW_FIELD(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->
+ xatten2Margin[i]);
+ REG_RMW_FIELD(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ pModal->
+ xatten2Db[i]);
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
+ | SM(pModal->
+ bswMargin[i],
+ AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+ REG_WRITE(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
+ | SM(pModal->bswAtten[i],
+ AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+ }
+ }
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah,
+ AR_PHY_RXGAIN +
+ regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN,
+ txRxAttenLocal);
+ REG_RMW_FIELD(ah,
+ AR_PHY_RXGAIN +
+ regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN,
+ pModal->rxTxMarginCh[i]);
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_RXGAIN + regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_RXGAIN +
+ regChainOffset) &
+ ~AR_PHY_RXGAIN_TXRX_ATTEN) |
+ SM(txRxAttenLocal,
+ AR_PHY_RXGAIN_TXRX_ATTEN));
+ REG_WRITE(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+ SM(pModal->rxTxMarginCh[i],
+ AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+ }
+ }
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (IS_CHAN_2GHZ(chan)) {
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+ AR_AN_RF2G1_CH0_OB,
+ AR_AN_RF2G1_CH0_OB_S,
+ pModal->ob);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+ AR_AN_RF2G1_CH0_DB,
+ AR_AN_RF2G1_CH0_DB_S,
+ pModal->db);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+ AR_AN_RF2G1_CH1_OB,
+ AR_AN_RF2G1_CH1_OB_S,
+ pModal->ob_ch1);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+ AR_AN_RF2G1_CH1_DB,
+ AR_AN_RF2G1_CH1_DB_S,
+ pModal->db_ch1);
+ } else {
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+ AR_AN_RF5G1_CH0_OB5,
+ AR_AN_RF5G1_CH0_OB5_S,
+ pModal->ob);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+ AR_AN_RF5G1_CH0_DB5,
+ AR_AN_RF5G1_CH0_DB5_S,
+ pModal->db);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+ AR_AN_RF5G1_CH1_OB5,
+ AR_AN_RF5G1_CH1_OB5_S,
+ pModal->ob_ch1);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+ AR_AN_RF5G1_CH1_DB5,
+ AR_AN_RF5G1_CH1_DB5_S,
+ pModal->db_ch1);
+ }
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+ AR_AN_TOP2_XPABIAS_LVL,
+ AR_AN_TOP2_XPABIAS_LVL_S,
+ pModal->xpaBiasLvl);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+ AR_AN_TOP2_LOCALBIAS,
+ AR_AN_TOP2_LOCALBIAS_S,
+ pModal->local_bias);
+
+ ARN_DBG((ARN_DBG_EEPROM, "arn: "
+ "ForceXPAon: %d\n", pModal->force_xpaon));
+
+ REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
+ pModal->force_xpaon);
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+ pModal->switchSettling);
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+ pModal->adcDesiredSize);
+
+ if (!AR_SREV_9280_10_OR_LATER(ah))
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_PGA,
+ pModal->pgaDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+ AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+ } else {
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+ AR_PHY_EXT_CCA_THRESH62,
+ pModal->thresh62);
+ }
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+ pModal->swSettleHt40);
+ }
+
+ return (B_TRUE);
+}
+
+static boolean_t
+ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_4k_header *pModal;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ int regChainOffset;
+ uint8_t txRxAttenLocal;
+ uint16_t ant_config = 0;
+ uint8_t ob[5], db1[5], db2[5];
+ uint8_t ant_div_control1, ant_div_control2;
+ uint32_t regVal;
+
+
+ pModal = &eep->modalHeader;
+
+ txRxAttenLocal = 23;
+
+ (void) ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+
+ regChainOffset = 0;
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+ pModal->antCtrlChain[0]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
+ ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[0];
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->xatten2Margin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+
+ if (AR_SREV_9285_11(ah))
+ REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
+
+ /* Initialize Ant Diversity settings from EEPROM */
+ if (pModal->version == 3) {
+ ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
+ ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
+ regVal = REG_READ(ah, 0x99ac);
+ regVal &= (~(0x7f000000));
+ regVal |= ((ant_div_control1 & 0x1) << 24);
+ regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
+ regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
+ regVal |= ((ant_div_control2 & 0x3) << 25);
+ regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
+ REG_WRITE(ah, 0x99ac, regVal);
+ regVal = REG_READ(ah, 0x99ac);
+ regVal = REG_READ(ah, 0xa208);
+ regVal &= (~(0x1 << 13));
+ regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
+ REG_WRITE(ah, 0xa208, regVal);
+ regVal = REG_READ(ah, 0xa208);
+ }
+
+ if (pModal->version >= 2) {
+ ob[0] = (pModal->ob_01 & 0xf);
+ ob[1] = (pModal->ob_01 >> 4) & 0xf;
+ ob[2] = (pModal->ob_234 & 0xf);
+ ob[3] = ((pModal->ob_234 >> 4) & 0xf);
+ ob[4] = ((pModal->ob_234 >> 8) & 0xf);
+
+ db1[0] = (pModal->db1_01 & 0xf);
+ db1[1] = ((pModal->db1_01 >> 4) & 0xf);
+ db1[2] = (pModal->db1_234 & 0xf);
+ db1[3] = ((pModal->db1_234 >> 4) & 0xf);
+ db1[4] = ((pModal->db1_234 >> 8) & 0xf);
+
+ db2[0] = (pModal->db2_01 & 0xf);
+ db2[1] = ((pModal->db2_01 >> 4) & 0xf);
+ db2[2] = (pModal->db2_234 & 0xf);
+ db2[3] = ((pModal->db2_234 >> 4) & 0xf);
+ db2[4] = ((pModal->db2_234 >> 8) & 0xf);
+
+ } else if (pModal->version == 1) {
+
+ ARN_DBG((ARN_DBG_EEPROM,
+ "EEPROM Model version is set to 1 \n"));
+ ob[0] = (pModal->ob_01 & 0xf);
+ ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
+ db1[0] = (pModal->db1_01 & 0xf);
+ db1[1] = db1[2] = db1[3] = db1[4] =
+ ((pModal->db1_01 >> 4) & 0xf);
+ db2[0] = (pModal->db2_01 & 0xf);
+ db2[1] = db2[2] = db2[3] = db2[4] =
+ ((pModal->db2_01 >> 4) & 0xf);
+ } else {
+ int i;
+ for (i = 0; i < 5; i++) {
+ ob[i] = pModal->ob_01;
+ db1[i] = pModal->db1_01;
+ db2[i] = pModal->db1_01;
+ }
+ }
+
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
+
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
+
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
+
+
+ if (AR_SREV_9285_11(ah))
+ REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+ pModal->switchSettling);
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+ pModal->adcDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
+ }
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ boolean_t val;
+
+ if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
+ val = ath9k_hw_eeprom_set_def_board_values(ah, chan);
+ else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ val = ath9k_hw_eeprom_set_4k_board_values(ah, chan);
+
+ return (val);
+}
+
+static int
+ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ uint8_t index, uint16_t *config)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ struct modal_eep_header *pModal =
+ &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+
+ switch (index) {
+ case 0:
+ *config = pModal->antCtrlCommon & 0xFFFF;
+ return (0);
+ case 1:
+ if (pBase->version >= 0x0E0D) {
+ if (pModal->useAnt1) {
+ *config =
+ ((pModal->antCtrlCommon & 0xFFFF0000)
+ >> 16);
+ return (0);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return (-EINVAL);
+}
+
+/* ARGSUSED */
+static int
+ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ uint8_t index, uint16_t *config)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &eep->modalHeader;
+
+ switch (index) {
+ case 0:
+ *config = pModal->antCtrlCommon & 0xFFFF;
+ return (0);
+ default:
+ break;
+ }
+
+ return (EINVAL);
+}
+
+int
+ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ uint8_t index, uint16_t *config)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int val;
+
+ if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
+ val = ath9k_hw_get_def_eeprom_antenna_cfg(ah, chan,
+ index, config);
+ else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ val = ath9k_hw_get_4k_eeprom_antenna_cfg(ah, chan,
+ index, config);
+
+ return (val);
+}
+
+/* ARGSUSED */
+static uint8_t
+ath9k_hw_get_4k_num_ant_config(struct ath_hal *ah,
+ enum ath9k_band freq_band)
+{
+ return (1);
+}
+
+static uint8_t
+ath9k_hw_get_def_num_ant_config(struct ath_hal *ah,
+ enum ath9k_band freq_band)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+
+ struct modal_eep_header *pModal =
+ &(eep->modalHeader[ATH9K_BAND_5GHZ == freq_band]);
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+ uint8_t num_ant_config;
+
+ num_ant_config = 1;
+
+ if (pBase->version >= 0x0E0D)
+ if (pModal->useAnt1)
+ num_ant_config += 1;
+
+ return (num_ant_config);
+}
+
+uint8_t
+ath9k_hw_get_num_ant_config(struct ath_hal *ah,
+ enum ath9k_band freq_band)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint8_t val;
+
+ if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
+ val = ath9k_hw_get_def_num_ant_config(ah, freq_band);
+ else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ val = ath9k_hw_get_4k_num_ant_config(ah, freq_band);
+
+ return (val);
+}
+
+uint16_t
+ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, uint16_t i, boolean_t is2GHz)
+{
+#define EEP_MAP4K_SPURCHAN \
+ (ahp->ah_eeprom.map4k.modalHeader.spurChans[i].spurChan)
+#define EEP_DEF_SPURCHAN \
+ (ahp->ah_eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
+
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint16_t spur_val = AR_NO_SPUR;
+
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "Getting spur idx %d is2Ghz. %d val %x\n",
+ i, is2GHz, ah->ah_config.spurchans[i][is2GHz]));
+
+ switch (ah->ah_config.spurmode) {
+ case SPUR_DISABLE:
+ break;
+ case SPUR_ENABLE_IOCTL:
+ spur_val = ah->ah_config.spurchans[i][is2GHz];
+ ARN_DBG((ARN_DBG_ANI, "arn: "
+ "Getting spur val from new loc. %d\n", spur_val));
+ break;
+ case SPUR_ENABLE_EEPROM:
+ if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ spur_val = EEP_MAP4K_SPURCHAN;
+ else
+ spur_val = EEP_DEF_SPURCHAN;
+ break;
+
+ }
+
+ return (spur_val);
+#undef EEP_DEF_SPURCHAN
+#undef EEP_MAP4K_SPURCHAN
+}
+
+static uint32_t
+ath9k_hw_get_eeprom_4k(struct ath_hal *ah,
+ enum eeprom_param param)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &eep->modalHeader;
+ struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+
+ switch (param) {
+ case EEP_NFTHRESH_2:
+ return (pModal[1].noiseFloorThreshCh[0]);
+ case AR_EEPROM_MAC(0):
+ return (pBase->macAddr[0] << 8 | pBase->macAddr[1]);
+ case AR_EEPROM_MAC(1):
+ return (pBase->macAddr[2] << 8 | pBase->macAddr[3]);
+ case AR_EEPROM_MAC(2):
+ return (pBase->macAddr[4] << 8 | pBase->macAddr[5]);
+ case EEP_REG_0:
+ return (pBase->regDmn[0]);
+ case EEP_REG_1:
+ return (pBase->regDmn[1]);
+ case EEP_OP_CAP:
+ return (pBase->deviceCap);
+ case EEP_OP_MODE:
+ return (pBase->opCapFlags);
+ case EEP_RF_SILENT:
+ return (pBase->rfSilent);
+ case EEP_OB_2:
+ return (pModal->ob_01);
+ case EEP_DB_2:
+ return (pModal->db1_01);
+ case EEP_MINOR_REV:
+ return (pBase->version & AR5416_EEP_VER_MINOR_MASK);
+ case EEP_TX_MASK:
+ return (pBase->txMask);
+ case EEP_RX_MASK:
+ return (pBase->rxMask);
+ default:
+ return (0);
+ }
+}
+
+uint32_t
+ath9k_hw_get_eeprom_def(struct ath_hal *ah, enum eeprom_param param)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ struct modal_eep_header *pModal = eep->modalHeader;
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+
+ switch (param) {
+ case EEP_NFTHRESH_5:
+ return (pModal[0].noiseFloorThreshCh[0]);
+ case EEP_NFTHRESH_2:
+ return (pModal[1].noiseFloorThreshCh[0]);
+ case AR_EEPROM_MAC(0):
+ return (pBase->macAddr[0] << 8 | pBase->macAddr[1]);
+ case AR_EEPROM_MAC(1):
+ return (pBase->macAddr[2] << 8 | pBase->macAddr[3]);
+ case AR_EEPROM_MAC(2):
+ return (pBase->macAddr[4] << 8 | pBase->macAddr[5]);
+ case EEP_REG_0:
+ return (pBase->regDmn[0]);
+ case EEP_REG_1:
+ return (pBase->regDmn[1]);
+ case EEP_OP_CAP:
+ return (pBase->deviceCap);
+ case EEP_OP_MODE:
+ return (pBase->opCapFlags);
+ case EEP_RF_SILENT:
+ return (pBase->rfSilent);
+ case EEP_OB_5:
+ return (pModal[0].ob);
+ case EEP_DB_5:
+ return (pModal[0].db);
+ case EEP_OB_2:
+ return (pModal[1].ob);
+ case EEP_DB_2:
+ return (pModal[1].db);
+ case EEP_MINOR_REV:
+ return (pBase->version & AR5416_EEP_VER_MINOR_MASK);
+ case EEP_TX_MASK:
+ return (pBase->txMask);
+ case EEP_RX_MASK:
+ return (pBase->rxMask);
+ case EEP_RXGAIN_TYPE:
+ return (pBase->rxGainType);
+ case EEP_TXGAIN_TYPE:
+ return (pBase->txGainType);
+
+ default:
+ return (0);
+ }
+}
+
+uint32_t
+ath9k_hw_get_eeprom(struct ath_hal *ah, enum eeprom_param param)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t val;
+
+ if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
+ val = ath9k_hw_get_eeprom_def(ah, param);
+ else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ val = ath9k_hw_get_eeprom_4k(ah, param);
+
+ return (val);
+}
+
+int
+ath9k_hw_eeprom_attach(struct ath_hal *ah)
+{
+ int status;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (ath9k_hw_use_flash(ah))
+ (void) ath9k_hw_flash_map(ah);
+
+ if (AR_SREV_9285(ah))
+ ahp->ah_eep_map = EEP_MAP_4KBITS;
+ else
+ ahp->ah_eep_map = EEP_MAP_DEFAULT;
+
+ if (!ath9k_hw_fill_eeprom(ah))
+ return (EIO);
+
+ status = ath9k_hw_check_eeprom(ah);
+
+ return (status);
+}
diff --git a/usr/src/uts/common/io/arn/arn_hw.c b/usr/src/uts/common/io/arn/arn_hw.c
new file mode 100644
index 0000000000..d9b8f45a5b
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_hw.c
@@ -0,0 +1,4149 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cmn_err.h>
+#include <sys/kmem.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/varargs.h>
+
+#include "arn_ath9k.h"
+#include "arn_core.h"
+#include "arn_hw.h"
+#include "arn_reg.h"
+#include "arn_phy.h"
+#include "arn_initvals.h"
+
+static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88, 40 };
+
+extern struct hal_percal_data iq_cal_multi_sample;
+extern struct hal_percal_data iq_cal_single_sample;
+extern struct hal_percal_data adc_gain_cal_multi_sample;
+extern struct hal_percal_data adc_gain_cal_single_sample;
+extern struct hal_percal_data adc_dc_cal_multi_sample;
+extern struct hal_percal_data adc_dc_cal_single_sample;
+extern struct hal_percal_data adc_init_dc_cal;
+
+static boolean_t ath9k_hw_set_reset_reg(struct ath_hal *ah, uint32_t type);
+static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode);
+static uint32_t ath9k_hw_ini_fixup(struct ath_hal *ah,
+ struct ar5416_eeprom_def *pEepData,
+ uint32_t reg, uint32_t value);
+static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+static void ath9k_hw_spur_mitigate(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+
+/* Helper Functions */
+
+static uint32_t
+ath9k_hw_mac_usec(struct ath_hal *ah, uint32_t clks)
+{
+ if (ah->ah_curchan != NULL)
+ return (clks /
+ CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)]);
+ else
+ return (clks / CLOCK_RATE[ATH9K_MODE_11B]);
+}
+
+static uint32_t
+ath9k_hw_mac_to_usec(struct ath_hal *ah, uint32_t clks)
+{
+ struct ath9k_channel *chan = ah->ah_curchan;
+
+ if (chan && IS_CHAN_HT40(chan))
+ return (ath9k_hw_mac_usec(ah, clks) / 2);
+ else
+ return (ath9k_hw_mac_usec(ah, clks));
+}
+
+static uint32_t
+ath9k_hw_mac_clks(struct ath_hal *ah, uint32_t usecs)
+{
+ if (ah->ah_curchan != NULL)
+ return (usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah,
+ ah->ah_curchan)]);
+ else
+ return (usecs * CLOCK_RATE[ATH9K_MODE_11B]);
+}
+
+static uint32_t
+ath9k_hw_mac_to_clks(struct ath_hal *ah, uint32_t usecs)
+{
+ struct ath9k_channel *chan = ah->ah_curchan;
+
+ if (chan && IS_CHAN_HT40(chan))
+ return (ath9k_hw_mac_clks(ah, usecs) * 2);
+ else
+ return (ath9k_hw_mac_clks(ah, usecs));
+}
+
+/* ARGSUSED */
+enum wireless_mode
+ath9k_hw_chan2wmode(struct ath_hal *ah, const struct ath9k_channel *chan)
+{
+ if (IS_CHAN_B(chan))
+ return (ATH9K_MODE_11B);
+ if (IS_CHAN_G(chan))
+ return (ATH9K_MODE_11G);
+
+ return (ATH9K_MODE_11A);
+}
+
+boolean_t
+ath9k_hw_wait(struct ath_hal *ah, uint32_t reg, uint32_t mask, uint32_t val)
+{
+ int i;
+
+ for (i = 0; i < (AH_TIMEOUT / AH_TIME_QUANTUM); i++) {
+ if ((REG_READ(ah, reg) & mask) == val)
+ return (B_TRUE);
+
+ drv_usecwait(AH_TIME_QUANTUM);
+ }
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_wait(): "
+ "timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
+ reg, REG_READ(ah, reg), mask, val));
+
+ return (B_FALSE);
+}
+
+uint32_t
+ath9k_hw_reverse_bits(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);
+}
+
+boolean_t
+ath9k_get_channel_edges(struct ath_hal *ah,
+ uint16_t flags, uint16_t *low, uint16_t *high)
+{
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+ if (flags & CHANNEL_5GHZ) {
+ *low = pCap->low_5ghz_chan;
+ *high = pCap->high_5ghz_chan;
+ return (B_TRUE);
+ }
+ if ((flags & CHANNEL_2GHZ)) {
+ *low = pCap->low_2ghz_chan;
+ *high = pCap->high_2ghz_chan;
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
+uint16_t
+ath9k_hw_computetxtime(struct ath_hal *ah,
+ struct ath_rate_table *rates,
+ uint32_t frameLen, uint16_t rateix,
+ boolean_t shortPreamble)
+{
+ uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
+ uint32_t kbps;
+
+ kbps = rates->info[rateix].ratekbps;
+
+ if (kbps == 0)
+ return (0);
+
+ switch (rates->info[rateix].phy) {
+ case WLAN_RC_PHY_CCK:
+ phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
+ if (shortPreamble && rates->info[rateix].short_preamble)
+ phyTime >>= 1;
+ numBits = frameLen << 3;
+ txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
+ break;
+ case WLAN_RC_PHY_OFDM:
+ if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) {
+ bitsPerSymbol =
+ (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME_QUARTER +
+ OFDM_PREAMBLE_TIME_QUARTER +
+ (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
+ } else if (ah->ah_curchan &&
+ IS_CHAN_HALF_RATE(ah->ah_curchan)) {
+ bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME_HALF +
+ OFDM_PREAMBLE_TIME_HALF +
+ (numSymbols * OFDM_SYMBOL_TIME_HALF);
+ } else {
+ bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME +
+ (numSymbols * OFDM_SYMBOL_TIME);
+ }
+ break;
+ default:
+ arn_problem("arn: "
+ "%s: unknown phy %u (rate ix %u)\n", __func__,
+ rates->info[rateix].phy, rateix);
+ txTime = 0;
+ break;
+ }
+
+ return ((uint16_t)txTime);
+}
+
+uint32_t
+ath9k_hw_mhz2ieee(struct ath_hal *ah, uint32_t freq, uint32_t flags)
+{
+ if (flags & CHANNEL_2GHZ) {
+ if (freq == 2484)
+ return (14);
+ if (freq < 2484)
+ return ((freq - 2407) / 5);
+ else
+ return (15 + ((freq - 2512) / 20));
+ } else if (flags & CHANNEL_5GHZ) {
+ if (ath9k_regd_is_public_safety_sku(ah) &&
+ IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
+ return (((freq * 10) +
+ (((freq % 5) == 2) ? 5 : 0) - 49400) / 5);
+ } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
+ return ((freq - 4000) / 5);
+ } else {
+ return ((freq - 5000) / 5);
+ }
+ } else {
+ if (freq == 2484)
+ return (14);
+ if (freq < 2484)
+ return ((freq - 2407) / 5);
+ if (freq < 5000) {
+ if (ath9k_regd_is_public_safety_sku(ah) &&
+ IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
+ return (((freq * 10) +
+ (((freq % 5) ==
+ 2) ? 5 : 0) - 49400) / 5);
+ } else if (freq > 4900) {
+ return ((freq - 4000) / 5);
+ } else {
+ return (15 + ((freq - 2512) / 20));
+ }
+ }
+ return ((freq - 5000) / 5);
+ }
+}
+
+void
+ath9k_hw_get_channel_centers(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct chan_centers *centers)
+{
+ int8_t extoff;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (!IS_CHAN_HT40(chan)) {
+ centers->ctl_center = centers->ext_center =
+ centers->synth_center = chan->channel;
+ return;
+ }
+
+ if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+ (chan->chanmode == CHANNEL_G_HT40PLUS)) {
+ centers->synth_center =
+ chan->channel + HT40_CHANNEL_CENTER_SHIFT;
+ extoff = 1;
+ } else {
+ centers->synth_center =
+ chan->channel - HT40_CHANNEL_CENTER_SHIFT;
+ extoff = -1;
+ }
+
+ centers->ctl_center =
+ centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
+ centers->ext_center =
+ centers->synth_center + (extoff *
+ ((ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ?
+ HT40_CHANNEL_CENTER_SHIFT : 15));
+
+}
+
+/* Chip Revisions */
+
+static void
+ath9k_hw_read_revisions(struct ath_hal *ah)
+{
+ uint32_t val;
+
+ val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
+
+ if (val == 0xFF) {
+ val = REG_READ(ah, AR_SREV);
+ ah->ah_macVersion = (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
+ ah->ah_macRev = MS(val, AR_SREV_REVISION2);
+ ah->ah_isPciExpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+ } else {
+ if (!AR_SREV_9100(ah))
+ ah->ah_macVersion = MS(val, AR_SREV_VERSION);
+
+ ah->ah_macRev = val & AR_SREV_REVISION;
+
+ if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE)
+ ah->ah_isPciExpress = B_TRUE;
+ }
+}
+
+static int
+ath9k_hw_get_radiorev(struct ath_hal *ah)
+{
+ uint32_t val;
+ int i;
+
+ REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
+
+ for (i = 0; i < 8; i++)
+ REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
+ val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
+ val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
+
+ return (ath9k_hw_reverse_bits(val, 8));
+}
+
+/* HW Attach, Detach, Init Routines */
+
+static void
+ath9k_hw_disablepcie(struct ath_hal *ah)
+{
+ if (!AR_SREV_9100(ah))
+ return;
+
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
+
+ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+}
+
+static boolean_t
+ath9k_hw_chip_test(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;
+
+ for (i = 0; i < 2; i++) {
+ uint32_t addr = regAddr[i];
+ uint32_t wrData, rdData;
+
+ regHold[i] = REG_READ(ah, addr);
+ for (j = 0; j < 0x100; j++) {
+ wrData = (j << 16) | j;
+ REG_WRITE(ah, addr, wrData);
+ rdData = REG_READ(ah, addr);
+ if (rdData != wrData) {
+ ARN_DBG((ARN_DBG_REG_IO,
+ "arn: ath9k_hw_chip_test(): "
+ "address test failed "
+ "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+ addr, wrData, rdData));
+
+ return (B_FALSE);
+ }
+ }
+ for (j = 0; j < 4; j++) {
+ wrData = patternData[j];
+ REG_WRITE(ah, addr, wrData);
+ rdData = REG_READ(ah, addr);
+ if (wrData != rdData) {
+ ARN_DBG((ARN_DBG_REG_IO,
+ "arn: ath9k_hw_chip_test(): "
+ "address test failed "
+ "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+ addr, wrData, rdData));
+
+ return (B_FALSE);
+ }
+ }
+ REG_WRITE(ah, regAddr[i], regHold[i]);
+ }
+ drv_usecwait(100);
+
+ return (B_TRUE);
+}
+
+static const char *
+ath9k_hw_devname(uint16_t devid)
+{
+ switch (devid) {
+ case AR5416_DEVID_PCI:
+ return ("Atheros 5416");
+ case AR5416_DEVID_PCIE:
+ return ("Atheros 5418");
+ case AR9160_DEVID_PCI:
+ return ("Atheros 9160");
+ case AR9280_DEVID_PCI:
+ case AR9280_DEVID_PCIE:
+ return ("Atheros 9280");
+ case AR9285_DEVID_PCIE:
+ return ("Atheros 9285");
+ }
+
+ return (NULL);
+}
+
+static void
+ath9k_hw_set_defaults(struct ath_hal *ah)
+{
+ int i;
+
+ ah->ah_config.dma_beacon_response_time = 2;
+ ah->ah_config.sw_beacon_response_time = 10;
+ ah->ah_config.additional_swba_backoff = 0;
+ ah->ah_config.ack_6mb = 0x0;
+ ah->ah_config.cwm_ignore_extcca = 0;
+ ah->ah_config.pcie_powersave_enable = 0;
+ ah->ah_config.pcie_l1skp_enable = 0;
+ ah->ah_config.pcie_clock_req = 0;
+ ah->ah_config.pcie_power_reset = 0x100;
+ ah->ah_config.pcie_restore = 0;
+ ah->ah_config.pcie_waen = 0;
+ ah->ah_config.analog_shiftreg = 1;
+ ah->ah_config.ht_enable = 1;
+ ah->ah_config.ofdm_trig_low = 200;
+ ah->ah_config.ofdm_trig_high = 500;
+ ah->ah_config.cck_trig_high = 200;
+ ah->ah_config.cck_trig_low = 100;
+ ah->ah_config.enable_ani = 1;
+ ah->ah_config.noise_immunity_level = 4;
+ ah->ah_config.ofdm_weaksignal_det = 1;
+ ah->ah_config.cck_weaksignal_thr = 0;
+ ah->ah_config.spur_immunity_level = 2;
+ ah->ah_config.firstep_level = 0;
+ ah->ah_config.rssi_thr_high = 40;
+ ah->ah_config.rssi_thr_low = 7;
+ ah->ah_config.diversity_control = 0;
+ ah->ah_config.antenna_switch_swap = 0;
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ ah->ah_config.spurchans[i][0] = AR_NO_SPUR;
+ ah->ah_config.spurchans[i][1] = AR_NO_SPUR;
+ }
+
+ ah->ah_config.intr_mitigation = 1;
+
+ /*
+ * We need this for PCI devices only (Cardbus, PCI, miniPCI)
+ * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
+ * This means we use it for all AR5416 devices, and the few
+ * minor PCI AR9280 devices out there.
+ *
+ * Serialization is required because these devices do not handle
+ * well the case of two concurrent reads/writes due to the latency
+ * involved. During one read/write another read/write can be issued
+ * on another CPU while the previous read/write may still be working
+ * on our hardware, if we hit this case the hardware poops in a loop.
+ * We prevent this by serializing reads and writes.
+ *
+ * This issue is not present on PCI-Express devices or pre-AR5416
+ * devices (legacy, 802.11abg).
+ */
+
+ /* num_of_cpus */
+}
+
+static struct ath_hal_5416 *
+ath9k_hw_newstate(uint16_t device_id, struct arn_softc *sc, caddr_t mem,
+ int *status)
+{
+ static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ struct ath_hal_5416 *ahp;
+ struct ath_hal *ah;
+
+ ahp = (struct ath_hal_5416 *)
+ kmem_zalloc(sizeof (struct ath_hal_5416), KM_SLEEP);
+ if (ahp == NULL) {
+ ARN_DBG((ARN_DBG_ANY, "arn: ath9k_hw_newstate(): "
+ "failed to alloc mem for ahp\n"));
+ *status = ENOMEM;
+ return (NULL);
+ }
+
+ ah = &ahp->ah;
+ ah->ah_sc = sc;
+ ah->ah_sh = mem;
+ ah->ah_magic = AR5416_MAGIC;
+ ah->ah_countryCode = CTRY_DEFAULT;
+ ah->ah_devid = device_id;
+ ah->ah_subvendorid = 0;
+
+ ah->ah_flags = 0;
+ if ((device_id == AR5416_AR9100_DEVID))
+ ah->ah_macVersion = AR_SREV_VERSION_9100;
+ if (!AR_SREV_9100(ah))
+ ah->ah_flags = AH_USE_EEPROM;
+
+ ah->ah_powerLimit = MAX_RATE_POWER;
+ ah->ah_tpScale = ATH9K_TP_SCALE_MAX;
+ ahp->ah_atimWindow = 0;
+ ahp->ah_diversityControl = ah->ah_config.diversity_control;
+ ahp->ah_antennaSwitchSwap =
+ ah->ah_config.antenna_switch_swap;
+ ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
+ ahp->ah_beaconInterval = 100;
+ ahp->ah_enable32kHzClock = DONT_USE_32KHZ;
+ ahp->ah_slottime = (uint32_t)-1;
+ ahp->ah_acktimeout = (uint32_t)-1;
+ ahp->ah_ctstimeout = (uint32_t)-1;
+ ahp->ah_globaltxtimeout = (uint32_t)-1;
+ (void) memcpy(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN);
+
+ ahp->ah_gBeaconRate = 0;
+
+ return (ahp);
+}
+
+static int
+ath9k_hw_rfattach(struct ath_hal *ah)
+{
+ boolean_t rfStatus = B_FALSE;
+ int ecode = 0;
+
+ rfStatus = ath9k_hw_init_rf(ah, &ecode);
+ if (!rfStatus) {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_rfattach(): "
+ "RF setup failed, status %u\n", ecode));
+
+ return (ecode);
+ }
+
+ return (0);
+}
+
+static int
+ath9k_hw_rf_claim(struct ath_hal *ah)
+{
+ uint32_t val;
+
+ REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+ val = ath9k_hw_get_radiorev(ah);
+ switch (val & AR_RADIO_SREV_MAJOR) {
+ case 0:
+ val = AR_RAD5133_SREV_MAJOR;
+ break;
+ case AR_RAD5133_SREV_MAJOR:
+ case AR_RAD5122_SREV_MAJOR:
+ case AR_RAD2133_SREV_MAJOR:
+ case AR_RAD2122_SREV_MAJOR:
+ break;
+ default:
+ ARN_DBG((ARN_DBG_CHANNEL,
+ "arn: ath9k_hw_rf_claim(): "
+ "5G Radio Chip Rev 0x%02X "
+ "is not supported by this driver\n",
+ ah->ah_analog5GhzRev));
+
+ return (ENOTSUP);
+ }
+
+ ah->ah_analog5GhzRev = (uint16_t)val;
+
+ return (0);
+}
+
+static int
+ath9k_hw_init_macaddr(struct ath_hal *ah)
+{
+ uint32_t sum;
+ int i;
+ uint16_t eeval;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ sum = 0;
+ for (i = 0; i < 3; i++) {
+ eeval = ath9k_hw_get_eeprom(ah, AR_EEPROM_MAC(i));
+ sum += eeval;
+ ahp->ah_macaddr[2 * i] = eeval >> 8;
+ ahp->ah_macaddr[2 * i + 1] = eeval & 0xff;
+ }
+ if (sum == 0 || sum == 0xffff * 3) {
+ ARN_DBG((ARN_DBG_EEPROM, "arn: ath9k_hw_init_macaddr(): "
+ "mac address read failed: %pM\n",
+ ahp->ah_macaddr));
+
+ return (EADDRNOTAVAIL);
+ }
+
+ return (0);
+}
+
+static void
+ath9k_hw_init_rxgain_ini(struct ath_hal *ah)
+{
+ uint32_t rxgain_type;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (ath9k_hw_get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) {
+ rxgain_type = ath9k_hw_get_eeprom(ah, EEP_RXGAIN_TYPE);
+ if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) {
+ INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
+ ar9280Modes_backoff_13db_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2),
+ 6);
+ } else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) {
+ INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
+ ar9280Modes_backoff_23db_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2),
+ 6);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
+ ar9280Modes_original_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ }
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
+ ar9280Modes_original_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ }
+}
+
+static void
+ath9k_hw_init_txgain_ini(struct ath_hal *ah)
+{
+ uint32_t txgain_type;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (ath9k_hw_get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) {
+ txgain_type = ath9k_hw_get_eeprom(ah, EEP_TXGAIN_TYPE);
+
+ if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
+ INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
+ ar9280Modes_high_power_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2),
+ 6);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
+ ar9280Modes_original_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ }
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
+ ar9280Modes_original_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ }
+}
+
+static int
+ath9k_hw_post_attach(struct ath_hal *ah)
+{
+ int ecode;
+
+ if (!ath9k_hw_chip_test(ah)) {
+ ARN_DBG((ARN_DBG_REG_IO, "arn: ath9k_hw_post_attach(): "
+ "hardware self-test failed\n"));
+
+ }
+
+ ecode = ath9k_hw_rf_claim(ah);
+ if (ecode != 0)
+ return (ecode);
+
+ ecode = ath9k_hw_eeprom_attach(ah);
+ if (ecode != 0)
+ return (ecode);
+ ecode = ath9k_hw_rfattach(ah);
+ if (ecode != 0)
+ return (ecode);
+
+ if (!AR_SREV_9100(ah)) {
+ ath9k_hw_ani_setup(ah);
+ ath9k_hw_ani_attach(ah);
+ }
+
+ return (0);
+}
+
+static struct ath_hal *
+ath9k_hw_do_attach(uint16_t device_id, struct arn_softc *sc,
+ caddr_t mem, int *status)
+{
+ struct ath_hal_5416 *ahp;
+ struct ath_hal *ah;
+ int ecode;
+ uint32_t i;
+ uint32_t j;
+
+ ahp = ath9k_hw_newstate(device_id, sc, mem, status);
+ if (ahp == NULL)
+ return (NULL);
+
+ ah = &ahp->ah;
+
+ ath9k_hw_set_defaults(ah);
+
+ if (ah->ah_config.intr_mitigation != 0)
+ ahp->ah_intrMitigation = B_TRUE;
+
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_set_reset_reg(): "
+ "couldn't reset chip \n"));
+ ecode = EIO;
+ goto bad;
+ }
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_setpower(): "
+ "couldn't wakeup chip \n"));
+ ecode = EIO;
+ goto bad;
+ }
+
+ if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) {
+ if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI ||
+ (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) {
+ ah->ah_config.serialize_regmode =
+ SER_REG_MODE_ON;
+ } else {
+ ah->ah_config.serialize_regmode =
+ SER_REG_MODE_OFF;
+ }
+ }
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_do_attach(): "
+ "serialize_regmode is %d\n",
+ ah->ah_config.serialize_regmode));
+
+ if ((ah->ah_macVersion != AR_SREV_VERSION_5416_PCI) &&
+ (ah->ah_macVersion != AR_SREV_VERSION_5416_PCIE) &&
+ (ah->ah_macVersion != AR_SREV_VERSION_9160) &&
+ (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) &&
+ (!AR_SREV_9285(ah))) {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_do_attach(): "
+ "Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
+ ah->ah_macVersion, ah->ah_macRev));
+ ecode = ENOTSUP;
+ goto bad;
+ }
+
+ if (AR_SREV_9100(ah)) {
+ ahp->ah_iqCalData.calData = &iq_cal_multi_sample;
+ ahp->ah_suppCals = IQ_MISMATCH_CAL;
+ ah->ah_isPciExpress = B_FALSE;
+ }
+ ah->ah_phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
+
+ if (AR_SREV_9160_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ ahp->ah_iqCalData.calData = &iq_cal_single_sample;
+ ahp->ah_adcGainCalData.calData =
+ &adc_gain_cal_single_sample;
+ ahp->ah_adcDcCalData.calData =
+ &adc_dc_cal_single_sample;
+ ahp->ah_adcDcCalInitData.calData =
+ &adc_init_dc_cal;
+ } else {
+ ahp->ah_iqCalData.calData = &iq_cal_multi_sample;
+ ahp->ah_adcGainCalData.calData =
+ &adc_gain_cal_multi_sample;
+ ahp->ah_adcDcCalData.calData =
+ &adc_dc_cal_multi_sample;
+ ahp->ah_adcDcCalInitData.calData =
+ &adc_init_dc_cal;
+ }
+ ahp->ah_suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+ }
+
+ if (AR_SREV_9160(ah)) {
+ ah->ah_config.enable_ani = 1;
+ ahp->ah_ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
+ ATH9K_ANI_FIRSTEP_LEVEL);
+ } else {
+ ahp->ah_ani_function = ATH9K_ANI_ALL;
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ ahp->ah_ani_function &=
+ ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
+ }
+ }
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_do_attach(): "
+ "This Mac Chip Rev 0x%02x.%x is \n",
+ ah->ah_macVersion, ah->ah_macRev));
+
+ if (AR_SREV_9285_12_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar9285Modes_9285_1_2,
+ ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
+
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9285Common_9285_1_2,
+ ARRAY_SIZE(ar9285Common_9285_1_2), 2);
+
+ if (ah->ah_config.pcie_clock_req) {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9285PciePhy_clkreq_off_L1_9285_1_2,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2),
+ 2);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
+ ARRAY_SIZE
+ (ar9285PciePhy_clkreq_always_on_L1_9285_1_2), 2);
+ }
+ } else if (AR_SREV_9285_10_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar9285Modes_9285,
+ ARRAY_SIZE(ar9285Modes_9285), 6);
+
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9285Common_9285,
+ ARRAY_SIZE(ar9285Common_9285), 2);
+
+ if (ah->ah_config.pcie_clock_req) {
+
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9285PciePhy_clkreq_off_L1_9285,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9285PciePhy_clkreq_always_on_L1_9285,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285),
+ 2);
+ }
+ } else if (AR_SREV_9280_20_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280_2,
+ ARRAY_SIZE(ar9280Modes_9280_2), 6);
+
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280_2,
+ ARRAY_SIZE(ar9280Common_9280_2), 2);
+
+ if (ah->ah_config.pcie_clock_req) {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9280PciePhy_clkreq_off_L1_9280,
+ ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9280PciePhy_clkreq_always_on_L1_9280,
+ ARRAY_SIZE
+ (ar9280PciePhy_clkreq_always_on_L1_9280), 2);
+ }
+
+ INIT_INI_ARRAY(&ahp->ah_iniModesAdditional,
+ ar9280Modes_fast_clock_9280_2,
+ ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
+ } else if (AR_SREV_9280_10_OR_LATER(ah)) {
+
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280,
+ ARRAY_SIZE(ar9280Modes_9280), 6);
+
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280,
+ ARRAY_SIZE(ar9280Common_9280), 2);
+ } else if (AR_SREV_9160_10_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes_9160,
+ ARRAY_SIZE(ar5416Modes_9160), 6);
+
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common_9160,
+ ARRAY_SIZE(ar5416Common_9160), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0_9160,
+ ARRAY_SIZE(ar5416Bank0_9160), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain_9160,
+ ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1_9160,
+ ARRAY_SIZE(ar5416Bank1_9160), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2_9160,
+ ARRAY_SIZE(ar5416Bank2_9160), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3_9160,
+ ARRAY_SIZE(ar5416Bank3_9160), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6_9160,
+ ARRAY_SIZE(ar5416Bank6_9160), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC_9160,
+ ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7_9160,
+ ARRAY_SIZE(ar5416Bank7_9160), 2);
+ if (AR_SREV_9160_11(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_iniAddac,
+ ar5416Addac_91601_1,
+ ARRAY_SIZE(ar5416Addac_91601_1), 2);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac_9160,
+ ARRAY_SIZE(ar5416Addac_9160), 2);
+ }
+ } else if (AR_SREV_9100_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes_9100,
+ ARRAY_SIZE(ar5416Modes_9100), 6);
+
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common_9100,
+ ARRAY_SIZE(ar5416Common_9100), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0_9100,
+ ARRAY_SIZE(ar5416Bank0_9100), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain_9100,
+ ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1_9100,
+ ARRAY_SIZE(ar5416Bank1_9100), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2_9100,
+ ARRAY_SIZE(ar5416Bank2_9100), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3_9100,
+ ARRAY_SIZE(ar5416Bank3_9100), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6_9100,
+ ARRAY_SIZE(ar5416Bank6_9100), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC_9100,
+ ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7_9100,
+ ARRAY_SIZE(ar5416Bank7_9100), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac_9100,
+ ARRAY_SIZE(ar5416Addac_9100), 2);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes,
+ ARRAY_SIZE(ar5416Modes), 6);
+
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common,
+ ARRAY_SIZE(ar5416Common), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0,
+ ARRAY_SIZE(ar5416Bank0), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain,
+ ARRAY_SIZE(ar5416BB_RfGain), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1,
+ ARRAY_SIZE(ar5416Bank1), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2,
+ ARRAY_SIZE(ar5416Bank2), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3,
+ ARRAY_SIZE(ar5416Bank3), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6,
+ ARRAY_SIZE(ar5416Bank6), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC,
+ ARRAY_SIZE(ar5416Bank6TPC), 3);
+
+ INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7,
+ ARRAY_SIZE(ar5416Bank7), 2);
+
+ INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac,
+ ARRAY_SIZE(ar5416Addac), 2);
+ }
+
+ if (ah->ah_isPciExpress)
+ ath9k_hw_configpcipowersave(ah, 0);
+ else
+ ath9k_hw_disablepcie(ah);
+
+ ecode = ath9k_hw_post_attach(ah);
+ if (ecode != 0)
+ goto bad;
+
+ /* rxgain table */
+ if (AR_SREV_9280_20(ah))
+ ath9k_hw_init_rxgain_ini(ah);
+
+ /* txgain table */
+ if (AR_SREV_9280_20(ah))
+ ath9k_hw_init_txgain_ini(ah);
+
+ if (ah->ah_devid == AR9280_DEVID_PCI) {
+ for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
+ uint32_t reg =
+ INI_RA(&ahp->ah_iniModes, i, 0);
+
+ for (j = 1; j < ahp->ah_iniModes.ia_columns; j++) {
+ uint32_t val
+ = INI_RA(&ahp->ah_iniModes, i, j);
+
+ INI_RA(&ahp->ah_iniModes, i, j) =
+ ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom.def,
+ reg, val);
+ }
+ }
+ }
+
+ if (!ath9k_hw_fill_cap_info(ah)) {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_do_attach(): "
+ "failed ath9k_hw_fill_cap_info\n"));
+ goto bad;
+ }
+
+ ecode = ath9k_hw_init_macaddr(ah);
+ if (ecode != 0) {
+ ARN_DBG((ARN_DBG_HW, "arn: "
+ "%s: failed initializing mac address\n",
+ __func__));
+ goto bad;
+ }
+
+ if (AR_SREV_9285(ah))
+ ah->ah_txTrigLevel = (AR_FTRIG_256B >> AR_FTRIG_S);
+ else
+ ah->ah_txTrigLevel = (AR_FTRIG_512B >> AR_FTRIG_S);
+
+ ath9k_init_nfcal_hist_buffer(ah);
+
+ return (ah);
+bad:
+ if (ahp)
+ ath9k_hw_detach((struct ath_hal *)ahp);
+ if (status)
+ *status = ecode;
+
+ return (NULL);
+}
+
+static void
+ath9k_hw_init_bb(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ uint32_t synthDelay;
+
+ synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+ if (IS_CHAN_B(chan))
+ synthDelay = (4 * synthDelay) / 22;
+ else
+ synthDelay /= 10;
+
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+ drv_usecwait(synthDelay + BASE_ACTIVATE_DELAY);
+}
+
+static void
+ath9k_hw_init_qos(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
+ REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
+
+ REG_WRITE(ah, AR_QOS_NO_ACK,
+ SM(2, AR_QOS_NO_ACK_TWO_BIT) |
+ SM(5, AR_QOS_NO_ACK_BIT_OFF) |
+ SM(0, AR_QOS_NO_ACK_BYTE_OFF));
+
+ REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
+ REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
+}
+
+static void
+ath9k_hw_init_pll(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ uint32_t pll;
+
+ if (AR_SREV_9100(ah)) {
+ if (chan && IS_CHAN_5GHZ(chan))
+ pll = 0x1450;
+ else
+ pll = 0x1458;
+ } else {
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+ if (chan && IS_CHAN_5GHZ(chan)) {
+ pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
+
+
+ if (AR_SREV_9280_20(ah)) {
+ if (((chan->channel % 20) == 0) ||
+ ((chan->channel % 10) == 0))
+ pll = 0x2850;
+ else
+ pll = 0x142c;
+ }
+ } else {
+ pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
+ }
+
+ } else if (AR_SREV_9160_10_OR_LATER(ah)) {
+
+ pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+ if (chan && IS_CHAN_5GHZ(chan))
+ pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
+ else
+ pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
+ } else {
+ pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
+
+ if (chan && IS_CHAN_5GHZ(chan))
+ pll |= SM(0xa, AR_RTC_PLL_DIV);
+ else
+ pll |= SM(0xb, AR_RTC_PLL_DIV);
+ }
+ }
+ REG_WRITE(ah, (uint16_t)(AR_RTC_PLL_CONTROL), pll);
+
+ drv_usecwait(RTC_PLL_SETTLE_DELAY);
+
+ REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
+}
+
+static void
+ath9k_hw_init_chain_masks(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int rx_chainmask, tx_chainmask;
+
+ rx_chainmask = ahp->ah_rxchainmask;
+ tx_chainmask = ahp->ah_txchainmask;
+
+ switch (rx_chainmask) {
+ case 0x5:
+ REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+ AR_PHY_SWAP_ALT_CHAIN);
+ /*FALLTHRU*/
+ case 0x3:
+ if (((ah)->ah_macVersion <= AR_SREV_VERSION_9160)) {
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
+ break;
+ }
+ /*FALLTHRU*/
+ case 0x1:
+ case 0x2:
+ case 0x7:
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+ break;
+ default:
+ break;
+ }
+
+ REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
+ if (tx_chainmask == 0x5) {
+ REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+ AR_PHY_SWAP_ALT_CHAIN);
+ }
+ if (AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
+ REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
+}
+
+static void
+ath9k_hw_init_interrupt_masks(struct ath_hal *ah, enum ath9k_opmode opmode)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ ahp->ah_maskReg = AR_IMR_TXERR |
+ AR_IMR_TXURN |
+ AR_IMR_RXERR |
+ AR_IMR_RXORN |
+ AR_IMR_BCNMISC;
+
+ if (ahp->ah_intrMitigation)
+ ahp->ah_maskReg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+ else
+ ahp->ah_maskReg |= AR_IMR_RXOK;
+
+ ahp->ah_maskReg |= AR_IMR_TXOK;
+
+ if (opmode == ATH9K_M_HOSTAP)
+ ahp->ah_maskReg |= AR_IMR_MIB;
+
+ REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
+ REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
+
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
+ REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
+ }
+}
+
+static boolean_t
+ath9k_hw_set_ack_timeout(struct ath_hal *ah, uint32_t us)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_set_ack_timeout(): "
+ "bad ack timeout %u\n", us));
+
+ ahp->ah_acktimeout = (uint32_t)-1;
+ return (B_FALSE);
+ } else {
+ REG_RMW_FIELD(ah, AR_TIME_OUT,
+ AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
+ ahp->ah_acktimeout = us;
+ return (B_TRUE);
+ }
+}
+
+static boolean_t
+ath9k_hw_set_cts_timeout(struct ath_hal *ah, uint32_t us)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_set_cts_timeout(): "
+ "bad cts timeout %u\n", us));
+
+ ahp->ah_ctstimeout = (uint32_t)-1;
+ return (B_FALSE);
+ } else {
+ REG_RMW_FIELD(ah, AR_TIME_OUT,
+ AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
+ ahp->ah_ctstimeout = us;
+ return (B_TRUE);
+ }
+}
+
+static boolean_t
+ath9k_hw_set_global_txtimeout(struct ath_hal *ah, uint32_t tu)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (tu > 0xFFFF) {
+ ARN_DBG((ARN_DBG_XMIT,
+ "arn: ath9k_hw_set_global_txtimeout(): "
+ "ath9k_hw_set_global_txtimeout\n", tu));
+
+ ahp->ah_globaltxtimeout = (uint32_t)-1;
+ return (B_FALSE);
+ } else {
+ REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
+ ahp->ah_globaltxtimeout = tu;
+ return (B_TRUE);
+ }
+}
+
+static void
+ath9k_hw_init_user_settings(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ ARN_DBG((ARN_DBG_ANY, "arn: ath9k_hw_init_user_settings(): "
+ "--AP ahp->ah_miscMode 0x%x\n", ahp->ah_miscMode));
+
+ if (ahp->ah_miscMode != 0)
+ REG_WRITE(ah, AR_PCU_MISC,
+ REG_READ(ah, AR_PCU_MISC) | ahp->ah_miscMode);
+ if (ahp->ah_slottime != (uint32_t)-1)
+ (void) ath9k_hw_setslottime(ah, ahp->ah_slottime);
+ if (ahp->ah_acktimeout != (uint32_t)-1)
+ (void) ath9k_hw_set_ack_timeout(ah, ahp->ah_acktimeout);
+ if (ahp->ah_ctstimeout != (uint32_t)-1)
+ (void) ath9k_hw_set_cts_timeout(ah, ahp->ah_ctstimeout);
+ if (ahp->ah_globaltxtimeout != (uint32_t)-1)
+ (void) ath9k_hw_set_global_txtimeout
+ (ah, ahp->ah_globaltxtimeout);
+}
+
+const char *
+ath9k_hw_probe(uint16_t vendorid, uint16_t devid)
+{
+ return (vendorid == ATHEROS_VENDOR_ID ?
+ ath9k_hw_devname(devid) : NULL);
+}
+
+void
+ath9k_hw_detach(struct ath_hal *ah)
+{
+ if (!AR_SREV_9100(ah))
+ ath9k_hw_ani_detach(ah);
+
+ ath9k_hw_rfdetach(ah);
+ (void) ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
+ kmem_free(ah, sizeof (struct ath_hal_5416)); /* ???? */
+}
+
+struct ath_hal *
+ath9k_hw_attach(uint16_t device_id, struct arn_softc *sc,
+ caddr_t mem, int *error)
+{
+ struct ath_hal *ah = NULL;
+
+ switch (device_id) {
+ case AR5416_DEVID_PCI:
+ case AR5416_DEVID_PCIE:
+ case AR9160_DEVID_PCI:
+ case AR9280_DEVID_PCI:
+ case AR9280_DEVID_PCIE:
+ case AR9285_DEVID_PCIE:
+ ah = ath9k_hw_do_attach(device_id, sc, mem, error);
+ break;
+ default:
+ *error = ENXIO;
+ break;
+ }
+
+ return (ah);
+}
+
+/* INI */
+
+/* ARGSUSED */
+static void
+ath9k_hw_override_ini(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ /*
+ * Set the RX_ABORT and RX_DIS and clear if off only after
+ * RXE is set for MAC. This prevents frames with corrupted
+ * descriptor status.
+ */
+ REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+ if (!AR_SREV_5416_V20_OR_LATER(ah) ||
+ AR_SREV_9280_10_OR_LATER(ah))
+ return;
+
+ REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
+}
+
+static uint32_t
+ath9k_hw_def_ini_fixup(struct ath_hal *ah,
+ struct ar5416_eeprom_def *pEepData,
+ uint32_t reg, uint32_t value)
+{
+ struct base_eep_header *pBase = &(pEepData->baseEepHeader);
+
+ switch (ah->ah_devid) {
+ case AR9280_DEVID_PCI:
+ if (reg == 0x7894) {
+ ARN_DBG((ARN_DBG_ANY,
+ "arn: ath9k_hw_ini_fixup(): "
+ "ini VAL: %x EEPROM: %x\n",
+ value, (pBase->version & 0xff)));
+
+ if ((pBase->version & 0xff) > 0x0a) {
+ ARN_DBG((ARN_DBG_ANY,
+ "arn: ath9k_hw_ini_fixup(): "
+ "PWDCLKIND: %d\n",
+ pBase->pwdclkind));
+
+ value &= ~AR_AN_TOP2_PWDCLKIND;
+ value |= AR_AN_TOP2_PWDCLKIND &
+ (pBase->pwdclkind <<
+ AR_AN_TOP2_PWDCLKIND_S);
+ } else {
+ ARN_DBG((ARN_DBG_ANY,
+ "arn: ath9k_hw_ini_fixup(): "
+ "PWDCLKIND Earlier Rev\n"));
+ }
+
+ ARN_DBG((ARN_DBG_ANY,
+ "arn: ath9k_hw_ini_fixup(): "
+ "final ini VAL: %x\n\n", value));
+ }
+ break;
+ }
+
+ return (value);
+}
+
+static uint32_t
+ath9k_hw_ini_fixup(struct ath_hal *ah, struct ar5416_eeprom_def *pEepData,
+ uint32_t reg, uint32_t value)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ return (value);
+ else
+ return (ath9k_hw_def_ini_fixup(ah, pEepData, reg, value));
+}
+
+static int
+ath9k_hw_process_ini(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode)
+{
+ int i, regWrites = 0;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t modesIndex, freqIndex;
+ int status;
+
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ modesIndex = 1;
+ freqIndex = 1;
+ break;
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ modesIndex = 2;
+ freqIndex = 1;
+ break;
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ modesIndex = 4;
+ freqIndex = 2;
+ break;
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ modesIndex = 3;
+ freqIndex = 2;
+ break;
+
+ default:
+ ARN_DBG((ARN_DBG_CHANNEL, "arn: "
+ "%s: err: unknow chan->chanmode\n", __func__));
+ return (EINVAL);
+ }
+
+ REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+ REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+
+ ath9k_hw_set_addac(ah, chan);
+
+ if (AR_SREV_5416_V22_OR_LATER(ah)) {
+ /* LINTED: E_CONSTANT_CONDITION */
+ REG_WRITE_ARRAY(&ahp->ah_iniAddac, 1, regWrites);
+ } else {
+ struct ar5416IniArray temp;
+ uint32_t addacSize =
+ sizeof (uint32_t) * ahp->ah_iniAddac.ia_rows *
+ ahp->ah_iniAddac.ia_columns;
+
+ (void) memcpy(ahp->ah_addac5416_21,
+ ahp->ah_iniAddac.ia_array, addacSize);
+
+ (ahp->ah_addac5416_21)
+ [31 * ahp->ah_iniAddac.ia_columns + 1] = 0;
+
+ temp.ia_array = ahp->ah_addac5416_21;
+ temp.ia_columns = ahp->ah_iniAddac.ia_columns;
+ temp.ia_rows = ahp->ah_iniAddac.ia_rows;
+ /* LINTED: E_CONSTANT_CONDITION */
+ REG_WRITE_ARRAY(&temp, 1, regWrites);
+ }
+
+ REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+ for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
+ uint32_t reg = INI_RA(&ahp->ah_iniModes, i, 0);
+ uint32_t val = INI_RA(&ahp->ah_iniModes, i, modesIndex);
+
+ REG_WRITE(ah, reg, val);
+
+ if (reg >= 0x7800 && reg < 0x78a0 &&
+ ah->ah_config.analog_shiftreg) {
+ drv_usecwait(100);
+ }
+
+ /* LINTED: E_CONSTANT_CONDITION */
+ DO_DELAY(regWrites);
+ }
+
+ if (AR_SREV_9280(ah)) {
+ /* LINTED: E_CONSTANT_CONDITION */
+ REG_WRITE_ARRAY(&ahp->ah_iniModesRxGain, modesIndex,
+ regWrites);
+ }
+
+ if (AR_SREV_9280(ah)) {
+ /* LINTED: E_CONSTANT_CONDITION */
+ REG_WRITE_ARRAY(&ahp->ah_iniModesTxGain, modesIndex,
+ regWrites);
+ }
+
+ for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) {
+ uint32_t reg = INI_RA(&ahp->ah_iniCommon, i, 0);
+ uint32_t val = INI_RA(&ahp->ah_iniCommon, i, 1);
+
+ REG_WRITE(ah, reg, val);
+
+ if (reg >= 0x7800 && reg < 0x78a0 &&
+ ah->ah_config.analog_shiftreg) {
+ drv_usecwait(100);
+ }
+
+ /* LINTED: E_CONSTANT_CONDITION */
+ DO_DELAY(regWrites);
+ }
+
+ ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
+
+ if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
+ /* LINTED: E_CONSTANT_CONDITION */
+ REG_WRITE_ARRAY(&ahp->ah_iniModesAdditional, modesIndex,
+ regWrites);
+ }
+
+ ath9k_hw_override_ini(ah, chan);
+ ath9k_hw_set_regs(ah, chan, macmode);
+ ath9k_hw_init_chain_masks(ah);
+
+ status = ath9k_hw_set_txpower(ah, chan,
+ ath9k_regd_get_ctl(ah, chan),
+ ath9k_regd_get_antenna_allowed(ah, chan),
+ chan->maxRegTxPower * 2,
+ min((uint32_t)MAX_RATE_POWER,
+ (uint32_t)ah->ah_powerLimit));
+ if (status != 0) {
+ ARN_DBG((ARN_DBG_ANY, "arn: ath9k_hw_process_ini(): "
+ "%s: error init'ing transmit power\n", __func__));
+
+ return (EIO);
+ }
+
+ if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+ ARN_DBG((ARN_DBG_ANY, "arn: ath9k_hw_process_ini(): "
+ "%s: ar5416SetRfRegs failed\n", __func__));
+
+ return (EIO);
+ }
+
+ return (0);
+}
+
+/* Reset and Channel Switching Routines */
+
+static void
+ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ uint32_t rfMode = 0;
+
+ if (chan == NULL)
+ return;
+
+ rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
+ ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+
+ if (!AR_SREV_9280_10_OR_LATER(ah))
+ rfMode |= (IS_CHAN_5GHZ(chan)) ?
+ AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
+
+ if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
+ rfMode |= (AR_PHY_MODE_DYNAMIC |
+ AR_PHY_MODE_DYN_CCK_DISABLE);
+
+ REG_WRITE(ah, AR_PHY_MODE, rfMode);
+}
+
+static void
+ath9k_hw_mark_phy_inactive(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+}
+
+static inline void
+ath9k_hw_set_dma(struct ath_hal *ah)
+{
+ uint32_t regval;
+
+ regval = REG_READ(ah, AR_AHB_MODE);
+ REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+
+ regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
+ REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
+
+ REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->ah_txTrigLevel);
+
+ regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
+ REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
+
+ REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
+
+ if (AR_SREV_9285(ah)) {
+ REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+ AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
+ } else {
+ REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+ AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+ }
+}
+
+static void
+ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode)
+{
+ uint32_t val;
+
+ val = REG_READ(ah, AR_STA_ID1);
+ val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
+ switch (opmode) {
+ case ATH9K_M_HOSTAP:
+ REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP |
+ AR_STA_ID1_KSRCH_MODE);
+ REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ break;
+ case ATH9K_M_IBSS:
+ REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC |
+ AR_STA_ID1_KSRCH_MODE);
+ REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ break;
+ case ATH9K_M_STA:
+ case ATH9K_M_MONITOR:
+ REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
+ break;
+ }
+}
+
+/* ARGSUSED */
+static inline void
+ath9k_hw_get_delta_slope_vals(struct ath_hal *ah,
+ uint32_t coef_scaled,
+ uint32_t *coef_mantissa,
+ uint32_t *coef_exponent)
+{
+ uint32_t coef_exp, coef_man;
+
+ for (coef_exp = 31; coef_exp > 0; coef_exp--)
+ if ((coef_scaled >> coef_exp) & 0x1)
+ break;
+
+ coef_exp = 14 - (coef_exp - COEF_SCALE_S);
+
+ coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
+
+ *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
+ *coef_exponent = coef_exp - 16;
+}
+
+static void
+ath9k_hw_set_delta_slope(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ uint32_t coef_scaled, ds_coef_exp, ds_coef_man;
+ uint32_t clockMhzScaled = 0x64000000;
+ struct chan_centers centers;
+
+ if (IS_CHAN_HALF_RATE(chan))
+ clockMhzScaled = clockMhzScaled >> 1;
+ else if (IS_CHAN_QUARTER_RATE(chan))
+ clockMhzScaled = clockMhzScaled >> 2;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ coef_scaled = clockMhzScaled / centers.synth_center;
+
+ ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+ &ds_coef_exp);
+
+ REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+ AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+ AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+
+ coef_scaled = (9 * coef_scaled) / 10;
+
+ ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+ &ds_coef_exp);
+
+ REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+ AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
+ REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+ AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
+}
+
+static boolean_t
+ath9k_hw_set_reset(struct ath_hal *ah, int type)
+{
+ uint32_t rst_flags;
+ uint32_t tmpReg;
+
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+ AR_RTC_FORCE_WAKE_ON_INT);
+
+ if (AR_SREV_9100(ah)) {
+ rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
+ AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
+ } else {
+ tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+ if (tmpReg &
+ (AR_INTR_SYNC_LOCAL_TIMEOUT |
+ AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+ REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+ } else {
+ REG_WRITE(ah, AR_RC, AR_RC_AHB);
+ }
+
+ rst_flags = AR_RTC_RC_MAC_WARM;
+ if (type == ATH9K_RESET_COLD)
+ rst_flags |= AR_RTC_RC_MAC_COLD;
+ }
+
+ REG_WRITE(ah, (uint16_t)(AR_RTC_RC), rst_flags);
+ drv_usecwait(50);
+
+ REG_WRITE(ah, (uint16_t)(AR_RTC_RC), 0);
+ if (!ath9k_hw_wait(ah, (uint16_t)(AR_RTC_RC), AR_RTC_RC_M, 0)) {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_set_reset(): "
+ "RTC stuck in MAC reset\n"));
+
+ return (B_FALSE);
+ }
+
+ if (!AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_RC, 0);
+
+ ath9k_hw_init_pll(ah, NULL);
+
+ if (AR_SREV_9100(ah))
+ drv_usecwait(50);
+
+ return (B_TRUE);
+}
+
+static boolean_t
+ath9k_hw_set_reset_power_on(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+ AR_RTC_FORCE_WAKE_ON_INT);
+
+ REG_WRITE(ah, (uint16_t)(AR_RTC_RESET), 0);
+ REG_WRITE(ah, (uint16_t)(AR_RTC_RESET), 1);
+
+ if (!ath9k_hw_wait(ah,
+ AR_RTC_STATUS,
+ AR_RTC_STATUS_M,
+ AR_RTC_STATUS_ON)) {
+ ARN_DBG((ARN_DBG_HW,
+ "arn: ath9k_hw_set_reset_power_on(): "
+ "RTC not waking up \n"));
+
+ return (B_FALSE);
+ }
+
+ ath9k_hw_read_revisions(ah);
+
+ return (ath9k_hw_set_reset(ah, ATH9K_RESET_WARM));
+}
+
+static boolean_t
+ath9k_hw_set_reset_reg(struct ath_hal *ah, uint32_t type)
+{
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+ switch (type) {
+ case ATH9K_RESET_POWER_ON:
+ return (ath9k_hw_set_reset_power_on(ah));
+ case ATH9K_RESET_WARM:
+ case ATH9K_RESET_COLD:
+ return (ath9k_hw_set_reset(ah, type));
+ default:
+ return (B_FALSE);
+ }
+}
+
+static void
+ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode)
+{
+ uint32_t phymode;
+ uint32_t enableDacFifo = 0;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (AR_SREV_9285_10_OR_LATER(ah))
+ enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
+ AR_PHY_FC_ENABLE_DAC_FIFO);
+
+ phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 |
+ AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
+
+ if (IS_CHAN_HT40(chan)) {
+ phymode |= AR_PHY_FC_DYN2040_EN;
+
+ if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+ (chan->chanmode == CHANNEL_G_HT40PLUS))
+ phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+
+ if (ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
+ phymode |= AR_PHY_FC_DYN2040_EXT_CH;
+ }
+ REG_WRITE(ah, AR_PHY_TURBO, phymode);
+
+ ath9k_hw_set11nmac2040(ah, macmode);
+
+ REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+ REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+}
+
+static boolean_t
+ath9k_hw_chip_reset(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+ return (B_FALSE);
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+ return (B_FALSE);
+
+ ahp->ah_chipFullSleep = B_FALSE;
+
+ ath9k_hw_init_pll(ah, chan);
+
+ ath9k_hw_set_rfmode(ah, chan);
+
+ return (B_TRUE);
+}
+
+static struct ath9k_channel *
+ath9k_hw_check_chan(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ if (!(IS_CHAN_2GHZ(chan) ^ IS_CHAN_5GHZ(chan))) {
+ ARN_DBG((ARN_DBG_CHANNEL, "arn: "
+ "%s: invalid channel %u/0x%x; not marked as "
+ "2GHz or 5GHz\n",
+ __func__, chan->channel, chan->channelFlags));
+ return (NULL);
+ }
+
+ if (!IS_CHAN_OFDM(chan) &&
+ !IS_CHAN_B(chan) &&
+ !IS_CHAN_HT20(chan) &&
+ !IS_CHAN_HT40(chan)) {
+ ARN_DBG((ARN_DBG_CHANNEL, "arn: "
+ "%s: invalid channel %u/0x%x; not marked as "
+ "OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n",
+ __func__, chan->channel, chan->channelFlags));
+
+ return (NULL);
+ }
+
+ return (ath9k_regd_check_channel(ah, chan));
+}
+
+static boolean_t
+ath9k_hw_channel_change(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode)
+{
+ uint32_t synthDelay, qnum;
+
+ for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
+ if (ath9k_hw_numtxpending(ah, qnum)) {
+ ARN_DBG((ARN_DBG_QUEUE, "arn: "
+ "%s: Transmit frames pending on queue %d\n",
+ __func__, qnum));
+
+ return (B_FALSE);
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+ if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
+ AR_PHY_RFBUS_GRANT_EN)) {
+ ARN_DBG((ARN_DBG_HW, "arn: "
+ "%s: Could not kill baseband RX\n", __func__));
+
+ return (B_FALSE);
+ }
+
+ ath9k_hw_set_regs(ah, chan, macmode);
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
+ ARN_DBG((ARN_DBG_CHANNEL, "arn: "
+ "%s: failed to set channel\n", __func__));
+ return (B_FALSE);
+ }
+ } else {
+ if (!(ath9k_hw_set_channel(ah, chan))) {
+ ARN_DBG((ARN_DBG_CHANNEL, "arn: "
+ "%s: failed to set channel\n", __func__));
+
+ return (B_FALSE);
+ }
+ }
+
+ if (ath9k_hw_set_txpower(ah, chan,
+ ath9k_regd_get_ctl(ah, chan),
+ ath9k_regd_get_antenna_allowed(ah, chan),
+ chan->maxRegTxPower * 2,
+ min((uint32_t)MAX_RATE_POWER,
+ (uint32_t)ah->ah_powerLimit)) != 0) {
+ ARN_DBG((ARN_DBG_EEPROM, "arn: "
+ "%s: error init'ing transmit power\n", __func__));
+
+ return (B_FALSE);
+ }
+
+ synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+ if (IS_CHAN_B(chan))
+ synthDelay = (4 * synthDelay) / 22;
+ else
+ synthDelay /= 10;
+
+ drv_usecwait(synthDelay + BASE_ACTIVATE_DELAY);
+
+ REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+
+ if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+ ath9k_hw_set_delta_slope(ah, chan);
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ath9k_hw_9280_spur_mitigate(ah, chan);
+ else
+ ath9k_hw_spur_mitigate(ah, chan);
+
+ if (!chan->oneTimeCalsDone)
+ chan->oneTimeCalsDone = B_TRUE;
+
+ return (B_TRUE);
+}
+
+static void
+ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ int bb_spur = AR_NO_SPUR;
+ int freq;
+ int bin, cur_bin;
+ int bb_spur_off, spur_subchannel_sd;
+ int spur_freq_sd;
+ int spur_delta_phase;
+ int denominator;
+ int upper, lower, cur_vit_mask;
+ int tmp, newVal;
+ int i;
+ int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+ AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+ };
+ int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+ AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+ };
+ int inc[4] = { 0, 100, 0, 0 };
+ struct chan_centers centers;
+
+ int8_t mask_m[123];
+ int8_t mask_p[123];
+ int8_t mask_amt;
+ int tmp_mask;
+ int cur_bb_spur;
+ boolean_t is2GHz = IS_CHAN_2GHZ(chan);
+
+ (void) memset(&mask_m, 0, sizeof (int8_t) * 123);
+ (void) memset(&mask_p, 0, sizeof (int8_t) * 123);
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ ah->ah_config.spurmode = SPUR_ENABLE_EEPROM;
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ cur_bb_spur = ath9k_hw_eeprom_get_spur_chan(ah, i, is2GHz);
+
+ if (is2GHz)
+ cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
+ else
+ cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
+
+ if (AR_NO_SPUR == cur_bb_spur)
+ break;
+ cur_bb_spur = cur_bb_spur - freq;
+
+ if (IS_CHAN_HT40(chan)) {
+ if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
+ (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
+ (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ }
+
+ if (AR_NO_SPUR == bb_spur) {
+ REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
+ AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+ return;
+ } else {
+ REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
+ AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+ }
+
+ bin = bb_spur * 320;
+
+ tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+
+ newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+ AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+ AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
+
+ newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+ AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+ AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+ SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+ REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
+
+ if (IS_CHAN_HT40(chan)) {
+ if (bb_spur < 0) {
+ spur_subchannel_sd = 1;
+ bb_spur_off = bb_spur + 10;
+ } else {
+ spur_subchannel_sd = 0;
+ bb_spur_off = bb_spur - 10;
+ }
+ } else {
+ spur_subchannel_sd = 0;
+ bb_spur_off = bb_spur;
+ }
+
+ if (IS_CHAN_HT40(chan))
+ spur_delta_phase =
+ ((bb_spur * 262144) / 10) &
+ AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+ else
+ spur_delta_phase =
+ ((bb_spur * 524288) / 10) &
+ AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+ denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
+ spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
+
+ newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+ SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+ SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+ REG_WRITE(ah, AR_PHY_TIMING11, newVal);
+
+ newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
+ REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
+
+ cur_bin = -6000;
+ upper = bin + 100;
+ lower = bin - 100;
+
+ for (i = 0; i < 4; i++) {
+ int pilot_mask = 0;
+ int chan_mask = 0;
+ int bp = 0;
+ for (bp = 0; bp < 30; bp++) {
+ if ((cur_bin > lower) && (cur_bin < upper)) {
+ pilot_mask = pilot_mask | 0x1 << bp;
+ chan_mask = chan_mask | 0x1 << bp;
+ }
+ cur_bin += 100;
+ }
+ cur_bin += inc[i];
+ REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+ REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+ }
+
+ cur_vit_mask = 6100;
+ upper = bin + 120;
+ lower = bin - 120;
+
+ for (i = 0; i < 123; i++) {
+ if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+
+ /* workaround for gcc bug #37014 */
+ volatile int tmp = abs(cur_vit_mask - bin);
+
+ if (tmp < 75)
+ mask_amt = 1;
+ else
+ mask_amt = 0;
+ if (cur_vit_mask < 0)
+ mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+ else
+ mask_p[cur_vit_mask / 100] = mask_amt;
+ }
+ cur_vit_mask -= 100;
+ }
+
+ tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) |
+ (mask_m[48] << 26) | (mask_m[49] << 24) |
+ (mask_m[50] << 22) | (mask_m[51] << 20) |
+ (mask_m[52] << 18) | (mask_m[53] << 16) |
+ (mask_m[54] << 14) | (mask_m[55] << 12) |
+ (mask_m[56] << 10) | (mask_m[57] << 8) |
+ (mask_m[58] << 6) | (mask_m[59] << 4) |
+ (mask_m[60] << 2) | (mask_m[61] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+ REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+ tmp_mask = (mask_m[31] << 28) |
+ (mask_m[32] << 26) | (mask_m[33] << 24) |
+ (mask_m[34] << 22) | (mask_m[35] << 20) |
+ (mask_m[36] << 18) | (mask_m[37] << 16) |
+ (mask_m[48] << 14) | (mask_m[39] << 12) |
+ (mask_m[40] << 10) | (mask_m[41] << 8) |
+ (mask_m[42] << 6) | (mask_m[43] << 4) |
+ (mask_m[44] << 2) | (mask_m[45] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+ tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) |
+ (mask_m[18] << 26) | (mask_m[18] << 24) |
+ (mask_m[20] << 22) | (mask_m[20] << 20) |
+ (mask_m[22] << 18) | (mask_m[22] << 16) |
+ (mask_m[24] << 14) | (mask_m[24] << 12) |
+ (mask_m[25] << 10) | (mask_m[26] << 8) |
+ (mask_m[27] << 6) | (mask_m[28] << 4) |
+ (mask_m[29] << 2) | (mask_m[30] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+ tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) |
+ (mask_m[2] << 26) | (mask_m[3] << 24) |
+ (mask_m[4] << 22) | (mask_m[5] << 20) |
+ (mask_m[6] << 18) | (mask_m[7] << 16) |
+ (mask_m[8] << 14) | (mask_m[9] << 12) |
+ (mask_m[10] << 10) | (mask_m[11] << 8) |
+ (mask_m[12] << 6) | (mask_m[13] << 4) |
+ (mask_m[14] << 2) | (mask_m[15] << 0);
+ REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+ tmp_mask = (mask_p[15] << 28) |
+ (mask_p[14] << 26) | (mask_p[13] << 24) |
+ (mask_p[12] << 22) | (mask_p[11] << 20) |
+ (mask_p[10] << 18) | (mask_p[9] << 16) |
+ (mask_p[8] << 14) | (mask_p[7] << 12) |
+ (mask_p[6] << 10) | (mask_p[5] << 8) |
+ (mask_p[4] << 6) | (mask_p[3] << 4) |
+ (mask_p[2] << 2) | (mask_p[1] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+ tmp_mask = (mask_p[30] << 28) |
+ (mask_p[29] << 26) | (mask_p[28] << 24) |
+ (mask_p[27] << 22) | (mask_p[26] << 20) |
+ (mask_p[25] << 18) | (mask_p[24] << 16) |
+ (mask_p[23] << 14) | (mask_p[22] << 12) |
+ (mask_p[21] << 10) | (mask_p[20] << 8) |
+ (mask_p[19] << 6) | (mask_p[18] << 4) |
+ (mask_p[17] << 2) | (mask_p[16] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+ tmp_mask = (mask_p[45] << 28) |
+ (mask_p[44] << 26) | (mask_p[43] << 24) |
+ (mask_p[42] << 22) | (mask_p[41] << 20) |
+ (mask_p[40] << 18) | (mask_p[39] << 16) |
+ (mask_p[38] << 14) | (mask_p[37] << 12) |
+ (mask_p[36] << 10) | (mask_p[35] << 8) |
+ (mask_p[34] << 6) | (mask_p[33] << 4) |
+ (mask_p[32] << 2) | (mask_p[31] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+ tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) |
+ (mask_p[59] << 26) | (mask_p[58] << 24) |
+ (mask_p[57] << 22) | (mask_p[56] << 20) |
+ (mask_p[55] << 18) | (mask_p[54] << 16) |
+ (mask_p[53] << 14) | (mask_p[52] << 12) |
+ (mask_p[51] << 10) | (mask_p[50] << 8) |
+ (mask_p[49] << 6) | (mask_p[48] << 4) |
+ (mask_p[47] << 2) | (mask_p[46] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+static void
+ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ int bb_spur = AR_NO_SPUR;
+ int bin, cur_bin;
+ int spur_freq_sd;
+ int spur_delta_phase;
+ int denominator;
+ int upper, lower, cur_vit_mask;
+ int tmp, new;
+ int i;
+ int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+ AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+ };
+ int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+ AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+ };
+ int inc[4] = { 0, 100, 0, 0 };
+
+ int8_t mask_m[123];
+ int8_t mask_p[123];
+ int8_t mask_amt;
+ int tmp_mask;
+ int cur_bb_spur;
+ boolean_t is2GHz = IS_CHAN_2GHZ(chan);
+
+ (void) memset(&mask_m, 0, sizeof (int8_t) * 123);
+ (void) memset(&mask_p, 0, sizeof (int8_t) * 123);
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ cur_bb_spur = ath9k_hw_eeprom_get_spur_chan(ah, i, is2GHz);
+ if (AR_NO_SPUR == cur_bb_spur)
+ break;
+ cur_bb_spur = cur_bb_spur - (chan->channel * 10);
+ if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ }
+
+ if (AR_NO_SPUR == bb_spur)
+ return;
+
+ bin = bb_spur * 32;
+
+ tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+ new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+ AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+ AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
+
+ new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+ AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+ AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+ SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+ REG_WRITE(ah, AR_PHY_SPUR_REG, new);
+
+ spur_delta_phase = ((bb_spur * 524288) / 100) &
+ AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+ denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
+ spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
+
+ new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+ SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+ SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+ REG_WRITE(ah, AR_PHY_TIMING11, new);
+
+ cur_bin = -6000;
+ upper = bin + 100;
+ lower = bin - 100;
+
+ for (i = 0; i < 4; i++) {
+ int pilot_mask = 0;
+ int chan_mask = 0;
+ int bp = 0;
+ for (bp = 0; bp < 30; bp++) {
+ if ((cur_bin > lower) && (cur_bin < upper)) {
+ pilot_mask = pilot_mask | 0x1 << bp;
+ chan_mask = chan_mask | 0x1 << bp;
+ }
+ cur_bin += 100;
+ }
+ cur_bin += inc[i];
+ REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+ REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+ }
+
+ cur_vit_mask = 6100;
+ upper = bin + 120;
+ lower = bin - 120;
+
+ for (i = 0; i < 123; i++) {
+ if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+
+ /* workaround for gcc bug #37014 */
+ volatile int tmp = abs(cur_vit_mask - bin);
+
+ if (tmp < 75)
+ mask_amt = 1;
+ else
+ mask_amt = 0;
+ if (cur_vit_mask < 0)
+ mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+ else
+ mask_p[cur_vit_mask / 100] = mask_amt;
+ }
+ cur_vit_mask -= 100;
+ }
+
+ tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) |
+ (mask_m[48] << 26) | (mask_m[49] << 24) |
+ (mask_m[50] << 22) | (mask_m[51] << 20) |
+ (mask_m[52] << 18) | (mask_m[53] << 16) |
+ (mask_m[54] << 14) | (mask_m[55] << 12) |
+ (mask_m[56] << 10) | (mask_m[57] << 8) |
+ (mask_m[58] << 6) | (mask_m[59] << 4) |
+ (mask_m[60] << 2) | (mask_m[61] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+ REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+ tmp_mask = (mask_m[31] << 28) |
+ (mask_m[32] << 26) | (mask_m[33] << 24) |
+ (mask_m[34] << 22) | (mask_m[35] << 20) |
+ (mask_m[36] << 18) | (mask_m[37] << 16) |
+ (mask_m[48] << 14) | (mask_m[39] << 12) |
+ (mask_m[40] << 10) | (mask_m[41] << 8) |
+ (mask_m[42] << 6) | (mask_m[43] << 4) |
+ (mask_m[44] << 2) | (mask_m[45] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+ tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) |
+ (mask_m[18] << 26) | (mask_m[18] << 24) |
+ (mask_m[20] << 22) | (mask_m[20] << 20) |
+ (mask_m[22] << 18) | (mask_m[22] << 16) |
+ (mask_m[24] << 14) | (mask_m[24] << 12) |
+ (mask_m[25] << 10) | (mask_m[26] << 8) |
+ (mask_m[27] << 6) | (mask_m[28] << 4) |
+ (mask_m[29] << 2) | (mask_m[30] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+ tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) |
+ (mask_m[2] << 26) | (mask_m[3] << 24) |
+ (mask_m[4] << 22) | (mask_m[5] << 20) |
+ (mask_m[6] << 18) | (mask_m[7] << 16) |
+ (mask_m[8] << 14) | (mask_m[9] << 12) |
+ (mask_m[10] << 10) | (mask_m[11] << 8) |
+ (mask_m[12] << 6) | (mask_m[13] << 4) |
+ (mask_m[14] << 2) | (mask_m[15] << 0);
+ REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+ tmp_mask = (mask_p[15] << 28) |
+ (mask_p[14] << 26) | (mask_p[13] << 24) |
+ (mask_p[12] << 22) | (mask_p[11] << 20) |
+ (mask_p[10] << 18) | (mask_p[9] << 16) |
+ (mask_p[8] << 14) | (mask_p[7] << 12) |
+ (mask_p[6] << 10) | (mask_p[5] << 8) |
+ (mask_p[4] << 6) | (mask_p[3] << 4) |
+ (mask_p[2] << 2) | (mask_p[1] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+ tmp_mask = (mask_p[30] << 28) |
+ (mask_p[29] << 26) | (mask_p[28] << 24) |
+ (mask_p[27] << 22) | (mask_p[26] << 20) |
+ (mask_p[25] << 18) | (mask_p[24] << 16) |
+ (mask_p[23] << 14) | (mask_p[22] << 12) |
+ (mask_p[21] << 10) | (mask_p[20] << 8) |
+ (mask_p[19] << 6) | (mask_p[18] << 4) |
+ (mask_p[17] << 2) | (mask_p[16] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+ tmp_mask = (mask_p[45] << 28) |
+ (mask_p[44] << 26) | (mask_p[43] << 24) |
+ (mask_p[42] << 22) | (mask_p[41] << 20) |
+ (mask_p[40] << 18) | (mask_p[39] << 16) |
+ (mask_p[38] << 14) | (mask_p[37] << 12) |
+ (mask_p[36] << 10) | (mask_p[35] << 8) |
+ (mask_p[34] << 6) | (mask_p[33] << 4) |
+ (mask_p[32] << 2) | (mask_p[31] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+ tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) |
+ (mask_p[59] << 26) | (mask_p[58] << 24) |
+ (mask_p[57] << 22) | (mask_p[56] << 20) |
+ (mask_p[55] << 18) | (mask_p[54] << 16) |
+ (mask_p[53] << 14) | (mask_p[52] << 12) |
+ (mask_p[51] << 10) | (mask_p[50] << 8) |
+ (mask_p[49] << 6) | (mask_p[48] << 4) |
+ (mask_p[47] << 2) | (mask_p[46] << 0);
+ REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+ REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+boolean_t
+ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode,
+ uint8_t txchainmask, uint8_t rxchainmask,
+ enum ath9k_ht_extprotspacing extprotspacing,
+ boolean_t bChannelChange, int *status)
+{
+ uint32_t saveLedState;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *curchan = ah->ah_curchan;
+ uint32_t saveDefAntenna;
+ uint32_t macStaId1;
+ int ecode;
+ int i, rx_chainmask;
+
+ ahp->ah_extprotspacing = extprotspacing;
+ ahp->ah_txchainmask = txchainmask;
+ ahp->ah_rxchainmask = rxchainmask;
+
+ if (AR_SREV_9280(ah)) {
+ ahp->ah_txchainmask &= 0x3;
+ ahp->ah_rxchainmask &= 0x3;
+ }
+
+ if (ath9k_hw_check_chan(ah, chan) == NULL) {
+ ARN_DBG((ARN_DBG_ANY, "arn: "
+ "%s: invalid channel %u/0x%x; no mapping\n",
+ __func__, chan->channel, chan->channelFlags));
+ ecode = EINVAL;
+ goto bad;
+ }
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
+ ARN_DBG((ARN_DBG_ANY, "arn: "
+ "%s: ath9k_hw_setpower failed!!!\n", __func__));
+ ecode = EIO;
+ goto bad;
+ }
+
+ if (curchan)
+ (void) ath9k_hw_getnf(ah, curchan);
+
+ if (bChannelChange &&
+ (ahp->ah_chipFullSleep != B_TRUE) &&
+ (ah->ah_curchan != NULL) &&
+ (chan->channel != ah->ah_curchan->channel) &&
+ ((chan->channelFlags & CHANNEL_ALL) ==
+ (ah->ah_curchan->channelFlags & CHANNEL_ALL)) &&
+ (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
+ !IS_CHAN_A_5MHZ_SPACED(ah->ah_curchan)))) {
+
+ if (ath9k_hw_channel_change(ah, chan, macmode)) {
+ ath9k_hw_loadnf(ah, ah->ah_curchan);
+ ath9k_hw_start_nfcal(ah);
+ return (B_TRUE);
+ }
+ }
+
+ saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
+ if (saveDefAntenna == 0)
+ saveDefAntenna = 1;
+
+ macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
+
+ saveLedState = REG_READ(ah, AR_CFG_LED) &
+ (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
+ AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
+
+ ath9k_hw_mark_phy_inactive(ah);
+
+ if (!ath9k_hw_chip_reset(ah, chan)) {
+ ARN_DBG((ARN_DBG_RESET, "arn: "
+ "%s: chip reset failed\n", __func__));
+ ecode = EINVAL;
+ goto bad;
+ }
+
+ if (AR_SREV_9280(ah)) {
+ REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+ AR_GPIO_JTAG_DISABLE);
+ if (is_set(ATH9K_MODE_11A, ah->ah_caps.wireless_modes)) {
+ if (IS_CHAN_5GHZ(chan))
+ ath9k_hw_set_gpio(ah, 9, 0);
+ else
+ ath9k_hw_set_gpio(ah, 9, 1);
+ }
+ ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ }
+
+ ecode = ath9k_hw_process_ini(ah, chan, macmode);
+ if (ecode != 0) {
+ ecode = EINVAL;
+ goto bad;
+ }
+
+ if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+ ath9k_hw_set_delta_slope(ah, chan);
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ath9k_hw_9280_spur_mitigate(ah, chan);
+ else
+ ath9k_hw_spur_mitigate(ah, chan);
+
+ if (!ath9k_hw_eeprom_set_board_values(ah, chan)) {
+ ARN_DBG((ARN_DBG_EEPROM, "arn: "
+ "%s: error setting board options\n", __func__));
+ ecode = EIO;
+ goto bad;
+ }
+
+ ath9k_hw_decrease_chain_power(ah, chan);
+
+ REG_WRITE(ah, AR_STA_ID0, ARN_LE_READ_32(ahp->ah_macaddr));
+ REG_WRITE(ah, AR_STA_ID1, ARN_LE_READ_16(ahp->ah_macaddr + 4) |
+ macStaId1 |
+ AR_STA_ID1_RTS_USE_DEF |
+ (ah->ah_config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) |
+ ahp->ah_staId1Defaults);
+ ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
+
+ REG_WRITE(ah, AR_BSSMSKL, ARN_LE_READ_32(ahp->ah_bssidmask));
+ REG_WRITE(ah, AR_BSSMSKU, ARN_LE_READ_16(ahp->ah_bssidmask + 4));
+
+ REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+
+ REG_WRITE(ah, AR_BSS_ID0, ARN_LE_READ_32(ahp->ah_bssid));
+ REG_WRITE(ah, AR_BSS_ID1, ARN_LE_READ_16(ahp->ah_bssid + 4) |
+ ((ahp->ah_assocId & 0x3fff) << AR_BSS_ID1_AID_S));
+
+ REG_WRITE(ah, AR_ISR, ~0);
+
+ REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: "
+ "%s: ath9k_hw_ar9280_set_channel failed!!!\n",
+ __func__));
+ ecode = EIO;
+ goto bad;
+ }
+ } else {
+ if (!(ath9k_hw_set_channel(ah, chan))) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: "
+ "%s: ath9k_hw_set_channel failed!!!\n", __func__));
+ ecode = EIO;
+ goto bad;
+ }
+ }
+
+ for (i = 0; i < AR_NUM_DCU; i++)
+ REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+ ahp->ah_intrTxqs = 0;
+ for (i = 0; i < ah->ah_caps.total_queues; i++)
+ (void) ath9k_hw_resettxqueue(ah, i);
+
+ ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode);
+ ath9k_hw_init_qos(ah);
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ ath9k_enable_rfkill(ah);
+#endif
+ ath9k_hw_init_user_settings(ah);
+
+ REG_WRITE(ah, AR_STA_ID1,
+ REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
+
+ ath9k_hw_set_dma(ah);
+
+ REG_WRITE(ah, AR_OBS, 8);
+
+ if (ahp->ah_intrMitigation) {
+
+ REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
+ REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
+ }
+
+ ath9k_hw_init_bb(ah, chan);
+
+ if (!ath9k_hw_init_cal(ah, chan)) {
+ ecode = EIO;
+ goto bad;
+ }
+
+ rx_chainmask = ahp->ah_rxchainmask;
+ if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+ }
+
+ REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
+
+ if (AR_SREV_9100(ah)) {
+ uint32_t mask;
+ mask = REG_READ(ah, AR_CFG);
+ if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
+ ARN_DBG((ARN_DBG_RESET, "arn: "
+ "%s CFG Byte Swap Set 0x%x\n",
+ __func__, mask));
+ } else {
+ mask = INIT_CONFIG_STATUS |
+ AR_CFG_SWRB | AR_CFG_SWTB;
+ REG_WRITE(ah, AR_CFG, mask);
+ ARN_DBG((ARN_DBG_RESET, "arn: "
+ "%s Setting CFG 0x%x\n",
+ __func__, REG_READ(ah, AR_CFG)));
+ }
+ } else {
+ ARN_DBG((ARN_DBG_HW, "arn: ath9k_hw_keyreset(): "
+ "#ifdef __BIG_ENDIAN \n"));
+#ifdef __BIG_ENDIAN
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+#endif
+ }
+
+ return (B_TRUE);
+bad:
+ if (status)
+ *status = ecode;
+ return (B_FALSE);
+}
+
+/* Key Cache Management */
+
+boolean_t
+ath9k_hw_keyreset(struct ath_hal *ah, uint16_t entry)
+{
+ uint32_t keyType;
+
+ if (entry >= ah->ah_caps.keycache_size) {
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn: ath9k_hw_keyreset(): "
+ "entry %u out of range\n", entry));
+
+ return (B_FALSE);
+ }
+
+ keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
+
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+
+ if (keyType == AR_KEYTABLE_TYPE_TKIP &&
+ ATH9K_IS_MIC_ENABLED(ah)) {
+ uint16_t micentry = entry + 64;
+
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+
+ }
+
+ if (ah->ah_curchan == NULL)
+ return (B_TRUE);
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_keysetmac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac)
+{
+ uint32_t macHi, macLo;
+
+ if (entry >= ah->ah_caps.keycache_size) {
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn: "
+ "%s: entry %u out of range\n", __func__, entry));
+ return (B_FALSE);
+ }
+
+ if (mac != NULL) {
+ macHi = (mac[5] << 8) | mac[4];
+ macLo = (mac[3] << 24) |
+ (mac[2] << 16) |
+ (mac[1] << 8) |
+ mac[0];
+ macLo >>= 1;
+ macLo |= (macHi & 1) << 31;
+ macHi >>= 1;
+ } else {
+ macLo = macHi = 0;
+ }
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_set_keycache_entry(struct ath_hal *ah, uint16_t entry,
+ const struct ath9k_keyval *k, const uint8_t *mac, int xorKey)
+{
+ const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ uint32_t key0, key1, key2, key3, key4;
+ uint32_t keyType;
+ uint32_t xorMask = xorKey ?
+ (ATH9K_KEY_XOR << 24 | ATH9K_KEY_XOR << 16 |
+ ATH9K_KEY_XOR << 8 | ATH9K_KEY_XOR) : 0;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (entry >= pCap->keycache_size) {
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn: "
+ "%s: entry %u out of range\n", __func__, entry));
+ return (B_FALSE);
+ }
+
+ switch (k->kv_type) {
+ case ATH9K_CIPHER_AES_OCB:
+ keyType = AR_KEYTABLE_TYPE_AES;
+ break;
+ case ATH9K_CIPHER_AES_CCM:
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn: "
+ "%s: AES-CCM not supported by "
+ "mac rev 0x%x\n", __func__,
+ ah->ah_macRev));
+ return (B_FALSE);
+ }
+ keyType = AR_KEYTABLE_TYPE_CCM;
+ break;
+ case ATH9K_CIPHER_TKIP:
+ keyType = AR_KEYTABLE_TYPE_TKIP;
+ if (ATH9K_IS_MIC_ENABLED(ah) &&
+ entry + 64 >= pCap->keycache_size) {
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn: "
+ "%s: entry %u inappropriate for TKIP\n",
+ __func__, entry));
+ return (B_FALSE);
+ }
+ break;
+ case ATH9K_CIPHER_WEP:
+ if (k->kv_len < ATH9K_LEN_WEP40) {
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn: "
+ "%s: WEP key length %u too small\n",
+ __func__, k->kv_len));
+ return (B_FALSE);
+ }
+ if (k->kv_len <= ATH9K_LEN_WEP40)
+ keyType = AR_KEYTABLE_TYPE_40;
+ else if (k->kv_len <= ATH9K_LEN_WEP104)
+ keyType = AR_KEYTABLE_TYPE_104;
+ else
+ keyType = AR_KEYTABLE_TYPE_128;
+ break;
+ case ATH9K_CIPHER_CLR:
+ keyType = AR_KEYTABLE_TYPE_CLR;
+ break;
+ default:
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn: "
+ "%s: cipher %u not supported\n", __func__,
+ k->kv_type));
+ return (B_FALSE);
+ }
+
+ key0 = ARN_LE_READ_32(k->kv_val + 0) ^ xorMask;
+ key1 = (ARN_LE_READ_16(k->kv_val + 4) ^ xorMask) & 0xffff;
+ key2 = ARN_LE_READ_32(k->kv_val + 6) ^ xorMask;
+ key3 = (ARN_LE_READ_16(k->kv_val + 10) ^ xorMask) & 0xffff;
+ key4 = ARN_LE_READ_32(k->kv_val + 12) ^ xorMask;
+
+ if (k->kv_len <= ATH9K_LEN_WEP104)
+ key4 &= 0xff;
+
+ if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
+ uint16_t micentry = entry + 64;
+
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+ (void) ath9k_hw_keysetmac(ah, entry, mac);
+
+ if (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) {
+ uint32_t mic0, mic1, mic2, mic3, mic4;
+ mic0 = ARN_LE_READ_32(k->kv_mic + 0);
+ mic2 = ARN_LE_READ_32(k->kv_mic + 4);
+ mic1 = ARN_LE_READ_16(k->kv_txmic + 2) & 0xffff;
+ mic3 = ARN_LE_READ_16(k->kv_txmic + 0) & 0xffff;
+ mic4 = ARN_LE_READ_32(k->kv_txmic + 4);
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+ AR_KEYTABLE_TYPE_CLR);
+
+ } else {
+ uint32_t mic0, mic2;
+ mic0 = ARN_LE_READ_32(k->kv_mic + 0);
+ mic2 = ARN_LE_READ_32(k->kv_mic + 4);
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+ AR_KEYTABLE_TYPE_CLR);
+ }
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+ } else {
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+ (void) ath9k_hw_keysetmac(ah, entry, mac);
+ }
+
+ if (ah->ah_curchan == NULL)
+ return (B_TRUE);
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_keyisvalid(struct ath_hal *ah, uint16_t entry)
+{
+ if (entry < ah->ah_caps.keycache_size) {
+ uint32_t val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
+ if (val & AR_KEYTABLE_VALID)
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
+/* Power Management (Chipset) */
+
+static void
+ath9k_set_power_sleep(struct ath_hal *ah, int setChip)
+{
+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+ if (setChip) {
+ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ if (!AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+
+ REG_CLR_BIT(ah, (uint16_t)(AR_RTC_RESET),
+ AR_RTC_RESET_EN);
+ }
+}
+
+static void
+ath9k_set_power_network_sleep(struct ath_hal *ah, int setChip)
+{
+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+ if (setChip) {
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_ON_INT);
+ } else {
+ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ }
+ }
+}
+
+static boolean_t
+ath9k_hw_set_power_awake(struct ath_hal *ah, int setChip)
+{
+ uint32_t val;
+ int i;
+
+ if (setChip) {
+ if ((REG_READ(ah, AR_RTC_STATUS) &
+ AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
+ if (ath9k_hw_set_reset_reg(ah,
+ ATH9K_RESET_POWER_ON) != B_TRUE) {
+ return (B_FALSE);
+ }
+ }
+ if (AR_SREV_9100(ah))
+ REG_SET_BIT(ah, AR_RTC_RESET,
+ AR_RTC_RESET_EN);
+
+ REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ drv_usecwait(50);
+
+ for (i = POWER_UP_TIME / 50; i > 0; i--) {
+ val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
+ if (val == AR_RTC_STATUS_ON)
+ break;
+ drv_usecwait(50);
+ REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ }
+ if (i == 0) {
+ ARN_DBG((ARN_DBG_POWER_MGMT,
+ "arn: ath9k_hw_set_power_awake(): "
+ "Failed to wakeup in %uus\n",
+ POWER_UP_TIME / 20));
+
+ return (B_FALSE);
+ }
+ }
+
+ REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_setpower(struct ath_hal *ah, enum ath9k_power_mode mode)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ static const char *modes[] = {
+ "AWAKE",
+ "FULL-SLEEP",
+ "NETWORK SLEEP",
+ "UNDEFINED"
+ };
+ int status = B_TRUE, setChip = B_TRUE;
+ ARN_DBG((ARN_DBG_ANY, "arn: ath9k_hw_setpower(): "
+ "%s -> %s (%s)\n",
+ modes[ahp->ah_powerMode],
+ modes[mode],
+ setChip ? "set chip " : ""));
+
+ switch (mode) {
+ case ATH9K_PM_AWAKE:
+ status = ath9k_hw_set_power_awake(ah, setChip);
+ break;
+ case ATH9K_PM_FULL_SLEEP:
+ ath9k_set_power_sleep(ah, setChip);
+ ahp->ah_chipFullSleep = B_TRUE;
+ break;
+ case ATH9K_PM_NETWORK_SLEEP:
+ ath9k_set_power_network_sleep(ah, setChip);
+ break;
+ default:
+ ARN_DBG((ARN_DBG_ANY, "arn: ath9k_hw_setpower(): "
+ "unknown power mode %u\n", mode));
+ return (B_FALSE);
+ }
+ ahp->ah_powerMode = mode;
+
+ return (status);
+}
+
+void
+ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint8_t i;
+
+ if (ah->ah_isPciExpress != B_TRUE)
+ return;
+
+ if (ah->ah_config.pcie_powersave_enable == 2)
+ return;
+
+ if (restore)
+ return;
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ for (i = 0; i < ahp->ah_iniPcieSerdes.ia_rows; i++) {
+ REG_WRITE(ah, INI_RA(&ahp->ah_iniPcieSerdes, i, 0),
+ INI_RA(&ahp->ah_iniPcieSerdes, i, 1));
+ }
+ drv_usecwait(1000);
+ } else if (AR_SREV_9280(ah) &&
+ (ah->ah_macRev == AR_SREV_REVISION_9280_10)) {
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
+
+ if (ah->ah_config.pcie_clock_req)
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
+ else
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
+
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
+
+ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+
+ drv_usecwait(1000);
+ } else {
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
+ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+ }
+
+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+ if (ah->ah_config.pcie_waen) {
+ REG_WRITE(ah, AR_WA, ah->ah_config.pcie_waen);
+ } else {
+ if (AR_SREV_9285(ah))
+ REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
+ else if (AR_SREV_9280(ah))
+ REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
+ else
+ REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);
+ }
+}
+
+/* Interrupt Handling */
+
+boolean_t
+ath9k_hw_intrpend(struct ath_hal *ah)
+{
+ uint32_t host_isr;
+
+ if (AR_SREV_9100(ah))
+ return (B_TRUE);
+
+ host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
+ if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
+ return (B_TRUE);
+
+ host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+
+ if ((host_isr & AR_INTR_SYNC_DEFAULT) &&
+ (host_isr != AR_INTR_SPURIOUS))
+ return (B_TRUE);
+
+ return (B_FALSE);
+}
+
+boolean_t
+ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
+{
+ uint32_t isr = 0;
+ uint32_t mask2 = 0;
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ uint32_t sync_cause = 0;
+ boolean_t fatal_int = B_FALSE;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (!AR_SREV_9100(ah)) {
+ if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
+ if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
+ == AR_RTC_STATUS_ON) {
+ isr = REG_READ(ah, AR_ISR);
+ }
+ }
+
+ sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
+ AR_INTR_SYNC_DEFAULT;
+
+ *masked = 0;
+
+ if (!isr && !sync_cause)
+ return (B_FALSE);
+ } else {
+ *masked = 0;
+ isr = REG_READ(ah, AR_ISR);
+ }
+
+ if (isr) {
+ if (isr & AR_ISR_BCNMISC) {
+ uint32_t isr2;
+ isr2 = REG_READ(ah, AR_ISR_S2);
+ if (isr2 & AR_ISR_S2_TIM)
+ mask2 |= ATH9K_INT_TIM;
+ if (isr2 & AR_ISR_S2_DTIM)
+ mask2 |= ATH9K_INT_DTIM;
+ if (isr2 & AR_ISR_S2_DTIMSYNC)
+ mask2 |= ATH9K_INT_DTIMSYNC;
+ if (isr2 & (AR_ISR_S2_CABEND))
+ mask2 |= ATH9K_INT_CABEND;
+ if (isr2 & AR_ISR_S2_GTT)
+ mask2 |= ATH9K_INT_GTT;
+ if (isr2 & AR_ISR_S2_CST)
+ mask2 |= ATH9K_INT_CST;
+ }
+
+ isr = REG_READ(ah, AR_ISR_RAC);
+ if (isr == 0xffffffff) {
+ *masked = 0;
+ return (B_FALSE);
+ }
+
+ *masked = isr & ATH9K_INT_COMMON;
+
+ if (ahp->ah_intrMitigation) {
+ if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+ *masked |= ATH9K_INT_RX;
+ }
+
+ if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+ *masked |= ATH9K_INT_RX;
+ if (isr &
+ (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
+ AR_ISR_TXEOL)) {
+ uint32_t s0_s, s1_s;
+
+ *masked |= ATH9K_INT_TX;
+
+ s0_s = REG_READ(ah, AR_ISR_S0_S);
+ ahp->ah_intrTxqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
+ ahp->ah_intrTxqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
+
+ s1_s = REG_READ(ah, AR_ISR_S1_S);
+ ahp->ah_intrTxqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
+ ahp->ah_intrTxqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
+ }
+
+ if (isr & AR_ISR_RXORN) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: "
+ "%s: receive FIFO overrun interrupt\n", __func__));
+ }
+
+ if (!AR_SREV_9100(ah)) {
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+ uint32_t isr5 = REG_READ(ah, AR_ISR_S5_S);
+ if (isr5 & AR_ISR_S5_TIM_TIMER)
+ *masked |= ATH9K_INT_TIM_TIMER;
+ }
+ }
+
+ *masked |= mask2;
+ }
+
+ if (AR_SREV_9100(ah))
+ return (B_TRUE);
+
+ if (sync_cause) {
+ fatal_int = (sync_cause &
+ (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) ?
+ B_TRUE : B_FALSE;
+
+ if (fatal_int) {
+ if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: "
+ "%s: received PCI FATAL interrupt\n",
+ __func__));
+ }
+ if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: "
+ "%s: received PCI PERR interrupt\n",
+ __func__));
+ }
+ }
+ if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: "
+ "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
+ __func__));
+
+ REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
+ REG_WRITE(ah, AR_RC, 0);
+ *masked |= ATH9K_INT_FATAL;
+ }
+ if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
+ ARN_DBG((ARN_DBG_ANY, "arn: "
+ "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
+ __func__));
+ }
+
+ REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+ (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
+ }
+
+ return (B_TRUE);
+}
+
+enum ath9k_int
+ath9k_hw_intrget(struct ath_hal *ah)
+{
+ return (AH5416(ah)->ah_maskReg);
+}
+
+enum ath9k_int
+ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t omask = ahp->ah_maskReg;
+ uint32_t mask, mask2;
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+ ARN_DBG((ARN_DBG_INTERRUPT,
+ "arn: ath9k_hw_set_interrupts(): "
+ "0x%x => 0x%x\n", omask, ints));
+
+ if (omask & ATH9K_INT_GLOBAL) {
+ ARN_DBG((ARN_DBG_INTERRUPT,
+ "arn: ath9k_hw_set_interrupts(): "
+ "disable IER\n"));
+
+ REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+ (void) REG_READ(ah, AR_IER);
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+ (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+ (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+ }
+ }
+
+ mask = ints & ATH9K_INT_COMMON;
+ mask2 = 0;
+
+ if (ints & ATH9K_INT_TX) {
+ if (ahp->ah_txOkInterruptMask)
+ mask |= AR_IMR_TXOK;
+ if (ahp->ah_txDescInterruptMask)
+ mask |= AR_IMR_TXDESC;
+ if (ahp->ah_txErrInterruptMask)
+ mask |= AR_IMR_TXERR;
+ if (ahp->ah_txEolInterruptMask)
+ mask |= AR_IMR_TXEOL;
+ }
+ if (ints & ATH9K_INT_RX) {
+ mask |= AR_IMR_RXERR;
+ if (ahp->ah_intrMitigation)
+ mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
+ else
+ mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+ mask |= AR_IMR_GENTMR;
+ }
+
+ if (ints & (ATH9K_INT_BMISC)) {
+ mask |= AR_IMR_BCNMISC;
+ if (ints & ATH9K_INT_TIM)
+ mask2 |= AR_IMR_S2_TIM;
+ if (ints & ATH9K_INT_DTIM)
+ mask2 |= AR_IMR_S2_DTIM;
+ if (ints & ATH9K_INT_DTIMSYNC)
+ mask2 |= AR_IMR_S2_DTIMSYNC;
+ if (ints & ATH9K_INT_CABEND)
+ mask2 |= (AR_IMR_S2_CABEND);
+ }
+
+ if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
+ mask |= AR_IMR_BCNMISC;
+ if (ints & ATH9K_INT_GTT)
+ mask2 |= AR_IMR_S2_GTT;
+ if (ints & ATH9K_INT_CST)
+ mask2 |= AR_IMR_S2_CST;
+ }
+
+ REG_WRITE(ah, AR_IMR, mask);
+ mask = REG_READ(ah, AR_IMR_S2) &
+ ~(AR_IMR_S2_TIM |
+ AR_IMR_S2_DTIM |
+ AR_IMR_S2_DTIMSYNC |
+ AR_IMR_S2_CABEND |
+ AR_IMR_S2_CABTO |
+ AR_IMR_S2_TSFOOR |
+ AR_IMR_S2_GTT |
+ AR_IMR_S2_CST);
+ REG_WRITE(ah, AR_IMR_S2, mask | mask2);
+ ahp->ah_maskReg = ints;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+ if (ints & ATH9K_INT_TIM_TIMER)
+ REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+ else
+ REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+ }
+
+ if (ints & ATH9K_INT_GLOBAL) {
+ REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
+ AR_INTR_MAC_IRQ);
+ REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
+ AR_INTR_SYNC_DEFAULT);
+ REG_WRITE(ah, AR_INTR_SYNC_MASK,
+ AR_INTR_SYNC_DEFAULT);
+ }
+
+ }
+
+ return (omask);
+}
+
+/* Beacon Handling */
+
+void
+ath9k_hw_beaconinit(struct ath_hal *ah, uint32_t next_beacon,
+ uint32_t beacon_period)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int flags = 0;
+
+ ahp->ah_beaconInterval = beacon_period;
+
+ switch (ah->ah_opmode) {
+ case ATH9K_M_STA:
+ case ATH9K_M_MONITOR:
+ REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
+ REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
+ REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
+ flags |= AR_TBTT_TIMER_EN;
+ break;
+ case ATH9K_M_IBSS:
+ REG_SET_BIT(ah, AR_TXCFG,
+ AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
+ REG_WRITE(ah, AR_NEXT_NDP_TIMER,
+ TU_TO_USEC(next_beacon +
+ (ahp->ah_atimWindow ? ahp->
+ ah_atimWindow : 1)));
+ flags |= AR_NDP_TIMER_EN;
+ /*FALLTHRU*/
+ case ATH9K_M_HOSTAP:
+ REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
+ REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
+ TU_TO_USEC(next_beacon -
+ ah->ah_config.
+ dma_beacon_response_time));
+ REG_WRITE(ah, AR_NEXT_SWBA,
+ TU_TO_USEC(next_beacon -
+ ah->ah_config.
+ sw_beacon_response_time));
+ flags |=
+ AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
+ break;
+ default:
+ ARN_DBG((ARN_DBG_BEACON,
+ "%s: unsupported opmode: %d\n",
+ __func__, ah->ah_opmode));
+ return;
+ }
+
+ REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period));
+ REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period));
+ REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));
+ REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
+
+ beacon_period &= ~ATH9K_BEACON_ENA;
+ if (beacon_period & ATH9K_BEACON_RESET_TSF) {
+ beacon_period &= ~ATH9K_BEACON_RESET_TSF;
+ ath9k_hw_reset_tsf(ah);
+ }
+
+ REG_SET_BIT(ah, AR_TIMER_MODE, flags);
+}
+
+void
+ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
+ const struct ath9k_beacon_state *bs)
+{
+ uint32_t nextTbtt, beaconintval, dtimperiod, beacontimeout;
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+ REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
+
+ REG_WRITE(ah, AR_BEACON_PERIOD,
+ TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+ REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
+ TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+
+ REG_RMW_FIELD(ah, AR_RSSI_THR,
+ AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
+
+ beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
+
+ if (bs->bs_sleepduration > beaconintval)
+ beaconintval = bs->bs_sleepduration;
+
+ dtimperiod = bs->bs_dtimperiod;
+ if (bs->bs_sleepduration > dtimperiod)
+ dtimperiod = bs->bs_sleepduration;
+
+ if (beaconintval == dtimperiod)
+ nextTbtt = bs->bs_nextdtim;
+ else
+ nextTbtt = bs->bs_nexttbtt;
+
+ ARN_DBG((ARN_DBG_BEACON, "arn: "
+ "%s: next DTIM %d\n", __func__, bs->bs_nextdtim));
+ ARN_DBG((ARN_DBG_BEACON, "arn: "
+ "%s: next beacon %d\n", __func__, nextTbtt));
+ ARN_DBG((ARN_DBG_BEACON, "arn: "
+ "%s: beacon period %d\n", __func__, beaconintval));
+ ARN_DBG((ARN_DBG_BEACON, "arn: "
+ "%s: DTIM period %d\n", __func__, dtimperiod));
+
+ REG_WRITE(ah, AR_NEXT_DTIM,
+ TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
+ REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
+
+ REG_WRITE(ah, AR_SLEEP1,
+ SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) |
+ AR_SLEEP1_ASSUME_DTIM);
+
+ if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)
+ beacontimeout = (BEACON_TIMEOUT_VAL << 3);
+ else
+ beacontimeout = MIN_BEACON_TIMEOUT_VAL;
+
+ REG_WRITE(ah, AR_SLEEP2,
+ SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
+
+ REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
+ REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
+
+ REG_SET_BIT(ah, AR_TIMER_MODE,
+ AR_TBTT_TIMER_EN |
+ AR_TIM_TIMER_EN |
+ AR_DTIM_TIMER_EN);
+
+}
+
+/* HW Capabilities */
+
+boolean_t
+ath9k_hw_fill_cap_info(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ uint16_t capField = 0, eeval;
+
+ eeval = ath9k_hw_get_eeprom(ah, EEP_REG_0);
+
+ ah->ah_currentRD = eeval;
+
+ eeval = ath9k_hw_get_eeprom(ah, EEP_REG_1);
+ ah->ah_currentRDExt = eeval;
+
+ capField = ath9k_hw_get_eeprom(ah, EEP_OP_CAP);
+
+ if (ah->ah_opmode != ATH9K_M_HOSTAP &&
+ ah->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+ if (ah->ah_currentRD == 0x64 ||
+ ah->ah_currentRD == 0x65)
+ ah->ah_currentRD += 5;
+ else if (ah->ah_currentRD == 0x41)
+ ah->ah_currentRD = 0x43;
+
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: regdomain mapped to 0x%x\n", __func__,
+ ah->ah_currentRD));
+ }
+
+ eeval = ath9k_hw_get_eeprom(ah, EEP_OP_MODE);
+
+ bzero(pCap->wireless_modes, sizeof (uint8_t)*4);
+
+ if (eeval & AR5416_OPFLAGS_11A) {
+ set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
+ if (ah->ah_config.ht_enable) {
+ if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
+ set_bit(ATH9K_MODE_11NA_HT20,
+ pCap->wireless_modes);
+ if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
+ set_bit(ATH9K_MODE_11NA_HT40PLUS,
+ pCap->wireless_modes);
+ set_bit(ATH9K_MODE_11NA_HT40MINUS,
+ pCap->wireless_modes);
+ }
+ }
+ }
+
+ if (eeval & AR5416_OPFLAGS_11G) {
+ set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
+ set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
+ if (ah->ah_config.ht_enable) {
+ if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
+ set_bit(ATH9K_MODE_11NG_HT20,
+ pCap->wireless_modes);
+ if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
+ set_bit(ATH9K_MODE_11NG_HT40PLUS,
+ pCap->wireless_modes);
+ set_bit(ATH9K_MODE_11NG_HT40MINUS,
+ pCap->wireless_modes);
+ }
+ }
+ }
+
+ pCap->tx_chainmask = ath9k_hw_get_eeprom(ah, EEP_TX_MASK);
+ if ((ah->ah_isPciExpress) ||
+ (eeval & AR5416_OPFLAGS_11A)) {
+ pCap->rx_chainmask =
+ ath9k_hw_get_eeprom(ah, EEP_RX_MASK);
+ } else {
+ pCap->rx_chainmask =
+ (ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7;
+ }
+
+ if (!(AR_SREV_9280(ah) && (ah->ah_macRev == 0)))
+ ahp->ah_miscMode |= AR_PCU_MIC_NEW_LOC_ENA;
+
+ pCap->low_2ghz_chan = 2312;
+ pCap->high_2ghz_chan = 2732;
+
+ pCap->low_5ghz_chan = 4920;
+ pCap->high_5ghz_chan = 6100;
+
+ pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
+ pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
+ pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
+
+ pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
+ pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
+ pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
+
+ pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
+#ifdef ARN_11N_SUPPORT
+ if (ah->ah_config.ht_enable)
+ pCap->hw_caps |= ATH9K_HW_CAP_HT;
+ else
+ pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+#else
+ pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+#endif
+
+ pCap->hw_caps |= ATH9K_HW_CAP_GTT;
+ pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
+ pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
+ pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
+
+ if (capField & AR_EEPROM_EEPCAP_MAXQCU)
+ pCap->total_queues =
+ MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
+ else
+ pCap->total_queues = ATH9K_NUM_TX_QUEUES;
+
+ if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
+ pCap->keycache_size =
+ 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
+ else
+ pCap->keycache_size = AR_KEYTABLE_SIZE;
+
+ pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
+ pCap->num_mr_retries = 4;
+ pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ pCap->num_gpio_pins = AR928X_NUM_GPIO;
+ else
+ pCap->num_gpio_pins = AR_NUM_GPIO;
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ pCap->hw_caps |= ATH9K_HW_CAP_WOW;
+ pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
+ } else {
+ pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
+ pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
+ }
+
+ if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
+ pCap->hw_caps |= ATH9K_HW_CAP_CST;
+ pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
+ } else {
+ pCap->rts_aggr_limit = (8 * 1024);
+ }
+
+ pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+ ah->ah_rfsilent = ath9k_hw_get_eeprom(ah, EEP_RF_SILENT);
+ if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
+ ah->ah_rfkill_gpio =
+ MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
+ ah->ah_rfkill_polarity =
+ MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
+
+ pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
+ }
+#endif
+
+ if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
+ (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
+ (ah->ah_macVersion == AR_SREV_VERSION_9160) ||
+ (ah->ah_macVersion == AR_SREV_VERSION_9100) ||
+ (ah->ah_macVersion == AR_SREV_VERSION_9280))
+ pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
+ else
+ pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
+
+ if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
+ pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
+ else
+ pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
+
+ if (ah->ah_currentRDExt & (1 << REG_EXT_JAPAN_MIDBAND)) {
+ pCap->reg_cap =
+ AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+ AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
+ AR_EEPROM_EEREGCAP_EN_KK_U2 |
+ AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
+ } else {
+ pCap->reg_cap =
+ AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+ AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
+ }
+
+ pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
+
+ /* ATH9K_HAL_FREQ_BAND_5GHZ == 0 */
+ pCap->num_antcfg_5ghz =
+ ath9k_hw_get_num_ant_config(ah, 0);
+ /* ATH9K_HAL_FREQ_BAND_2GHZ == 1 */
+ pCap->num_antcfg_2ghz =
+ ath9k_hw_get_num_ant_config(ah, 1);
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_getcapability(struct ath_hal *ah,
+ enum ath9k_capability_type type,
+ uint32_t capability, uint32_t *result)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+ switch (type) {
+ case ATH9K_CAP_CIPHER:
+ switch (capability) {
+ case ATH9K_CIPHER_AES_CCM:
+ case ATH9K_CIPHER_AES_OCB:
+ case ATH9K_CIPHER_TKIP:
+ case ATH9K_CIPHER_WEP:
+ case ATH9K_CIPHER_MIC:
+ case ATH9K_CIPHER_CLR:
+ return (B_TRUE);
+ default:
+ return (B_FALSE);
+ }
+ case ATH9K_CAP_TKIP_MIC:
+ switch (capability) {
+ case 0:
+ return (B_TRUE);
+ case 1:
+ return ((ahp->ah_staId1Defaults &
+ AR_STA_ID1_CRPT_MIC_ENABLE) ? B_TRUE :
+ B_FALSE);
+ }
+ /*FALLTHRU*/
+ case ATH9K_CAP_TKIP_SPLIT:
+ return ((ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) ?
+ B_FALSE : B_TRUE);
+ case ATH9K_CAP_WME_TKIPMIC:
+ return (0);
+ case ATH9K_CAP_PHYCOUNTERS:
+ return (ahp->ah_hasHwPhyCounters ? 0 : -ENXIO);
+ case ATH9K_CAP_DIVERSITY:
+ return ((REG_READ(ah, AR_PHY_CCK_DETECT) &
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
+ B_TRUE : B_FALSE);
+ case ATH9K_CAP_PHYDIAG:
+ return (B_TRUE);
+ case ATH9K_CAP_MCAST_KEYSRCH:
+ switch (capability) {
+ case 0:
+ return (B_TRUE);
+ case 1:
+ if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
+ return (B_FALSE);
+ } else {
+ return ((ahp->ah_staId1Defaults &
+ AR_STA_ID1_MCAST_KSRCH) ? B_TRUE :
+ B_FALSE);
+ }
+ }
+ return (B_FALSE);
+ case ATH9K_CAP_TSF_ADJUST:
+ return ((ahp->ah_miscMode & AR_PCU_TX_ADD_TSF) ?
+ B_TRUE : B_FALSE);
+ case ATH9K_CAP_RFSILENT:
+ if (capability == 3)
+ return (B_FALSE);
+ /*FALLTHRU*/
+ case ATH9K_CAP_ANT_CFG_2GHZ:
+ *result = pCap->num_antcfg_2ghz;
+ return (B_TRUE);
+ case ATH9K_CAP_ANT_CFG_5GHZ:
+ *result = pCap->num_antcfg_5ghz;
+ return (B_TRUE);
+ case ATH9K_CAP_TXPOW:
+ switch (capability) {
+ case 0:
+ return (0);
+ case 1:
+ *result = ah->ah_powerLimit;
+ return (0);
+ case 2:
+ *result = ah->ah_maxPowerLevel;
+ return (0);
+ case 3:
+ *result = ah->ah_tpScale;
+ return (0);
+ }
+ return (B_FALSE);
+ default:
+ return (B_FALSE);
+ }
+}
+
+/* ARGSUSED */
+boolean_t
+ath9k_hw_setcapability(struct ath_hal *ah,
+ enum ath9k_capability_type type,
+ uint32_t capability, uint32_t setting,
+ int *status)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t v;
+
+ switch (type) {
+ case ATH9K_CAP_TKIP_MIC:
+ if (setting)
+ ahp->ah_staId1Defaults |=
+ AR_STA_ID1_CRPT_MIC_ENABLE;
+ else
+ ahp->ah_staId1Defaults &=
+ ~AR_STA_ID1_CRPT_MIC_ENABLE;
+ return (B_TRUE);
+ case ATH9K_CAP_DIVERSITY:
+ v = REG_READ(ah, AR_PHY_CCK_DETECT);
+ if (setting)
+ v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ else
+ v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+ return (B_TRUE);
+ case ATH9K_CAP_MCAST_KEYSRCH:
+ if (setting)
+ ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
+ else
+ ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
+ return (B_TRUE);
+ case ATH9K_CAP_TSF_ADJUST:
+ if (setting)
+ ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
+ else
+ ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
+ return (B_TRUE);
+ default:
+ return (B_FALSE);
+ }
+}
+
+/* GPIO / RFKILL / Antennae */
+
+static void
+ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
+ uint32_t gpio, uint32_t type)
+{
+ int addr;
+ uint32_t gpio_shift, tmp;
+
+ if (gpio > 11)
+ addr = AR_GPIO_OUTPUT_MUX3;
+ else if (gpio > 5)
+ addr = AR_GPIO_OUTPUT_MUX2;
+ else
+ addr = AR_GPIO_OUTPUT_MUX1;
+
+ gpio_shift = (gpio % 6) * 5;
+
+ if (AR_SREV_9280_20_OR_LATER(ah) ||
+ (addr != AR_GPIO_OUTPUT_MUX1)) {
+ REG_RMW(ah, addr, (type << gpio_shift),
+ (0x1f << gpio_shift));
+ } else {
+ tmp = REG_READ(ah, addr);
+ tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
+ tmp &= ~(0x1f << gpio_shift);
+ tmp |= (type << gpio_shift);
+ REG_WRITE(ah, addr, tmp);
+ }
+}
+
+void
+ath9k_hw_cfg_gpio_input(struct ath_hal *ah, uint32_t gpio)
+{
+ uint32_t gpio_shift;
+
+ ASSERT(gpio < ah->ah_caps.num_gpio_pins);
+
+ gpio_shift = gpio << 1;
+
+ REG_RMW(ah,
+ AR_GPIO_OE_OUT,
+ (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+uint32_t
+ath9k_hw_gpio_get(struct ath_hal *ah, uint32_t gpio)
+{
+ if (gpio >= ah->ah_caps.num_gpio_pins)
+ return (0xffffffff);
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ return ((MS(REG_READ(ah, AR_GPIO_IN_OUT),
+ AR928X_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0);
+ } else {
+ return ((MS(REG_READ(ah,
+ AR_GPIO_IN_OUT), AR_GPIO_IN_VAL) &
+ AR_GPIO_BIT(gpio)) != 0);
+ }
+}
+
+void
+ath9k_hw_cfg_output(struct ath_hal *ah, uint32_t gpio,
+ uint32_t ah_signal_type)
+{
+ uint32_t gpio_shift;
+
+ ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+
+ gpio_shift = 2 * gpio;
+
+ REG_RMW(ah,
+ AR_GPIO_OE_OUT,
+ (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+void
+ath9k_hw_set_gpio(struct ath_hal *ah, uint32_t gpio, uint32_t val)
+{
+ REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
+ AR_GPIO_BIT(gpio));
+}
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+void
+ath9k_enable_rfkill(struct ath_hal *ah)
+{
+ REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+ AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
+
+ REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
+ AR_GPIO_INPUT_MUX2_RFSILENT);
+
+ ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio);
+ REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
+}
+#endif
+
+int
+ath9k_hw_select_antconfig(struct ath_hal *ah, uint32_t cfg)
+{
+ struct ath9k_channel *chan = ah->ah_curchan;
+ const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ uint16_t ant_config;
+ uint32_t halNumAntConfig;
+
+ halNumAntConfig = IS_CHAN_2GHZ(chan) ?
+ pCap->num_antcfg_2ghz : pCap->num_antcfg_5ghz;
+
+ if (cfg < halNumAntConfig) {
+ if (!ath9k_hw_get_eeprom_antenna_cfg(ah, chan,
+ cfg, &ant_config)) {
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+ return (0);
+ }
+ }
+
+ return (-EINVAL);
+}
+
+uint32_t
+ath9k_hw_getdefantenna(struct ath_hal *ah)
+{
+ return (REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
+}
+
+void
+ath9k_hw_setantenna(struct ath_hal *ah, uint32_t antenna)
+{
+ REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
+}
+
+/* ARGSUSED */
+boolean_t
+ath9k_hw_setantennaswitch(struct ath_hal *ah,
+ enum ath9k_ant_setting settings,
+ struct ath9k_channel *chan,
+ uint8_t *tx_chainmask,
+ uint8_t *rx_chainmask,
+ uint8_t *antenna_cfgd)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ static uint8_t tx_chainmask_cfg, rx_chainmask_cfg;
+
+ if (AR_SREV_9280(ah)) {
+ if (!tx_chainmask_cfg) {
+
+ tx_chainmask_cfg = *tx_chainmask;
+ rx_chainmask_cfg = *rx_chainmask;
+ }
+
+ switch (settings) {
+ case ATH9K_ANT_FIXED_A:
+ *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
+ *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
+ *antenna_cfgd = B_TRUE;
+ break;
+ case ATH9K_ANT_FIXED_B:
+ if (ah->ah_caps.tx_chainmask >
+ ATH9K_ANTENNA1_CHAINMASK) {
+ *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
+ }
+ *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
+ *antenna_cfgd = B_TRUE;
+ break;
+ case ATH9K_ANT_VARIABLE:
+ *tx_chainmask = tx_chainmask_cfg;
+ *rx_chainmask = rx_chainmask_cfg;
+ *antenna_cfgd = B_TRUE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ ahp->ah_diversityControl = settings;
+ }
+
+ return (B_TRUE);
+}
+
+/* General Operation */
+
+uint32_t
+ath9k_hw_getrxfilter(struct ath_hal *ah)
+{
+ uint32_t bits = REG_READ(ah, AR_RX_FILTER);
+ uint32_t phybits = REG_READ(ah, AR_PHY_ERR);
+
+ if (phybits & AR_PHY_ERR_RADAR)
+ bits |= ATH9K_RX_FILTER_PHYRADAR;
+ if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
+ bits |= ATH9K_RX_FILTER_PHYERR;
+
+ return (bits);
+}
+
+void
+ath9k_hw_setrxfilter(struct ath_hal *ah, uint32_t bits)
+{
+ uint32_t phybits;
+
+ REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
+ phybits = 0;
+ if (bits & ATH9K_RX_FILTER_PHYRADAR)
+ phybits |= AR_PHY_ERR_RADAR;
+ if (bits & ATH9K_RX_FILTER_PHYERR)
+ phybits |= AR_PHY_ERR_OFDM_TIMING |
+ AR_PHY_ERR_CCK_TIMING;
+ REG_WRITE(ah, AR_PHY_ERR, phybits);
+
+ if (phybits)
+ REG_WRITE(ah, AR_RXCFG,
+ REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
+ else
+ REG_WRITE(ah, AR_RXCFG,
+ REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
+}
+
+boolean_t
+ath9k_hw_phy_disable(struct ath_hal *ah)
+{
+ return (ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM));
+}
+
+boolean_t
+ath9k_hw_disable(struct ath_hal *ah)
+{
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+ return (B_FALSE);
+
+ return (ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD));
+}
+
+boolean_t
+ath9k_hw_set_txpowerlimit(struct ath_hal *ah, uint32_t limit)
+{
+ struct ath9k_channel *chan = ah->ah_curchan;
+
+ /* LINT */
+ ah->ah_powerLimit = (uint16_t)min(limit, (uint32_t)MAX_RATE_POWER);
+
+ if (ath9k_hw_set_txpower(ah, chan,
+ ath9k_regd_get_ctl(ah, chan),
+ ath9k_regd_get_antenna_allowed(ah, chan),
+ chan->maxRegTxPower * 2,
+ ARN_MIN((uint32_t)MAX_RATE_POWER,
+ (uint32_t)ah->ah_powerLimit)) != 0)
+ return (B_FALSE);
+
+ return (B_TRUE);
+}
+
+void
+ath9k_hw_getmac(struct ath_hal *ah, uint8_t *mac)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ (void) memcpy(mac, ahp->ah_macaddr, 6);
+}
+
+boolean_t
+ath9k_hw_setmac(struct ath_hal *ah, const uint8_t *mac)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ (void) memcpy(ahp->ah_macaddr, mac, 6);
+
+ return (B_TRUE);
+}
+
+void
+ath9k_hw_setopmode(struct ath_hal *ah)
+{
+ ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
+}
+
+void
+ath9k_hw_setmcastfilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1)
+{
+ REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+ REG_WRITE(ah, AR_MCAST_FIL1, filter1);
+}
+
+void
+ath9k_hw_getbssidmask(struct ath_hal *ah, uint8_t *mask)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ (void) memcpy(mask, ahp->ah_bssidmask, 6);
+}
+
+boolean_t
+ath9k_hw_setbssidmask(struct ath_hal *ah, const uint8_t *mask)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ (void) memcpy(ahp->ah_bssidmask, mask, 6);
+
+ REG_WRITE(ah, AR_BSSMSKL, ARN_LE_READ_32(ahp->ah_bssidmask));
+ REG_WRITE(ah, AR_BSSMSKU, ARN_LE_READ_16(ahp->ah_bssidmask + 4));
+
+ return (B_TRUE);
+}
+
+void
+ath9k_hw_write_associd(struct ath_hal *ah,
+ const uint8_t *bssid, uint16_t assocId)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ (void) memcpy(ahp->ah_bssid, bssid, 6);
+ ahp->ah_assocId = assocId;
+
+ REG_WRITE(ah, AR_BSS_ID0, ARN_LE_READ_32(ahp->ah_bssid));
+ REG_WRITE(ah, AR_BSS_ID1, ARN_LE_READ_16(ahp->ah_bssid + 4) |
+ ((assocId & 0x3fff) << AR_BSS_ID1_AID_S));
+}
+
+uint64_t
+ath9k_hw_gettsf64(struct ath_hal *ah)
+{
+ uint64_t tsf;
+
+ tsf = REG_READ(ah, AR_TSF_U32);
+ tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
+
+ return (tsf);
+}
+
+void
+ath9k_hw_reset_tsf(struct ath_hal *ah)
+{
+ int count;
+
+ count = 0;
+ while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
+ count++;
+ if (count > 10) {
+ ARN_DBG((ARN_DBG_HW, "arn: "
+ "%s: AR_SLP32_TSF_WRITE_STATUS limit exceeded\n",
+ __func__));
+
+ break;
+ }
+ drv_usecwait(10);
+ }
+ REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
+}
+
+boolean_t
+ath9k_hw_set_tsfadjust(struct ath_hal *ah, uint32_t setting)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (setting)
+ ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
+ else
+ ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_setslottime(struct ath_hal *ah, uint32_t us)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
+ ARN_DBG((ARN_DBG_HW, "arn: "
+ "%s: bad slot time %u\n", __func__, us));
+
+ ahp->ah_slottime = (uint32_t)-1;
+ return (B_FALSE);
+ } else {
+ REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
+ ahp->ah_slottime = us;
+ return (B_TRUE);
+ }
+}
+
+void
+ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode)
+{
+ uint32_t macmode;
+
+ if (mode == ATH9K_HT_MACMODE_2040 &&
+ !ah->ah_config.cwm_ignore_extcca)
+ macmode = AR_2040_JOINED_RX_CLEAR;
+ else
+ macmode = 0;
+
+ REG_WRITE(ah, AR_2040_MODE, macmode);
+}
diff --git a/usr/src/uts/common/io/arn/arn_hw.h b/usr/src/uts/common/io/arn/arn_hw.h
new file mode 100644
index 0000000000..5919816ba5
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_hw.h
@@ -0,0 +1,1089 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARN_HW_H
+#define _ARN_HW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(1)
+struct ar5416_desc {
+ uint32_t ds_link;
+ uint32_t ds_data;
+ uint32_t ds_ctl0;
+ uint32_t ds_ctl1;
+ union {
+ struct {
+ 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 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;
+ uint32_t status9;
+ } tx;
+ struct {
+ 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;
+ } rx;
+ } u;
+};
+#pragma pack()
+
+#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds))
+#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds))
+
+#define ds_ctl2 u.tx.ctl2
+#define ds_ctl3 u.tx.ctl3
+#define ds_ctl4 u.tx.ctl4
+#define ds_ctl5 u.tx.ctl5
+#define ds_ctl6 u.tx.ctl6
+#define ds_ctl7 u.tx.ctl7
+#define ds_ctl8 u.tx.ctl8
+#define ds_ctl9 u.tx.ctl9
+#define ds_ctl10 u.tx.ctl10
+#define ds_ctl11 u.tx.ctl11
+
+#define ds_txstatus0 u.tx.status0
+#define ds_txstatus1 u.tx.status1
+#define ds_txstatus2 u.tx.status2
+#define ds_txstatus3 u.tx.status3
+#define ds_txstatus4 u.tx.status4
+#define ds_txstatus5 u.tx.status5
+#define ds_txstatus6 u.tx.status6
+#define ds_txstatus7 u.tx.status7
+#define ds_txstatus8 u.tx.status8
+#define ds_txstatus9 u.tx.status9
+
+#define ds_rxstatus0 u.rx.status0
+#define ds_rxstatus1 u.rx.status1
+#define ds_rxstatus2 u.rx.status2
+#define ds_rxstatus3 u.rx.status3
+#define ds_rxstatus4 u.rx.status4
+#define ds_rxstatus5 u.rx.status5
+#define ds_rxstatus6 u.rx.status6
+#define ds_rxstatus7 u.rx.status7
+#define ds_rxstatus8 u.rx.status8
+
+#define AR_FrameLen 0x00000fff
+#define AR_VirtMoreFrag 0x00001000
+#define AR_TxCtlRsvd00 0x0000e000
+#define AR_XmitPower 0x003f0000
+#define AR_XmitPower_S 16
+#define AR_RTSEnable 0x00400000
+#define AR_VEOL 0x00800000
+#define AR_ClrDestMask 0x01000000
+#define AR_TxCtlRsvd01 0x1e000000
+#define AR_TxIntrReq 0x20000000
+#define AR_DestIdxValid 0x40000000
+#define AR_CTSEnable 0x80000000
+
+#define AR_BufLen 0x00000fff
+#define AR_TxMore 0x00001000
+#define AR_DestIdx 0x000fe000
+#define AR_DestIdx_S 13
+#define AR_FrameType 0x00f00000
+#define AR_FrameType_S 20
+#define AR_NoAck 0x01000000
+#define AR_InsertTS 0x02000000
+#define AR_CorruptFCS 0x04000000
+#define AR_ExtOnly 0x08000000
+#define AR_ExtAndCtl 0x10000000
+#define AR_MoreAggr 0x20000000
+#define AR_IsAggr 0x40000000
+
+#define AR_BurstDur 0x00007fff
+#define AR_BurstDur_S 0
+#define AR_DurUpdateEna 0x00008000
+#define AR_XmitDataTries0 0x000f0000
+#define AR_XmitDataTries0_S 16
+#define AR_XmitDataTries1 0x00f00000
+#define AR_XmitDataTries1_S 20
+#define AR_XmitDataTries2 0x0f000000
+#define AR_XmitDataTries2_S 24
+#define AR_XmitDataTries3 0xf0000000
+#define AR_XmitDataTries3_S 28
+
+#define AR_XmitRate0 0x000000ff
+#define AR_XmitRate0_S 0
+#define AR_XmitRate1 0x0000ff00
+#define AR_XmitRate1_S 8
+#define AR_XmitRate2 0x00ff0000
+#define AR_XmitRate2_S 16
+#define AR_XmitRate3 0xff000000
+#define AR_XmitRate3_S 24
+
+#define AR_PacketDur0 0x00007fff
+#define AR_PacketDur0_S 0
+#define AR_RTSCTSQual0 0x00008000
+#define AR_PacketDur1 0x7fff0000
+#define AR_PacketDur1_S 16
+#define AR_RTSCTSQual1 0x80000000
+
+#define AR_PacketDur2 0x00007fff
+#define AR_PacketDur2_S 0
+#define AR_RTSCTSQual2 0x00008000
+#define AR_PacketDur3 0x7fff0000
+#define AR_PacketDur3_S 16
+#define AR_RTSCTSQual3 0x80000000
+
+#define AR_AggrLen 0x0000ffff
+#define AR_AggrLen_S 0
+#define AR_TxCtlRsvd60 0x00030000
+#define AR_PadDelim 0x03fc0000
+#define AR_PadDelim_S 18
+#define AR_EncrType 0x0c000000
+#define AR_EncrType_S 26
+#define AR_TxCtlRsvd61 0xf0000000
+
+#define AR_2040_0 0x00000001
+#define AR_GI0 0x00000002
+#define AR_ChainSel0 0x0000001c
+#define AR_ChainSel0_S 2
+#define AR_2040_1 0x00000020
+#define AR_GI1 0x00000040
+#define AR_ChainSel1 0x00000380
+#define AR_ChainSel1_S 7
+#define AR_2040_2 0x00000400
+#define AR_GI2 0x00000800
+#define AR_ChainSel2 0x00007000
+#define AR_ChainSel2_S 12
+#define AR_2040_3 0x00008000
+#define AR_GI3 0x00010000
+#define AR_ChainSel3 0x000e0000
+#define AR_ChainSel3_S 17
+#define AR_RTSCTSRate 0x0ff00000
+#define AR_RTSCTSRate_S 20
+#define AR_TxCtlRsvd70 0xf0000000
+
+#define AR_TxRSSIAnt00 0x000000ff
+#define AR_TxRSSIAnt00_S 0
+#define AR_TxRSSIAnt01 0x0000ff00
+#define AR_TxRSSIAnt01_S 8
+#define AR_TxRSSIAnt02 0x00ff0000
+#define AR_TxRSSIAnt02_S 16
+#define AR_TxStatusRsvd00 0x3f000000
+#define AR_TxBaStatus 0x40000000
+#define AR_TxStatusRsvd01 0x80000000
+
+#define AR_FrmXmitOK 0x00000001
+#define AR_ExcessiveRetries 0x00000002
+#define AR_FIFOUnderrun 0x00000004
+#define AR_Filtered 0x00000008
+#define AR_RTSFailCnt 0x000000f0
+#define AR_RTSFailCnt_S 4
+#define AR_DataFailCnt 0x00000f00
+#define AR_DataFailCnt_S 8
+#define AR_VirtRetryCnt 0x0000f000
+#define AR_VirtRetryCnt_S 12
+#define AR_TxDelimUnderrun 0x00010000
+#define AR_TxDataUnderrun 0x00020000
+#define AR_DescCfgErr 0x00040000
+#define AR_TxTimerExpired 0x00080000
+#define AR_TxStatusRsvd10 0xfff00000
+
+#define AR_SendTimestamp ds_txstatus2
+#define AR_BaBitmapLow ds_txstatus3
+#define AR_BaBitmapHigh ds_txstatus4
+
+#define AR_TxRSSIAnt10 0x000000ff
+#define AR_TxRSSIAnt10_S 0
+#define AR_TxRSSIAnt11 0x0000ff00
+#define AR_TxRSSIAnt11_S 8
+#define AR_TxRSSIAnt12 0x00ff0000
+#define AR_TxRSSIAnt12_S 16
+#define AR_TxRSSICombined 0xff000000
+#define AR_TxRSSICombined_S 24
+
+#define AR_TxEVM0 ds_txstatus5
+#define AR_TxEVM1 ds_txstatus6
+#define AR_TxEVM2 ds_txstatus7
+
+#define AR_TxDone 0x00000001
+#define AR_SeqNum 0x00001ffe
+#define AR_SeqNum_S 1
+#define AR_TxStatusRsvd80 0x0001e000
+#define AR_TxOpExceeded 0x00020000
+#define AR_TxStatusRsvd81 0x001c0000
+#define AR_FinalTxIdx 0x00600000
+#define AR_FinalTxIdx_S 21
+#define AR_TxStatusRsvd82 0x01800000
+#define AR_PowerMgmt 0x02000000
+#define AR_TxStatusRsvd83 0xfc000000
+
+#define AR_RxCTLRsvd00 0xffffffff
+
+#define AR_BufLen 0x00000fff
+#define AR_RxCtlRsvd00 0x00001000
+#define AR_RxIntrReq 0x00002000
+#define AR_RxCtlRsvd01 0xffffc000
+
+#define AR_RxRSSIAnt00 0x000000ff
+#define AR_RxRSSIAnt00_S 0
+#define AR_RxRSSIAnt01 0x0000ff00
+#define AR_RxRSSIAnt01_S 8
+#define AR_RxRSSIAnt02 0x00ff0000
+#define AR_RxRSSIAnt02_S 16
+#define AR_RxRate 0xff000000
+#define AR_RxRate_S 24
+#define AR_RxStatusRsvd00 0xff000000
+
+#define AR_DataLen 0x00000fff
+#define AR_RxMore 0x00001000
+#define AR_NumDelim 0x003fc000
+#define AR_NumDelim_S 14
+#define AR_RxStatusRsvd10 0xff800000
+
+#define AR_RcvTimestamp ds_rxstatus2
+
+#define AR_GI 0x00000001
+#define AR_2040 0x00000002
+#define AR_Parallel40 0x00000004
+#define AR_Parallel40_S 2
+#define AR_RxStatusRsvd30 0x000000f8
+#define AR_RxAntenna 0xffffff00
+#define AR_RxAntenna_S 8
+
+#define AR_RxRSSIAnt10 0x000000ff
+#define AR_RxRSSIAnt10_S 0
+#define AR_RxRSSIAnt11 0x0000ff00
+#define AR_RxRSSIAnt11_S 8
+#define AR_RxRSSIAnt12 0x00ff0000
+#define AR_RxRSSIAnt12_S 16
+#define AR_RxRSSICombined 0xff000000
+#define AR_RxRSSICombined_S 24
+
+#define AR_RxEVM0 ds_rxstatus4
+#define AR_RxEVM1 ds_rxstatus5
+#define AR_RxEVM2 ds_rxstatus6
+
+#define AR_RxDone 0x00000001
+#define AR_RxFrameOK 0x00000002
+#define AR_CRCErr 0x00000004
+#define AR_DecryptCRCErr 0x00000008
+#define AR_PHYErr 0x00000010
+#define AR_MichaelErr 0x00000020
+#define AR_PreDelimCRCErr 0x00000040
+#define AR_RxStatusRsvd70 0x00000080
+#define AR_RxKeyIdxValid 0x00000100
+#define AR_KeyIdx 0x0000fe00
+#define AR_KeyIdx_S 9
+#define AR_PHYErrCode 0x0000ff00
+#define AR_PHYErrCode_S 8
+#define AR_RxMoreAggr 0x00010000
+#define AR_RxAggr 0x00020000
+#define AR_PostDelimCRCErr 0x00040000
+#define AR_RxStatusRsvd71 0x3ff80000
+#define AR_DecryptBusyErr 0x40000000
+#define AR_KeyMiss 0x80000000
+
+#define AR5416_MAGIC 0x19641014
+
+#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \
+ MS(ads->ds_rxstatus0, AR_RxRate) : \
+ (ads->ds_rxstatus3 >> 2) & 0xFF)
+
+#define set11nTries(_series, _index) \
+ (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
+
+#define set11nRate(_series, _index) \
+ (SM((_series)[_index].Rate, AR_XmitRate##_index))
+
+#define set11nPktDurRTSCTS(_series, _index) \
+ (SM((_series)[_index].PktDuration, AR_PacketDur##_index) | \
+ ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS ? \
+ AR_RTSCTSQual##_index : 0))
+
+#define set11nRateFlags(_series, _index) \
+ (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \
+ AR_2040_##_index : 0) \
+ |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \
+ AR_GI##_index : 0) \
+ |SM((_series)[_index].ChSel, AR_ChainSel##_index))
+
+#define AR_SREV_9100(ah) ((ah->ah_macVersion) == AR_SREV_VERSION_9100)
+
+#define INIT_CONFIG_STATUS 0x00000000
+#define INIT_RSSI_THR 0x00000700
+#define INIT_BCON_CNTRL_REG 0x00000000
+
+#define MIN_TX_FIFO_THRESHOLD 0x1
+#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1)
+#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD
+
+struct ar5416AniState {
+ struct ath9k_channel c;
+ uint8_t noiseImmunityLevel;
+ uint8_t spurImmunityLevel;
+ uint8_t firstepLevel;
+ uint8_t ofdmWeakSigDetectOff;
+ uint8_t cckWeakSigThreshold;
+ uint32_t listenTime;
+ uint32_t ofdmTrigHigh;
+ uint32_t ofdmTrigLow;
+ int32_t cckTrigHigh;
+ int32_t cckTrigLow;
+ int32_t rssiThrLow;
+ int32_t rssiThrHigh;
+ uint32_t noiseFloor;
+ uint32_t txFrameCount;
+ uint32_t rxFrameCount;
+ uint32_t cycleCount;
+ uint32_t ofdmPhyErrCount;
+ uint32_t cckPhyErrCount;
+ uint32_t ofdmPhyErrBase;
+ uint32_t cckPhyErrBase;
+ int16_t pktRssi[2];
+ int16_t ofdmErrRssi[2];
+ int16_t cckErrRssi[2];
+};
+
+#define HAL_PROCESS_ANI 0x00000001
+#define DO_ANI(ah) \
+ ((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI))
+
+struct ar5416Stats {
+ uint32_t ast_ani_niup;
+ uint32_t ast_ani_nidown;
+ uint32_t ast_ani_spurup;
+ uint32_t ast_ani_spurdown;
+ uint32_t ast_ani_ofdmon;
+ uint32_t ast_ani_ofdmoff;
+ uint32_t ast_ani_cckhigh;
+ uint32_t ast_ani_ccklow;
+ uint32_t ast_ani_stepup;
+ uint32_t ast_ani_stepdown;
+ uint32_t ast_ani_ofdmerrs;
+ uint32_t ast_ani_cckerrs;
+ uint32_t ast_ani_reset;
+ uint32_t ast_ani_lzero;
+ uint32_t ast_ani_lneg;
+ struct ath9k_mib_stats ast_mibstats;
+ struct ath9k_node_stats ast_nodestats;
+};
+
+#define AR5416_OPFLAGS_11A 0x01
+#define AR5416_OPFLAGS_11G 0x02
+#define AR5416_OPFLAGS_N_5G_HT40 0x04
+#define AR5416_OPFLAGS_N_2G_HT40 0x08
+#define AR5416_OPFLAGS_N_5G_HT20 0x10
+#define AR5416_OPFLAGS_N_2G_HT20 0x20
+
+#define EEP_RFSILENT_ENABLED 0x0001
+#define EEP_RFSILENT_ENABLED_S 0
+#define EEP_RFSILENT_POLARITY 0x0002
+#define EEP_RFSILENT_POLARITY_S 1
+#define EEP_RFSILENT_GPIO_SEL 0x001c
+#define EEP_RFSILENT_GPIO_SEL_S 2
+
+#define AR5416_EEP_NO_BACK_VER 0x1
+#define AR5416_EEP_VER 0xE
+#define AR5416_EEP_VER_MINOR_MASK 0x0FFF
+#define AR5416_EEP_MINOR_VER_2 0x2
+#define AR5416_EEP_MINOR_VER_3 0x3
+#define AR5416_EEP_MINOR_VER_7 0x7
+#define AR5416_EEP_MINOR_VER_9 0x9
+#define AR5416_EEP_MINOR_VER_16 0x10
+#define AR5416_EEP_MINOR_VER_17 0x11
+#define AR5416_EEP_MINOR_VER_19 0x13
+
+#define AR5416_NUM_5G_CAL_PIERS 8
+#define AR5416_NUM_2G_CAL_PIERS 4
+#define AR5416_NUM_5G_20_TARGET_POWERS 8
+#define AR5416_NUM_5G_40_TARGET_POWERS 8
+#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_NUM_2G_20_TARGET_POWERS 4
+#define AR5416_NUM_2G_40_TARGET_POWERS 4
+#define AR5416_NUM_CTLS 24
+#define AR5416_NUM_BAND_EDGES 8
+#define AR5416_NUM_PD_GAINS 4
+#define AR5416_PD_GAINS_IN_MASK 4
+#define AR5416_PD_GAIN_ICEPTS 5
+#define AR5416_EEPROM_MODAL_SPURS 5
+#define AR5416_MAX_RATE_POWER 63
+#define AR5416_NUM_PDADC_VALUES 128
+#define AR5416_BCHAN_UNUSED 0xFF
+#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
+#define AR5416_MAX_CHAINS 3
+#define AR5416_PWR_TABLE_OFFSET -5
+
+/* Rx gain type values */
+#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
+#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1
+#define AR5416_EEP_RXGAIN_ORIG 2
+
+/* Tx gain type values */
+#define AR5416_EEP_TXGAIN_ORIGINAL 0
+#define AR5416_EEP_TXGAIN_HIGH_POWER 1
+
+#define AR5416_EEP4K_START_LOC 64
+#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3
+#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_CTLS 12
+#define AR5416_EEP4K_NUM_BAND_EDGES 4
+#define AR5416_EEP4K_NUM_PD_GAINS 2
+#define AR5416_EEP4K_PD_GAINS_IN_MASK 4
+#define AR5416_EEP4K_PD_GAIN_ICEPTS 5
+#define AR5416_EEP4K_MAX_CHAINS 1
+
+enum eeprom_param {
+ EEP_NFTHRESH_5,
+ EEP_NFTHRESH_2,
+ EEP_MAC_MSW,
+ EEP_MAC_MID,
+ EEP_MAC_LSW,
+ EEP_REG_0,
+ EEP_REG_1,
+ EEP_OP_CAP,
+ EEP_OP_MODE,
+ EEP_RF_SILENT,
+ EEP_OB_5,
+ EEP_DB_5,
+ EEP_OB_2,
+ EEP_DB_2,
+ EEP_MINOR_REV,
+ EEP_TX_MASK,
+ EEP_RX_MASK,
+ EEP_RXGAIN_TYPE,
+ EEP_TXGAIN_TYPE,
+};
+
+enum ar5416_rates {
+ rate6mb, rate9mb, rate12mb, rate18mb,
+ rate24mb, rate36mb, rate48mb, rate54mb,
+ rate1l, rate2l, rate2s, rate5_5l,
+ rate5_5s, rate11l, rate11s, rateXr,
+ rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
+ rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
+ rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
+ rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
+ rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
+ Ar5416RateSize
+};
+
+enum ath9k_hal_freq_band {
+ ATH9K_HAL_FREQ_BAND_5GHZ = 0,
+ ATH9K_HAL_FREQ_BAND_2GHZ = 1
+};
+
+#pragma pack(1)
+struct base_eep_header {
+ uint16_t length;
+ uint16_t checksum;
+ uint16_t version;
+ 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 futureBase_1[2];
+ uint8_t rxGainType;
+ uint8_t futureBase_2[3];
+ uint8_t txGainType;
+ uint8_t futureBase_3[25];
+};
+
+struct base_eep_header_4k {
+ uint16_t length;
+ uint16_t checksum;
+ uint16_t version;
+ 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 futureBase[1];
+};
+
+struct spur_chan {
+ uint16_t spurChan;
+ uint8_t spurRangeLow;
+ uint8_t spurRangeHigh;
+};
+
+struct modal_eep_header {
+ uint32_t antCtrlChain[AR5416_MAX_CHAINS];
+ uint32_t antCtrlCommon;
+ uint8_t antennaGainCh[AR5416_MAX_CHAINS];
+ uint8_t switchSettling;
+ uint8_t txRxAttenCh[AR5416_MAX_CHAINS];
+ uint8_t rxTxMarginCh[AR5416_MAX_CHAINS];
+ uint8_t adcDesiredSize;
+ uint8_t pgaDesiredSize;
+ uint8_t xlnaGainCh[AR5416_MAX_CHAINS];
+ uint8_t txEndToXpaOff;
+ uint8_t txEndToRxOn;
+ uint8_t txFrameToXpaOn;
+ uint8_t thresh62;
+ uint8_t noiseFloorThreshCh[AR5416_MAX_CHAINS];
+ uint8_t xpdGain;
+ uint8_t xpd;
+ uint8_t iqCalICh[AR5416_MAX_CHAINS];
+ uint8_t iqCalQCh[AR5416_MAX_CHAINS];
+ uint8_t pdGainOverlap;
+ uint8_t ob;
+ uint8_t db;
+ uint8_t xpaBiasLvl;
+ uint8_t pwrDecreaseFor2Chain;
+ uint8_t pwrDecreaseFor3Chain;
+ uint8_t txFrameToDataStart;
+ uint8_t txFrameToPaOn;
+ uint8_t ht40PowerIncForPdadc;
+ uint8_t bswAtten[AR5416_MAX_CHAINS];
+ uint8_t bswMargin[AR5416_MAX_CHAINS];
+ uint8_t swSettleHt40;
+ uint8_t xatten2Db[AR5416_MAX_CHAINS];
+ uint8_t xatten2Margin[AR5416_MAX_CHAINS];
+ uint8_t ob_ch1;
+ uint8_t db_ch1;
+ uint8_t useAnt1:1,
+ force_xpaon:1,
+ local_bias:1,
+ femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
+ uint8_t futureModalar9280;
+ uint16_t xpaBiasLvlFreq[3];
+ uint8_t futureModal[6];
+
+ struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
+};
+
+struct modal_eep_4k_header {
+ uint32_t antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
+ uint32_t antCtrlCommon;
+ uint8_t antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t switchSettling;
+ uint8_t txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t adcDesiredSize;
+ uint8_t pgaDesiredSize;
+ uint8_t xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t txEndToXpaOff;
+ uint8_t txEndToRxOn;
+ uint8_t txFrameToXpaOn;
+ uint8_t thresh62;
+ uint8_t noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t xpdGain;
+ uint8_t xpd;
+ uint8_t iqCalICh[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t pdGainOverlap;
+ uint8_t ob_01;
+ uint8_t db1_01;
+ uint8_t xpaBiasLvl;
+ uint8_t txFrameToDataStart;
+ uint8_t txFrameToPaOn;
+ uint8_t ht40PowerIncForPdadc;
+ uint8_t bswAtten[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t bswMargin[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t swSettleHt40;
+ uint8_t xatten2Db[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
+ uint8_t db2_01;
+ uint8_t version;
+ uint16_t ob_234;
+ uint16_t db1_234;
+ uint16_t db2_234;
+ uint8_t futureModal[4];
+
+ struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
+};
+
+struct cal_data_per_freq {
+ uint8_t pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+ uint8_t vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+};
+
+struct cal_data_per_freq_4k {
+ uint8_t pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
+ uint8_t vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
+};
+
+struct cal_target_power_leg {
+ uint8_t bChannel;
+ uint8_t tPow2x[4];
+};
+
+struct cal_target_power_ht {
+ uint8_t bChannel;
+ uint8_t tPow2x[8];
+};
+
+#ifdef __BIG_ENDIAN_BITFIELD
+struct cal_ctl_edges {
+ uint8_t bChannel;
+ uint8_t flag:2, tPower:6;
+};
+#else
+struct cal_ctl_edges {
+ uint8_t bChannel;
+ uint8_t tPower:6, flag:2;
+};
+#endif
+
+struct cal_ctl_data {
+ struct cal_ctl_edges
+ ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+};
+
+struct cal_ctl_data_4k {
+ struct cal_ctl_edges
+ ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
+};
+
+struct ar5416_eeprom_def {
+ struct base_eep_header baseEepHeader;
+ uint8_t custData[64];
+ struct modal_eep_header modalHeader[2];
+ uint8_t calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
+ uint8_t calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
+ struct cal_data_per_freq
+ calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
+ struct cal_data_per_freq
+ calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+ struct cal_target_power_leg
+ calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
+ uint8_t ctlIndex[AR5416_NUM_CTLS];
+ struct cal_ctl_data ctlData[AR5416_NUM_CTLS];
+ uint8_t padding;
+};
+
+struct ar5416_eeprom_4k {
+ struct base_eep_header_4k baseEepHeader;
+ uint8_t custData[20];
+ struct modal_eep_4k_header modalHeader;
+ uint8_t calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
+ struct cal_data_per_freq_4k
+ calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
+ struct cal_target_power_leg
+ calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
+ uint8_t ctlIndex[AR5416_EEP4K_NUM_CTLS];
+ struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
+ uint8_t padding;
+};
+#pragma pack()
+
+struct ar5416IniArray {
+ uint32_t *ia_array;
+ uint32_t ia_rows;
+ uint32_t ia_columns;
+};
+
+#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
+ (iniarray)->ia_array = (uint32_t *)(array); \
+ (iniarray)->ia_rows = (rows); \
+ (iniarray)->ia_columns = (columns); \
+ _NOTE(CONSTCOND) \
+ } while (0)
+
+#define INI_RA(iniarray, row, column) \
+ (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)])
+
+#define INIT_CAL(_perCal) do { \
+ (_perCal)->calState = CAL_WAITING; \
+ (_perCal)->calNext = NULL; \
+ } while (0)
+
+#define INSERT_CAL(_ahp, _perCal) \
+ do { \
+ if ((_ahp)->ah_cal_list_last == NULL) { \
+ (_ahp)->ah_cal_list = \
+ (_ahp)->ah_cal_list_last = (_perCal); \
+ ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \
+ } else { \
+ ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \
+ (_ahp)->ah_cal_list_last = (_perCal); \
+ (_perCal)->calNext = (_ahp)->ah_cal_list; \
+ } \
+ } while (0)
+
+enum hal_cal_types {
+ ADC_DC_INIT_CAL = 0x1,
+ ADC_GAIN_CAL = 0x2,
+ ADC_DC_CAL = 0x4,
+ IQ_MISMATCH_CAL = 0x8
+};
+
+enum hal_cal_state {
+ CAL_INACTIVE,
+ CAL_WAITING,
+ CAL_RUNNING,
+ CAL_DONE
+};
+
+#define MIN_CAL_SAMPLES 1
+#define MAX_CAL_SAMPLES 64
+#define INIT_LOG_COUNT 5
+#define PER_MIN_LOG_COUNT 2
+#define PER_MAX_LOG_COUNT 10
+
+struct hal_percal_data {
+ enum hal_cal_types calType;
+ uint32_t calNumSamples;
+ uint32_t calCountMax;
+ void (*calCollect) (struct ath_hal *);
+ void (*calPostProc) (struct ath_hal *, uint8_t);
+};
+
+struct hal_cal_list {
+ const struct hal_percal_data *calData;
+ enum hal_cal_state calState;
+ struct hal_cal_list *calNext;
+};
+
+/*
+ * Enum to indentify the eeprom mappings
+ */
+enum hal_eep_map {
+ EEP_MAP_DEFAULT = 0x0,
+ EEP_MAP_4KBITS,
+ EEP_MAP_MAX
+};
+
+struct ath_hal_5416 {
+ struct ath_hal ah;
+ union {
+ struct ar5416_eeprom_def def;
+ struct ar5416_eeprom_4k map4k;
+ } ah_eeprom;
+ struct ar5416Stats ah_stats;
+ struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES];
+
+ uint8_t ah_macaddr[IEEE80211_ADDR_LEN];
+ uint8_t ah_bssid[IEEE80211_ADDR_LEN];
+ uint8_t ah_bssidmask[IEEE80211_ADDR_LEN];
+ uint16_t ah_assocId;
+
+ int16_t ah_curchanRadIndex;
+ uint32_t ah_maskReg;
+ uint32_t ah_txOkInterruptMask;
+ uint32_t ah_txErrInterruptMask;
+ uint32_t ah_txDescInterruptMask;
+ uint32_t ah_txEolInterruptMask;
+ uint32_t ah_txUrnInterruptMask;
+ boolean_t ah_chipFullSleep;
+ uint32_t ah_atimWindow;
+ uint16_t ah_antennaSwitchSwap;
+ enum ath9k_power_mode ah_powerMode;
+ enum ath9k_ant_setting ah_diversityControl;
+
+ /* Calibration */
+ enum hal_cal_types ah_suppCals;
+ struct hal_cal_list ah_iqCalData;
+ struct hal_cal_list ah_adcGainCalData;
+ struct hal_cal_list ah_adcDcCalInitData;
+ struct hal_cal_list ah_adcDcCalData;
+ struct hal_cal_list *ah_cal_list;
+ struct hal_cal_list *ah_cal_list_last;
+ struct hal_cal_list *ah_cal_list_curr;
+#define ah_totalPowerMeasI ah_Meas0.unsign
+#define ah_totalPowerMeasQ ah_Meas1.unsign
+#define ah_totalIqCorrMeas ah_Meas2.sign
+#define ah_totalAdcIOddPhase ah_Meas0.unsign
+#define ah_totalAdcIEvenPhase ah_Meas1.unsign
+#define ah_totalAdcQOddPhase ah_Meas2.unsign
+#define ah_totalAdcQEvenPhase ah_Meas3.unsign
+#define ah_totalAdcDcOffsetIOddPhase ah_Meas0.sign
+#define ah_totalAdcDcOffsetIEvenPhase ah_Meas1.sign
+#define ah_totalAdcDcOffsetQOddPhase ah_Meas2.sign
+#define ah_totalAdcDcOffsetQEvenPhase ah_Meas3.sign
+ union {
+ uint32_t unsign[AR5416_MAX_CHAINS];
+ int32_t sign[AR5416_MAX_CHAINS];
+ } ah_Meas0;
+ union {
+ uint32_t unsign[AR5416_MAX_CHAINS];
+ int32_t sign[AR5416_MAX_CHAINS];
+ } ah_Meas1;
+ union {
+ uint32_t unsign[AR5416_MAX_CHAINS];
+ int32_t sign[AR5416_MAX_CHAINS];
+ } ah_Meas2;
+ union {
+ uint32_t unsign[AR5416_MAX_CHAINS];
+ int32_t sign[AR5416_MAX_CHAINS];
+ } ah_Meas3;
+ uint16_t ah_CalSamples;
+
+ uint32_t ah_staId1Defaults;
+ uint32_t ah_miscMode;
+ enum {
+ AUTO_32KHZ,
+ USE_32KHZ,
+ DONT_USE_32KHZ,
+ } ah_enable32kHzClock;
+
+ /* RF */
+ uint32_t *ah_analogBank0Data;
+ uint32_t *ah_analogBank1Data;
+ uint32_t *ah_analogBank2Data;
+ uint32_t *ah_analogBank3Data;
+ uint32_t *ah_analogBank6Data;
+ uint32_t *ah_analogBank6TPCData;
+ uint32_t *ah_analogBank7Data;
+ uint32_t *ah_addac5416_21;
+ uint32_t *ah_bank6Temp;
+
+ int16_t ah_txPowerIndexOffset;
+ uint32_t ah_beaconInterval;
+ uint32_t ah_slottime;
+ uint32_t ah_acktimeout;
+ uint32_t ah_ctstimeout;
+ uint32_t ah_globaltxtimeout;
+ uint8_t ah_gBeaconRate;
+ uint32_t ah_gpioSelect;
+ uint32_t ah_polarity;
+ uint32_t ah_gpioBit;
+
+ /* ANI */
+ uint32_t ah_procPhyErr;
+ boolean_t ah_hasHwPhyCounters;
+ uint32_t ah_aniPeriod;
+ struct ar5416AniState *ah_curani;
+ struct ar5416AniState ah_ani[255];
+ int ah_totalSizeDesired[5];
+ int ah_coarseHigh[5];
+ int ah_coarseLow[5];
+ int ah_firpwr[5];
+ enum ath9k_ani_cmd ah_ani_function;
+
+ uint32_t ah_intrTxqs;
+ boolean_t ah_intrMitigation;
+ enum ath9k_ht_extprotspacing ah_extprotspacing;
+ uint8_t ah_txchainmask;
+ uint8_t ah_rxchainmask;
+
+ struct ar5416IniArray ah_iniModes;
+ struct ar5416IniArray ah_iniCommon;
+ struct ar5416IniArray ah_iniBank0;
+ struct ar5416IniArray ah_iniBB_RfGain;
+ struct ar5416IniArray ah_iniBank1;
+ struct ar5416IniArray ah_iniBank2;
+ struct ar5416IniArray ah_iniBank3;
+ struct ar5416IniArray ah_iniBank6;
+ struct ar5416IniArray ah_iniBank6TPC;
+ struct ar5416IniArray ah_iniBank7;
+ struct ar5416IniArray ah_iniAddac;
+ struct ar5416IniArray ah_iniPcieSerdes;
+ struct ar5416IniArray ah_iniModesAdditional;
+ struct ar5416IniArray ah_iniModesRxGain;
+ struct ar5416IniArray ah_iniModesTxGain;
+ /* To indicate EEPROM mapping used */
+ enum hal_eep_map ah_eep_map;
+};
+#define AH5416(_ah) ((struct ath_hal_5416 *)(_ah))
+
+#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
+
+#define ar5416RfDetach(ah) do { \
+ if (AH5416(ah)->ah_rfHal.rfDetach != NULL) \
+ AH5416(ah)->ah_rfHal.rfDetach(ah); \
+ } while (0)
+
+#define ath9k_hw_use_flash(_ah) \
+ (!(_ah->ah_flags & AH_USE_EEPROM))
+
+
+#define DO_DELAY(x) do { \
+ if ((++(x) % 64) == 0) \
+ drv_usecwait(1); \
+ } while (0)
+
+#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \
+ int r; \
+ for (r = 0; r < ((iniarray)->ia_rows); r++) { \
+ REG_WRITE(ah, INI_RA((iniarray), (r), 0), \
+ INI_RA((iniarray), r, (column))); \
+ DO_DELAY(regWr); \
+ } \
+ } while (0)
+
+#define BASE_ACTIVATE_DELAY 100
+#define RTC_PLL_SETTLE_DELAY 1000
+#define COEF_SCALE_S 24
+#define HT40_CHANNEL_CENTER_SHIFT 10
+
+#define AR5416_EEPROM_MAGIC_OFFSET 0x0
+
+#define AR5416_EEPROM_S 2
+#define AR5416_EEPROM_OFFSET 0x2000
+#define AR5416_EEPROM_START_ADDR \
+ (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
+#define AR5416_EEPROM_MAX 0xae0
+#define ar5416_get_eep_ver(_ahp) \
+ (((_ahp)->ah_eeprom.def.baseEepHeader.version >> 12) & 0xF)
+#define ar5416_get_eep_rev(_ahp) \
+ (((_ahp)->ah_eeprom.def.baseEepHeader.version) & 0xFFF)
+#define ar5416_get_ntxchains(_txchainmask) \
+ (((_txchainmask >> 2) & 1) + \
+ ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
+
+/* EEPROM 4K bit map definations */
+#define ar5416_get_eep4k_ver(_ahp) \
+ (((_ahp)->ah_eeprom.map4k.baseEepHeader.version >> 12) & 0xF)
+#define ar5416_get_eep4k_rev(_ahp) \
+ (((_ahp)->ah_eeprom.map4k.baseEepHeader.version) & 0xFFF)
+
+#ifdef __BIG_ENDIAN
+#define AR5416_EEPROM_MAGIC 0x5aa5
+#else
+#define AR5416_EEPROM_MAGIC 0xa55a
+#endif
+
+#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
+
+#define ATH9K_ANTENNA0_CHAINMASK 0x1
+#define ATH9K_ANTENNA1_CHAINMASK 0x2
+
+#define ATH9K_NUM_DMA_DEBUG_REGS 8
+#define ATH9K_NUM_QUEUES 10
+
+#define HAL_NOISE_IMMUNE_MAX 4
+#define HAL_SPUR_IMMUNE_MAX 7
+#define HAL_FIRST_STEP_MAX 2
+
+#define ATH9K_ANI_OFDM_TRIG_HIGH 500
+#define ATH9K_ANI_OFDM_TRIG_LOW 200
+#define ATH9K_ANI_CCK_TRIG_HIGH 200
+#define ATH9K_ANI_CCK_TRIG_LOW 100
+#define ATH9K_ANI_NOISE_IMMUNE_LVL 4
+#define ATH9K_ANI_USE_OFDM_WEAK_SIG B_TRUE
+#define ATH9K_ANI_CCK_WEAK_SIG_THR B_FALSE
+#define ATH9K_ANI_SPUR_IMMUNE_LVL 7
+#define ATH9K_ANI_FIRSTEP_LVL 0
+#define ATH9K_ANI_RSSI_THR_HIGH 40
+#define ATH9K_ANI_RSSI_THR_LOW 7
+#define ATH9K_ANI_PERIOD 100
+
+#define AR_GPIOD_MASK 0x00001FFF
+#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
+
+#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, \
+ ATH9K_RSSI_EP_MULTIPLIER)
+
+#define ah_mibStats ah_stats.ast_mibstats
+
+#define AH_TIMEOUT 100000
+#define AH_TIME_QUANTUM 10
+
+#define AR_KEYTABLE_SIZE 128
+#define POWER_UP_TIME 200000
+
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2
+#define SUB_NUM_CTL_MODES_AT_2G_40 3
+#define SPUR_RSSI_THRESH 40
+
+#define TU_TO_USEC(_tu) ((_tu) << 10)
+
+#define CAB_TIMEOUT_VAL 10
+#define BEACON_TIMEOUT_VAL 10
+#define MIN_BEACON_TIMEOUT_VAL 1
+#define SLEEP_SLOP 3
+
+#define CCK_SIFS_TIME 10
+#define CCK_PREAMBLE_BITS 144
+#define CCK_PLCP_BITS 48
+
+#define OFDM_SIFS_TIME 16
+#define OFDM_PREAMBLE_TIME 20
+#define OFDM_PLCP_BITS 22
+#define OFDM_SYMBOL_TIME 4
+
+#define OFDM_SIFS_TIME_HALF 32
+#define OFDM_PREAMBLE_TIME_HALF 40
+#define OFDM_PLCP_BITS_HALF 22
+#define OFDM_SYMBOL_TIME_HALF 8
+
+#define OFDM_SIFS_TIME_QUARTER 64
+#define OFDM_PREAMBLE_TIME_QUARTER 80
+#define OFDM_PLCP_BITS_QUARTER 22
+#define OFDM_SYMBOL_TIME_QUARTER 16
+
+uint32_t ath9k_hw_get_eeprom(struct ath_hal *ah,
+ enum eeprom_param param);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARN_HW_H */
diff --git a/usr/src/uts/common/io/arn/arn_initvals.h b/usr/src/uts/common/io/arn/arn_initvals.h
new file mode 100644
index 0000000000..4186d82e0f
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_initvals.h
@@ -0,0 +1,6337 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARN_INITVALS_H
+#define _ARN_INITVALS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* AR5416 to Fowl ar5146.ini */
+static const uint32_t ar5416Modes_9100[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160,
+ 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c,
+ 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38,
+ 0x00001180 },
+ { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000,
+ 0x00014008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00,
+ 0x06e006e0 },
+ { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab,
+ 0x098813cf },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300,
+ 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200,
+ 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001,
+ 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007 },
+ { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0,
+ 0x137216a0 },
+ { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de,
+ 0x6c48b0de },
+ { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e,
+ 0x7ec82d2e },
+ { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e,
+ 0x31395d5e },
+ { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18,
+ 0x00049d18 },
+ { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00,
+ 0x0001ce00 },
+ { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190,
+ 0x409a4190 },
+ { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081,
+ 0x050cb081 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898,
+ 0x000007d0 },
+ { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134,
+ 0x00000134 },
+ { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b,
+ 0xd0058a0b },
+ { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020,
+ 0xffb81020 },
+ { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80,
+ 0x00012d80 },
+ { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80,
+ 0x00012d80 },
+ { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80,
+ 0x00012d80 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120,
+ 0x00001120 },
+ { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00,
+ 0x001a0a00 },
+ { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be,
+ 0x038919be },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77,
+ 0x06336f77 },
+ { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c,
+ 0x60f6532c },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8,
+ 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384,
+ 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880,
+ 0x00000880 },
+ { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788,
+ 0xd03e4788 },
+ { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a,
+ 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108,
+ 0x00000000 },
+ { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa,
+ 0x0a1a7caa },
+ { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000,
+ 0x18010000 },
+ { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402,
+ 0x2e032402 },
+ { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06,
+ 0x4a0a3c06 },
+ { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b,
+ 0x621a540b },
+ { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b,
+ 0x764f6c1b },
+ { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a,
+ 0x845b7a5a },
+ { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf,
+ 0x950f8ccf },
+ { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f,
+ 0xa5cf9b4f },
+ { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f,
+ 0xbddfaf1f },
+ { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f,
+ 0xd1ffc93f },
+ { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 }
+};
+
+static const uint32_t ar5416Common_9100[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00007010, 0x00000000 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x000080c0, 0x2a82301a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c4, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x00008300, 0x00000000 },
+ { 0x00008304, 0x00000000 },
+ { 0x00008308, 0x00000000 },
+ { 0x0000830c, 0x00000000 },
+ { 0x00008310, 0x00000000 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008318, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00070000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xad848e19 },
+ { 0x00009810, 0x7d14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x00009840, 0x206a002e },
+ { 0x0000984c, 0x1284233c },
+ { 0x00009854, 0x00000859 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x05100000 },
+ { 0x0000a920, 0x05100000 },
+ { 0x0000b920, 0x05100000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280b212 },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5d50e188 },
+ { 0x00009958, 0x00081fff },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x0000c968, 0x000003ce },
+ { 0x00009970, 0x190fb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x001fff00 },
+ { 0x000099ac, 0x00000000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000200 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x000000aa },
+ { 0x000099fc, 0x00001042 },
+ { 0x00009b00, 0x00000000 },
+ { 0x00009b04, 0x00000001 },
+ { 0x00009b08, 0x00000002 },
+ { 0x00009b0c, 0x00000003 },
+ { 0x00009b10, 0x00000004 },
+ { 0x00009b14, 0x00000005 },
+ { 0x00009b18, 0x00000008 },
+ { 0x00009b1c, 0x00000009 },
+ { 0x00009b20, 0x0000000a },
+ { 0x00009b24, 0x0000000b },
+ { 0x00009b28, 0x0000000c },
+ { 0x00009b2c, 0x0000000d },
+ { 0x00009b30, 0x00000010 },
+ { 0x00009b34, 0x00000011 },
+ { 0x00009b38, 0x00000012 },
+ { 0x00009b3c, 0x00000013 },
+ { 0x00009b40, 0x00000014 },
+ { 0x00009b44, 0x00000015 },
+ { 0x00009b48, 0x00000018 },
+ { 0x00009b4c, 0x00000019 },
+ { 0x00009b50, 0x0000001a },
+ { 0x00009b54, 0x0000001b },
+ { 0x00009b58, 0x0000001c },
+ { 0x00009b5c, 0x0000001d },
+ { 0x00009b60, 0x00000020 },
+ { 0x00009b64, 0x00000021 },
+ { 0x00009b68, 0x00000022 },
+ { 0x00009b6c, 0x00000023 },
+ { 0x00009b70, 0x00000024 },
+ { 0x00009b74, 0x00000025 },
+ { 0x00009b78, 0x00000028 },
+ { 0x00009b7c, 0x00000029 },
+ { 0x00009b80, 0x0000002a },
+ { 0x00009b84, 0x0000002b },
+ { 0x00009b88, 0x0000002c },
+ { 0x00009b8c, 0x0000002d },
+ { 0x00009b90, 0x00000030 },
+ { 0x00009b94, 0x00000031 },
+ { 0x00009b98, 0x00000032 },
+ { 0x00009b9c, 0x00000033 },
+ { 0x00009ba0, 0x00000034 },
+ { 0x00009ba4, 0x00000035 },
+ { 0x00009ba8, 0x00000035 },
+ { 0x00009bac, 0x00000035 },
+ { 0x00009bb0, 0x00000035 },
+ { 0x00009bb4, 0x00000035 },
+ { 0x00009bb8, 0x00000035 },
+ { 0x00009bbc, 0x00000035 },
+ { 0x00009bc0, 0x00000035 },
+ { 0x00009bc4, 0x00000035 },
+ { 0x00009bc8, 0x00000035 },
+ { 0x00009bcc, 0x00000035 },
+ { 0x00009bd0, 0x00000035 },
+ { 0x00009bd4, 0x00000035 },
+ { 0x00009bd8, 0x00000035 },
+ { 0x00009bdc, 0x00000035 },
+ { 0x00009be0, 0x00000035 },
+ { 0x00009be4, 0x00000035 },
+ { 0x00009be8, 0x00000035 },
+ { 0x00009bec, 0x00000035 },
+ { 0x00009bf0, 0x00000035 },
+ { 0x00009bf4, 0x00000035 },
+ { 0x00009bf8, 0x00000010 },
+ { 0x00009bfc, 0x0000001a },
+ { 0x0000a210, 0x40806333 },
+ { 0x0000a214, 0x00106c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x018830c6 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x00000bb5 },
+ { 0x0000a22c, 0x00000011 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c889af },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00007bb6 },
+ { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a24c, 0x00000001 },
+ { 0x0000a250, 0x0000a000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cc75380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9c6 },
+ { 0x0000b26c, 0x0ebae9c6 },
+ { 0x0000c26c, 0x0ebae9c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000a27c, 0x051701ce },
+ { 0x0000a338, 0x00000000 },
+ { 0x0000a33c, 0x00000000 },
+ { 0x0000a340, 0x00000000 },
+ { 0x0000a344, 0x00000000 },
+ { 0x0000a348, 0x3fffffff },
+ { 0x0000a34c, 0x3fffffff },
+ { 0x0000a350, 0x3fffffff },
+ { 0x0000a354, 0x0003ffff },
+ { 0x0000a358, 0x79a8aa1f },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x08000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+};
+
+static const uint32_t ar5416Bank0_9100[][2] = {
+ { 0x000098b0, 0x1e5795e5 },
+ { 0x000098e0, 0x02008020 },
+};
+
+static const uint32_t ar5416BB_RfGain_9100[][3] = {
+ { 0x00009a00, 0x00000000, 0x00000000 },
+ { 0x00009a04, 0x00000040, 0x00000040 },
+ { 0x00009a08, 0x00000080, 0x00000080 },
+ { 0x00009a0c, 0x000001a1, 0x00000141 },
+ { 0x00009a10, 0x000001e1, 0x00000181 },
+ { 0x00009a14, 0x00000021, 0x000001c1 },
+ { 0x00009a18, 0x00000061, 0x00000001 },
+ { 0x00009a1c, 0x00000168, 0x00000041 },
+ { 0x00009a20, 0x000001a8, 0x000001a8 },
+ { 0x00009a24, 0x000001e8, 0x000001e8 },
+ { 0x00009a28, 0x00000028, 0x00000028 },
+ { 0x00009a2c, 0x00000068, 0x00000068 },
+ { 0x00009a30, 0x00000189, 0x000000a8 },
+ { 0x00009a34, 0x000001c9, 0x00000169 },
+ { 0x00009a38, 0x00000009, 0x000001a9 },
+ { 0x00009a3c, 0x00000049, 0x000001e9 },
+ { 0x00009a40, 0x00000089, 0x00000029 },
+ { 0x00009a44, 0x00000170, 0x00000069 },
+ { 0x00009a48, 0x000001b0, 0x00000190 },
+ { 0x00009a4c, 0x000001f0, 0x000001d0 },
+ { 0x00009a50, 0x00000030, 0x00000010 },
+ { 0x00009a54, 0x00000070, 0x00000050 },
+ { 0x00009a58, 0x00000191, 0x00000090 },
+ { 0x00009a5c, 0x000001d1, 0x00000151 },
+ { 0x00009a60, 0x00000011, 0x00000191 },
+ { 0x00009a64, 0x00000051, 0x000001d1 },
+ { 0x00009a68, 0x00000091, 0x00000011 },
+ { 0x00009a6c, 0x000001b8, 0x00000051 },
+ { 0x00009a70, 0x000001f8, 0x00000198 },
+ { 0x00009a74, 0x00000038, 0x000001d8 },
+ { 0x00009a78, 0x00000078, 0x00000018 },
+ { 0x00009a7c, 0x00000199, 0x00000058 },
+ { 0x00009a80, 0x000001d9, 0x00000098 },
+ { 0x00009a84, 0x00000019, 0x00000159 },
+ { 0x00009a88, 0x00000059, 0x00000199 },
+ { 0x00009a8c, 0x00000099, 0x000001d9 },
+ { 0x00009a90, 0x000000d9, 0x00000019 },
+ { 0x00009a94, 0x000000f9, 0x00000059 },
+ { 0x00009a98, 0x000000f9, 0x00000099 },
+ { 0x00009a9c, 0x000000f9, 0x000000d9 },
+ { 0x00009aa0, 0x000000f9, 0x000000f9 },
+ { 0x00009aa4, 0x000000f9, 0x000000f9 },
+ { 0x00009aa8, 0x000000f9, 0x000000f9 },
+ { 0x00009aac, 0x000000f9, 0x000000f9 },
+ { 0x00009ab0, 0x000000f9, 0x000000f9 },
+ { 0x00009ab4, 0x000000f9, 0x000000f9 },
+ { 0x00009ab8, 0x000000f9, 0x000000f9 },
+ { 0x00009abc, 0x000000f9, 0x000000f9 },
+ { 0x00009ac0, 0x000000f9, 0x000000f9 },
+ { 0x00009ac4, 0x000000f9, 0x000000f9 },
+ { 0x00009ac8, 0x000000f9, 0x000000f9 },
+ { 0x00009acc, 0x000000f9, 0x000000f9 },
+ { 0x00009ad0, 0x000000f9, 0x000000f9 },
+ { 0x00009ad4, 0x000000f9, 0x000000f9 },
+ { 0x00009ad8, 0x000000f9, 0x000000f9 },
+ { 0x00009adc, 0x000000f9, 0x000000f9 },
+ { 0x00009ae0, 0x000000f9, 0x000000f9 },
+ { 0x00009ae4, 0x000000f9, 0x000000f9 },
+ { 0x00009ae8, 0x000000f9, 0x000000f9 },
+ { 0x00009aec, 0x000000f9, 0x000000f9 },
+ { 0x00009af0, 0x000000f9, 0x000000f9 },
+ { 0x00009af4, 0x000000f9, 0x000000f9 },
+ { 0x00009af8, 0x000000f9, 0x000000f9 },
+ { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const uint32_t ar5416Bank1_9100[][2] = {
+ { 0x000098b0, 0x02108421 },
+ { 0x000098ec, 0x00000008 },
+};
+
+static const uint32_t ar5416Bank2_9100[][2] = {
+ { 0x000098b0, 0x0e73ff17 },
+ { 0x000098e0, 0x00000420 },
+};
+
+static const uint32_t ar5416Bank3_9100[][3] = {
+ { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+static const uint32_t ar5416Bank6_9100[][3] = {
+
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00e00000, 0x00e00000 },
+ { 0x0000989c, 0x005e0000, 0x005e0000 },
+ { 0x0000989c, 0x00120000, 0x00120000 },
+ { 0x0000989c, 0x00620000, 0x00620000 },
+ { 0x0000989c, 0x00020000, 0x00020000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 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 ar5416Bank6TPC_9100[][3] = {
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00e00000, 0x00e00000 },
+ { 0x0000989c, 0x005e0000, 0x005e0000 },
+ { 0x0000989c, 0x00120000, 0x00120000 },
+ { 0x0000989c, 0x00620000, 0x00620000 },
+ { 0x0000989c, 0x00020000, 0x00020000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+ { 0x0000989c, 0x005f0000, 0x005f0000 },
+ { 0x0000989c, 0x00870000, 0x00870000 },
+ { 0x0000989c, 0x00f90000, 0x00f90000 },
+ { 0x0000989c, 0x007b0000, 0x007b0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00f50000, 0x00f50000 },
+ { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+ { 0x0000989c, 0x00110000, 0x00110000 },
+ { 0x0000989c, 0x006100a8, 0x006100a8 },
+ { 0x0000989c, 0x00423022, 0x00423022 },
+ { 0x0000989c, 0x201400df, 0x201400df },
+ { 0x0000989c, 0x00c40002, 0x00c40002 },
+ { 0x0000989c, 0x003000f2, 0x003000f2 },
+ { 0x0000989c, 0x00440016, 0x00440016 },
+ { 0x0000989c, 0x00410040, 0x00410040 },
+ { 0x0000989c, 0x0001805e, 0x0001805e },
+ { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+ { 0x0000989c, 0x000000e1, 0x000000e1 },
+ { 0x0000989c, 0x00007081, 0x00007081 },
+ { 0x0000989c, 0x000000d4, 0x000000d4 },
+ { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const uint32_t ar5416Bank7_9100[][2] = {
+ { 0x0000989c, 0x00000500 },
+ { 0x0000989c, 0x00000800 },
+ { 0x000098cc, 0x0000000e },
+};
+
+static const uint32_t ar5416Addac_9100[][2] = {
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000003 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x0000000c },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000030 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000060 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000058 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x000098c4, 0x00000000 },
+};
+
+/* ar5416 - howl ar5416_howl.ini */
+static const uint32_t ar5416Modes[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160,
+ 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c,
+ 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38,
+ 0x00001180 },
+ { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000,
+ 0x00014008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00,
+ 0x06e006e0 },
+ { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab,
+ 0x098813cf },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300,
+ 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200,
+ 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001,
+ 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007 },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0,
+ 0x037216a0 },
+ { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2,
+ 0x6d48b0e2 },
+ { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e,
+ 0x7ec82d2e },
+ { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e,
+ 0x3139605e },
+ { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20,
+ 0x00048d18 },
+ { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00,
+ 0x0001ce00 },
+ { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0,
+ 0x409a40d0 },
+ { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081,
+ 0x050cb081 },
+ { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898,
+ 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b,
+ 0x00000016 },
+ { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d,
+ 0xd00a8a0d },
+ { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204,
+ 0xfff81204 },
+ { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020,
+ 0xdfb81020 },
+ { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e,
+ 0xe250a51e },
+ { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff,
+ 0x3388ffff },
+#ifdef TB243
+ { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40,
+ 0x00012d80 },
+ { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40,
+ 0x00012d80 },
+ { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40,
+ 0x00012d80 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210,
+ 0x00001120 },
+#else
+ { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0,
+ 0x0001bfc0 },
+ { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0,
+ 0x0001bfc0 },
+ { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0,
+ 0x0001bfc0 },
+ { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120,
+ 0x00001120 },
+#endif
+ { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00,
+ 0x001a0c00 },
+ { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be,
+ 0x038919be },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77,
+ 0x06336f77 },
+ { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329,
+ 0x60f65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8,
+ 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384,
+ 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880,
+ 0x00000880 },
+ { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788,
+ 0xd03e4788 },
+ { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a,
+ 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108,
+ 0x00000000 },
+ { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa,
+ 0x0a1a7caa },
+ { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000,
+ 0x18010000 },
+ { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402,
+ 0x2e032402 },
+ { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06,
+ 0x4a0a3c06 },
+ { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b,
+ 0x621a540b },
+ { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b,
+ 0x764f6c1b },
+ { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a,
+ 0x845b7a5a },
+ { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf,
+ 0x950f8ccf },
+ { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f,
+ 0xa5cf9b4f },
+ { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f,
+ 0xbddfaf1f },
+ { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f,
+ 0xd1ffc93f },
+ { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+};
+
+static const 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 },
+ { 0x00020010, 0x00000003 },
+ { 0x00020038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00004000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x000080c0, 0x2a82301a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0x00000000 },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c4, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x00008300, 0x00000000 },
+ { 0x00008304, 0x00000000 },
+ { 0x00008308, 0x00000000 },
+ { 0x0000830c, 0x00000000 },
+ { 0x00008310, 0x00000000 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008318, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00000000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xad848e19 },
+ { 0x00009810, 0x7d14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x00009840, 0x206a01ae },
+ { 0x0000984c, 0x1284233c },
+ { 0x00009854, 0x00000859 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x05100000 },
+ { 0x0000a920, 0x05100000 },
+ { 0x0000b920, 0x05100000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280b212 },
+ { 0x0000994c, 0x00020028 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x0000c968, 0x000003ce },
+ { 0x00009970, 0x190fb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x006f0000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000200 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099fc, 0x00001042 },
+ { 0x00009b00, 0x00000000 },
+ { 0x00009b04, 0x00000001 },
+ { 0x00009b08, 0x00000002 },
+ { 0x00009b0c, 0x00000003 },
+ { 0x00009b10, 0x00000004 },
+ { 0x00009b14, 0x00000005 },
+ { 0x00009b18, 0x00000008 },
+ { 0x00009b1c, 0x00000009 },
+ { 0x00009b20, 0x0000000a },
+ { 0x00009b24, 0x0000000b },
+ { 0x00009b28, 0x0000000c },
+ { 0x00009b2c, 0x0000000d },
+ { 0x00009b30, 0x00000010 },
+ { 0x00009b34, 0x00000011 },
+ { 0x00009b38, 0x00000012 },
+ { 0x00009b3c, 0x00000013 },
+ { 0x00009b40, 0x00000014 },
+ { 0x00009b44, 0x00000015 },
+ { 0x00009b48, 0x00000018 },
+ { 0x00009b4c, 0x00000019 },
+ { 0x00009b50, 0x0000001a },
+ { 0x00009b54, 0x0000001b },
+ { 0x00009b58, 0x0000001c },
+ { 0x00009b5c, 0x0000001d },
+ { 0x00009b60, 0x00000020 },
+ { 0x00009b64, 0x00000021 },
+ { 0x00009b68, 0x00000022 },
+ { 0x00009b6c, 0x00000023 },
+ { 0x00009b70, 0x00000024 },
+ { 0x00009b74, 0x00000025 },
+ { 0x00009b78, 0x00000028 },
+ { 0x00009b7c, 0x00000029 },
+ { 0x00009b80, 0x0000002a },
+ { 0x00009b84, 0x0000002b },
+ { 0x00009b88, 0x0000002c },
+ { 0x00009b8c, 0x0000002d },
+ { 0x00009b90, 0x00000030 },
+ { 0x00009b94, 0x00000031 },
+ { 0x00009b98, 0x00000032 },
+ { 0x00009b9c, 0x00000033 },
+ { 0x00009ba0, 0x00000034 },
+ { 0x00009ba4, 0x00000035 },
+ { 0x00009ba8, 0x00000035 },
+ { 0x00009bac, 0x00000035 },
+ { 0x00009bb0, 0x00000035 },
+ { 0x00009bb4, 0x00000035 },
+ { 0x00009bb8, 0x00000035 },
+ { 0x00009bbc, 0x00000035 },
+ { 0x00009bc0, 0x00000035 },
+ { 0x00009bc4, 0x00000035 },
+ { 0x00009bc8, 0x00000035 },
+ { 0x00009bcc, 0x00000035 },
+ { 0x00009bd0, 0x00000035 },
+ { 0x00009bd4, 0x00000035 },
+ { 0x00009bd8, 0x00000035 },
+ { 0x00009bdc, 0x00000035 },
+ { 0x00009be0, 0x00000035 },
+ { 0x00009be4, 0x00000035 },
+ { 0x00009be8, 0x00000035 },
+ { 0x00009bec, 0x00000035 },
+ { 0x00009bf0, 0x00000035 },
+ { 0x00009bf4, 0x00000035 },
+ { 0x00009bf8, 0x00000010 },
+ { 0x00009bfc, 0x0000001a },
+ { 0x0000a210, 0x40806333 },
+ { 0x0000a214, 0x00106c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x018830c6 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x001a0bb5 },
+ { 0x0000a22c, 0x00000000 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c889ae },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00007bb6 },
+ { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a24c, 0x00000001 },
+ { 0x0000a250, 0x0000a000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cc75380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a268, 0x00000001 },
+ { 0x0000a26c, 0x0ebae9c6 },
+ { 0x0000b26c, 0x0ebae9c6 },
+ { 0x0000c26c, 0x0ebae9c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000a27c, 0x050701ce },
+ { 0x0000a338, 0x00000000 },
+ { 0x0000a33c, 0x00000000 },
+ { 0x0000a340, 0x00000000 },
+ { 0x0000a344, 0x00000000 },
+ { 0x0000a348, 0x3fffffff },
+ { 0x0000a34c, 0x3fffffff },
+ { 0x0000a350, 0x3fffffff },
+ { 0x0000a354, 0x0003ffff },
+ { 0x0000a358, 0x79a8aa33 },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+};
+
+static const 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 },
+};
+
+static const uint32_t ar5416Bank6[][3] = {
+
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00e00000, 0x00e00000 },
+ { 0x0000989c, 0x005e0000, 0x005e0000 },
+ { 0x0000989c, 0x00120000, 0x00120000 },
+ { 0x0000989c, 0x00620000, 0x00620000 },
+ { 0x0000989c, 0x00020000, 0x00020000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x005f0000, 0x005f0000 },
+ { 0x0000989c, 0x00870000, 0x00870000 },
+ { 0x0000989c, 0x00f90000, 0x00f90000 },
+ { 0x0000989c, 0x007b0000, 0x007b0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00f50000, 0x00f50000 },
+ { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+ { 0x0000989c, 0x00110000, 0x00110000 },
+ { 0x0000989c, 0x006100a8, 0x006100a8 },
+ { 0x0000989c, 0x004210a2, 0x004210a2 },
+ { 0x0000989c, 0x0014000f, 0x0014000f },
+ { 0x0000989c, 0x00c40002, 0x00c40002 },
+ { 0x0000989c, 0x003000f2, 0x003000f2 },
+ { 0x0000989c, 0x00440016, 0x00440016 },
+ { 0x0000989c, 0x00410040, 0x00410040 },
+ { 0x0000989c, 0x000180d6, 0x000180d6 },
+ { 0x0000989c, 0x0000c0aa, 0x0000c0aa },
+ { 0x0000989c, 0x000000b1, 0x000000b1 },
+ { 0x0000989c, 0x00002000, 0x00002000 },
+ { 0x0000989c, 0x000000d4, 0x000000d4 },
+ { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+
+static const uint32_t ar5416Bank6TPC[][3] = {
+
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00e00000, 0x00e00000 },
+ { 0x0000989c, 0x005e0000, 0x005e0000 },
+ { 0x0000989c, 0x00120000, 0x00120000 },
+ { 0x0000989c, 0x00620000, 0x00620000 },
+ { 0x0000989c, 0x00020000, 0x00020000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+ { 0x0000989c, 0x005f0000, 0x005f0000 },
+ { 0x0000989c, 0x00870000, 0x00870000 },
+ { 0x0000989c, 0x00f90000, 0x00f90000 },
+ { 0x0000989c, 0x007b0000, 0x007b0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00f50000, 0x00f50000 },
+ { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+ { 0x0000989c, 0x00110000, 0x00110000 },
+ { 0x0000989c, 0x006100a8, 0x006100a8 },
+ { 0x0000989c, 0x00423022, 0x00423022 },
+ { 0x0000989c, 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 ar5416Bank7[][2] = {
+ { 0x0000989c, 0x00000500 },
+ { 0x0000989c, 0x00000800 },
+ { 0x000098cc, 0x0000000e },
+};
+
+static const uint32_t ar5416Addac[][2] = {
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000010 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x000000c0 },
+ {0x0000989c, 0x00000015 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x000098cc, 0x00000000 },
+};
+
+/* AR5416 9160 Sowl ar5416_sowl.ini */
+static const uint32_t ar5416Modes_9160[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160,
+ 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c,
+ 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38,
+ 0x00001180 },
+ { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000,
+ 0x00014008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00,
+ 0x06e006e0 },
+ { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab,
+ 0x098813cf },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300,
+ 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200,
+ 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001,
+ 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007 },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0,
+ 0x037216a0 },
+ { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68,
+ 0x00197a68 },
+ { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2,
+ 0x6c48b0e2 },
+ { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e,
+ 0x7ec82d2e },
+ { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e,
+ 0x31395d5e },
+ { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20,
+ 0x00048d18 },
+ { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00,
+ 0x0001ce00 },
+ { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0,
+ 0x409a40d0 },
+ { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081,
+ 0x050cb081 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898,
+ 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b,
+ 0x00000016 },
+ { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d,
+ 0xd00a8a0d },
+ { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020,
+ 0xffb81020 },
+ { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40,
+ 0x00009b40 },
+ { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40,
+ 0x00009b40 },
+ { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40,
+ 0x00009b40 },
+ { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120,
+ 0x00001120 },
+ { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce,
+ 0x000003ce },
+ { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00,
+ 0x001a0c00 },
+ { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be,
+ 0x038919be },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77,
+ 0x06336f77 },
+ { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329,
+ 0x60f65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8,
+ 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384,
+ 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880,
+ 0x00000880 },
+ { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788,
+ 0xd03e4788 },
+ { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120,
+ 0x002ac120 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a,
+ 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108,
+ 0x00000000 },
+ { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa,
+ 0x0a1a7caa },
+ { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000,
+ 0x18010000 },
+ { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402,
+ 0x2e032402 },
+ { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06,
+ 0x4a0a3c06 },
+ { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b,
+ 0x621a540b },
+ { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b,
+ 0x764f6c1b },
+ { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a,
+ 0x845b7a5a },
+ { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf,
+ 0x950f8ccf },
+ { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f,
+ 0xa5cf9b4f },
+ { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f,
+ 0xbddfaf1f },
+ { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f,
+ 0xd1ffc93f },
+ { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+};
+
+static const uint32_t ar5416Common_9160[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00007010, 0x00000020 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x000080c0, 0x2a82301a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c4, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x00008300, 0x00000000 },
+ { 0x00008304, 0x00000000 },
+ { 0x00008308, 0x00000000 },
+ { 0x0000830c, 0x00000000 },
+ { 0x00008310, 0x00000000 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008318, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xad848e19 },
+ { 0x00009810, 0x7d14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x00009840, 0x206a01ae },
+ { 0x0000984c, 0x1284233c },
+ { 0x00009854, 0x00000859 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x05100000 },
+ { 0x0000a920, 0x05100000 },
+ { 0x0000b920, 0x05100000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280b212 },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x2108ecff },
+ { 0x00009940, 0x00750604 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x00009970, 0x190fb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x006f0000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000200 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099fc, 0x00001042 },
+ { 0x00009b00, 0x00000000 },
+ { 0x00009b04, 0x00000001 },
+ { 0x00009b08, 0x00000002 },
+ { 0x00009b0c, 0x00000003 },
+ { 0x00009b10, 0x00000004 },
+ { 0x00009b14, 0x00000005 },
+ { 0x00009b18, 0x00000008 },
+ { 0x00009b1c, 0x00000009 },
+ { 0x00009b20, 0x0000000a },
+ { 0x00009b24, 0x0000000b },
+ { 0x00009b28, 0x0000000c },
+ { 0x00009b2c, 0x0000000d },
+ { 0x00009b30, 0x00000010 },
+ { 0x00009b34, 0x00000011 },
+ { 0x00009b38, 0x00000012 },
+ { 0x00009b3c, 0x00000013 },
+ { 0x00009b40, 0x00000014 },
+ { 0x00009b44, 0x00000015 },
+ { 0x00009b48, 0x00000018 },
+ { 0x00009b4c, 0x00000019 },
+ { 0x00009b50, 0x0000001a },
+ { 0x00009b54, 0x0000001b },
+ { 0x00009b58, 0x0000001c },
+ { 0x00009b5c, 0x0000001d },
+ { 0x00009b60, 0x00000020 },
+ { 0x00009b64, 0x00000021 },
+ { 0x00009b68, 0x00000022 },
+ { 0x00009b6c, 0x00000023 },
+ { 0x00009b70, 0x00000024 },
+ { 0x00009b74, 0x00000025 },
+ { 0x00009b78, 0x00000028 },
+ { 0x00009b7c, 0x00000029 },
+ { 0x00009b80, 0x0000002a },
+ { 0x00009b84, 0x0000002b },
+ { 0x00009b88, 0x0000002c },
+ { 0x00009b8c, 0x0000002d },
+ { 0x00009b90, 0x00000030 },
+ { 0x00009b94, 0x00000031 },
+ { 0x00009b98, 0x00000032 },
+ { 0x00009b9c, 0x00000033 },
+ { 0x00009ba0, 0x00000034 },
+ { 0x00009ba4, 0x00000035 },
+ { 0x00009ba8, 0x00000035 },
+ { 0x00009bac, 0x00000035 },
+ { 0x00009bb0, 0x00000035 },
+ { 0x00009bb4, 0x00000035 },
+ { 0x00009bb8, 0x00000035 },
+ { 0x00009bbc, 0x00000035 },
+ { 0x00009bc0, 0x00000035 },
+ { 0x00009bc4, 0x00000035 },
+ { 0x00009bc8, 0x00000035 },
+ { 0x00009bcc, 0x00000035 },
+ { 0x00009bd0, 0x00000035 },
+ { 0x00009bd4, 0x00000035 },
+ { 0x00009bd8, 0x00000035 },
+ { 0x00009bdc, 0x00000035 },
+ { 0x00009be0, 0x00000035 },
+ { 0x00009be4, 0x00000035 },
+ { 0x00009be8, 0x00000035 },
+ { 0x00009bec, 0x00000035 },
+ { 0x00009bf0, 0x00000035 },
+ { 0x00009bf4, 0x00000035 },
+ { 0x00009bf8, 0x00000010 },
+ { 0x00009bfc, 0x0000001a },
+ { 0x0000a210, 0x40806333 },
+ { 0x0000a214, 0x00106c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x018830c6 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x001a0bb5 },
+ { 0x0000a22c, 0x00000000 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c889af },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00007bb6 },
+ { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a24c, 0x00000001 },
+ { 0x0000a250, 0x0000e000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cc75380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a268, 0x00000001 },
+ { 0x0000a26c, 0x0ebae9c6 },
+ { 0x0000b26c, 0x0ebae9c6 },
+ { 0x0000c26c, 0x0ebae9c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000a27c, 0x050701ce },
+ { 0x0000a338, 0x00000000 },
+ { 0x0000a33c, 0x00000000 },
+ { 0x0000a340, 0x00000000 },
+ { 0x0000a344, 0x00000000 },
+ { 0x0000a348, 0x3fffffff },
+ { 0x0000a34c, 0x3fffffff },
+ { 0x0000a350, 0x3fffffff },
+ { 0x0000a354, 0x0003ffff },
+ { 0x0000a358, 0x79bfaa03 },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+};
+
+static const uint32_t ar5416Bank0_9160[][2] = {
+ { 0x000098b0, 0x1e5795e5 },
+ { 0x000098e0, 0x02008020 },
+};
+
+static const uint32_t ar5416BB_RfGain_9160[][3] = {
+ { 0x00009a00, 0x00000000, 0x00000000 },
+ { 0x00009a04, 0x00000040, 0x00000040 },
+ { 0x00009a08, 0x00000080, 0x00000080 },
+ { 0x00009a0c, 0x000001a1, 0x00000141 },
+ { 0x00009a10, 0x000001e1, 0x00000181 },
+ { 0x00009a14, 0x00000021, 0x000001c1 },
+ { 0x00009a18, 0x00000061, 0x00000001 },
+ { 0x00009a1c, 0x00000168, 0x00000041 },
+ { 0x00009a20, 0x000001a8, 0x000001a8 },
+ { 0x00009a24, 0x000001e8, 0x000001e8 },
+ { 0x00009a28, 0x00000028, 0x00000028 },
+ { 0x00009a2c, 0x00000068, 0x00000068 },
+ { 0x00009a30, 0x00000189, 0x000000a8 },
+ { 0x00009a34, 0x000001c9, 0x00000169 },
+ { 0x00009a38, 0x00000009, 0x000001a9 },
+ { 0x00009a3c, 0x00000049, 0x000001e9 },
+ { 0x00009a40, 0x00000089, 0x00000029 },
+ { 0x00009a44, 0x00000170, 0x00000069 },
+ { 0x00009a48, 0x000001b0, 0x00000190 },
+ { 0x00009a4c, 0x000001f0, 0x000001d0 },
+ { 0x00009a50, 0x00000030, 0x00000010 },
+ { 0x00009a54, 0x00000070, 0x00000050 },
+ { 0x00009a58, 0x00000191, 0x00000090 },
+ { 0x00009a5c, 0x000001d1, 0x00000151 },
+ { 0x00009a60, 0x00000011, 0x00000191 },
+ { 0x00009a64, 0x00000051, 0x000001d1 },
+ { 0x00009a68, 0x00000091, 0x00000011 },
+ { 0x00009a6c, 0x000001b8, 0x00000051 },
+ { 0x00009a70, 0x000001f8, 0x00000198 },
+ { 0x00009a74, 0x00000038, 0x000001d8 },
+ { 0x00009a78, 0x00000078, 0x00000018 },
+ { 0x00009a7c, 0x00000199, 0x00000058 },
+ { 0x00009a80, 0x000001d9, 0x00000098 },
+ { 0x00009a84, 0x00000019, 0x00000159 },
+ { 0x00009a88, 0x00000059, 0x00000199 },
+ { 0x00009a8c, 0x00000099, 0x000001d9 },
+ { 0x00009a90, 0x000000d9, 0x00000019 },
+ { 0x00009a94, 0x000000f9, 0x00000059 },
+ { 0x00009a98, 0x000000f9, 0x00000099 },
+ { 0x00009a9c, 0x000000f9, 0x000000d9 },
+ { 0x00009aa0, 0x000000f9, 0x000000f9 },
+ { 0x00009aa4, 0x000000f9, 0x000000f9 },
+ { 0x00009aa8, 0x000000f9, 0x000000f9 },
+ { 0x00009aac, 0x000000f9, 0x000000f9 },
+ { 0x00009ab0, 0x000000f9, 0x000000f9 },
+ { 0x00009ab4, 0x000000f9, 0x000000f9 },
+ { 0x00009ab8, 0x000000f9, 0x000000f9 },
+ { 0x00009abc, 0x000000f9, 0x000000f9 },
+ { 0x00009ac0, 0x000000f9, 0x000000f9 },
+ { 0x00009ac4, 0x000000f9, 0x000000f9 },
+ { 0x00009ac8, 0x000000f9, 0x000000f9 },
+ { 0x00009acc, 0x000000f9, 0x000000f9 },
+ { 0x00009ad0, 0x000000f9, 0x000000f9 },
+ { 0x00009ad4, 0x000000f9, 0x000000f9 },
+ { 0x00009ad8, 0x000000f9, 0x000000f9 },
+ { 0x00009adc, 0x000000f9, 0x000000f9 },
+ { 0x00009ae0, 0x000000f9, 0x000000f9 },
+ { 0x00009ae4, 0x000000f9, 0x000000f9 },
+ { 0x00009ae8, 0x000000f9, 0x000000f9 },
+ { 0x00009aec, 0x000000f9, 0x000000f9 },
+ { 0x00009af0, 0x000000f9, 0x000000f9 },
+ { 0x00009af4, 0x000000f9, 0x000000f9 },
+ { 0x00009af8, 0x000000f9, 0x000000f9 },
+ { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const uint32_t ar5416Bank1_9160[][2] = {
+{ 0x000098b0, 0x02108421 },
+ {0x000098ec, 0x00000008 },
+};
+
+static const uint32_t ar5416Bank2_9160[][2] = {
+ { 0x000098b0, 0x0e73ff17 },
+ { 0x000098e0, 0x00000420 },
+};
+
+static const uint32_t ar5416Bank3_9160[][3] = {
+ { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+static const uint32_t ar5416Bank6_9160[][3] = {
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00e00000, 0x00e00000 },
+ { 0x0000989c, 0x005e0000, 0x005e0000 },
+ { 0x0000989c, 0x00120000, 0x00120000 },
+ { 0x0000989c, 0x00620000, 0x00620000 },
+ { 0x0000989c, 0x00020000, 0x00020000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+ { 0x0000989c, 0x005f0000, 0x005f0000 },
+ { 0x0000989c, 0x00870000, 0x00870000 },
+ { 0x0000989c, 0x00f90000, 0x00f90000 },
+ { 0x0000989c, 0x007b0000, 0x007b0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00f50000, 0x00f50000 },
+ { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+ { 0x0000989c, 0x00110000, 0x00110000 },
+ { 0x0000989c, 0x006100a8, 0x006100a8 },
+ { 0x0000989c, 0x004210a2, 0x004210a2 },
+ { 0x0000989c, 0x0014008f, 0x0014008f },
+ { 0x0000989c, 0x00c40003, 0x00c40003 },
+ { 0x0000989c, 0x003000f2, 0x003000f2 },
+ { 0x0000989c, 0x00440016, 0x00440016 },
+ { 0x0000989c, 0x00410040, 0x00410040 },
+ { 0x0000989c, 0x0001805e, 0x0001805e },
+ { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+ { 0x0000989c, 0x000000f1, 0x000000f1 },
+ { 0x0000989c, 0x00002081, 0x00002081 },
+ { 0x0000989c, 0x000000d4, 0x000000d4 },
+ { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const uint32_t ar5416Bank6TPC_9160[][3] = {
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00000000, 0x00000000 },
+ { 0x0000989c, 0x00e00000, 0x00e00000 },
+ { 0x0000989c, 0x005e0000, 0x005e0000 },
+ { 0x0000989c, 0x00120000, 0x00120000 },
+ { 0x0000989c, 0x00620000, 0x00620000 },
+ { 0x0000989c, 0x00020000, 0x00020000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+ { 0x0000989c, 0x005f0000, 0x005f0000 },
+ { 0x0000989c, 0x00870000, 0x00870000 },
+ { 0x0000989c, 0x00f90000, 0x00f90000 },
+ { 0x0000989c, 0x007b0000, 0x007b0000 },
+ { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+ { 0x0000989c, 0x00f50000, 0x00f50000 },
+ { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+ { 0x0000989c, 0x00110000, 0x00110000 },
+ { 0x0000989c, 0x006100a8, 0x006100a8 },
+ { 0x0000989c, 0x00423022, 0x00423022 },
+ { 0x0000989c, 0x2014008f, 0x2014008f },
+ { 0x0000989c, 0x00c40002, 0x00c40002 },
+ { 0x0000989c, 0x003000f2, 0x003000f2 },
+ { 0x0000989c, 0x00440016, 0x00440016 },
+ { 0x0000989c, 0x00410040, 0x00410040 },
+ { 0x0000989c, 0x0001805e, 0x0001805e },
+ { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+ { 0x0000989c, 0x000000e1, 0x000000e1 },
+ { 0x0000989c, 0x00007080, 0x00007080 },
+ { 0x0000989c, 0x000000d4, 0x000000d4 },
+ { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const uint32_t ar5416Bank7_9160[][2] = {
+ { 0x0000989c, 0x00000500 },
+ { 0x0000989c, 0x00000800 },
+ { 0x000098cc, 0x0000000e },
+};
+
+static uint32_t ar5416Addac_9160[][2] = {
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x000000c0 },
+ {0x0000989c, 0x00000018 },
+ {0x0000989c, 0x00000004 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x000000c0 },
+ {0x0000989c, 0x00000019 },
+ {0x0000989c, 0x00000004 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000004 },
+ {0x0000989c, 0x00000003 },
+ {0x0000989c, 0x00000008 },
+ {0x0000989c, 0x00000000 },
+ {0x000098cc, 0x00000000 },
+};
+
+static uint32_t ar5416Addac_91601_1[][2] = {
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x000000c0 },
+ {0x0000989c, 0x00000018 },
+ {0x0000989c, 0x00000004 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x000000c0 },
+ {0x0000989c, 0x00000019 },
+ {0x0000989c, 0x00000004 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x0000989c, 0x00000000 },
+ {0x000098cc, 0x00000000 },
+};
+
+/* XXX 9280 1 */
+static const uint32_t ar9280Modes_9280[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160,
+ 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c,
+ 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38,
+ 0x00001180 },
+ { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000,
+ 0x00014008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840,
+ 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b,
+ 0x0988004f },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300,
+ 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200,
+ 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001,
+ 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007 },
+ { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0,
+ 0x137216a0 },
+ { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563,
+ 0x00028563 },
+ { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563,
+ 0x00028563 },
+ { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2,
+ 0x6d4000e2 },
+ { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e,
+ 0x7ec82d2e },
+ { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e,
+ 0x3139605e },
+ { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20,
+ 0x00049d18 },
+ { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00,
+ 0x0001ce00 },
+ { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190,
+ 0x5ac64190 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881,
+ 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898,
+ 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b,
+ 0x00000016 },
+ { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d,
+ 0xd00a8a0d },
+ { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010,
+ 0xdfbc1010 },
+ { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010 },
+ { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010 },
+ { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210,
+ 0x00000210 },
+ { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a,
+ 0x0000001a },
+ { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00,
+ 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4,
+ 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77,
+ 0x06336f77 },
+ { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c,
+ 0x60f6532c },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8,
+ 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384,
+ 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214,
+ 0x00000214 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218,
+ 0x00000218 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224,
+ 0x00000224 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228,
+ 0x00000228 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c,
+ 0x0000022c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230,
+ 0x00000230 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4,
+ 0x000002a4 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8,
+ 0x000002a8 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac,
+ 0x000002ac },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0,
+ 0x000002b0 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4,
+ 0x000002b4 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8,
+ 0x000002b8 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390,
+ 0x00000390 },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394,
+ 0x00000394 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398,
+ 0x00000398 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334,
+ 0x00000334 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338,
+ 0x00000338 },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac,
+ 0x000003ac },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0,
+ 0x000003b0 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4,
+ 0x000003b4 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8,
+ 0x000003b8 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5,
+ 0x000003a5 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9,
+ 0x000003a9 },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad,
+ 0x000003ad },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194,
+ 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0,
+ 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c,
+ 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8,
+ 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284,
+ 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288,
+ 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224,
+ 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290,
+ 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300,
+ 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304,
+ 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308,
+ 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c,
+ 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380,
+ 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384,
+ 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700,
+ 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704,
+ 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708,
+ 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c,
+ 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780,
+ 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784,
+ 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00,
+ 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04,
+ 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08,
+ 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c,
+ 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80,
+ 0x00008b80 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84,
+ 0x00008b84 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88,
+ 0x00008b88 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c,
+ 0x00008b8c },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90,
+ 0x00008b90 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80,
+ 0x00008f80 },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84,
+ 0x00008f84 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88,
+ 0x00008f88 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c,
+ 0x00008f8c },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90,
+ 0x00008f90 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c,
+ 0x0000930c },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310,
+ 0x00009310 },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384,
+ 0x00009384 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388,
+ 0x00009388 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324,
+ 0x00009324 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704,
+ 0x00009704 },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4,
+ 0x000096a4 },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8,
+ 0x000096a8 },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710,
+ 0x00009710 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714,
+ 0x00009714 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720,
+ 0x00009720 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724,
+ 0x00009724 },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728,
+ 0x00009728 },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c,
+ 0x0000972c },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0,
+ 0x000097a0 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4,
+ 0x000097a4 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8,
+ 0x000097a8 },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0,
+ 0x000097b0 },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4,
+ 0x000097b4 },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8,
+ 0x000097b8 },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5,
+ 0x000097a5 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9,
+ 0x000097a9 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad,
+ 0x000097ad },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1,
+ 0x000097b1 },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5,
+ 0x000097b5 },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9,
+ 0x000097b9 },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5,
+ 0x000097c5 },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9,
+ 0x000097c9 },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1,
+ 0x000097d1 },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5,
+ 0x000097d5 },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9,
+ 0x000097d9 },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6,
+ 0x000097c6 },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca,
+ 0x000097ca },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce,
+ 0x000097ce },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2,
+ 0x000097d2 },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6,
+ 0x000097d6 },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3,
+ 0x000097c3 },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7,
+ 0x000097c7 },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb,
+ 0x000097cb },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf,
+ 0x000097cf },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7,
+ 0x000097d7 },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444,
+ 0x00000444 },
+ { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788,
+ 0x803e4788 },
+ { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019,
+ 0x000c6019 },
+ { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019,
+ 0x000c6019 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a,
+ 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108,
+ 0x00000000 },
+ { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652,
+ 0x0a1aa652 },
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002,
+ 0x00003002 },
+ { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009,
+ 0x00008009 },
+ { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b,
+ 0x0000b00b },
+ { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012,
+ 0x0000e012 },
+ { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048,
+ 0x00012048 },
+ { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a,
+ 0x0001604a },
+ { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211,
+ 0x0001a211 },
+ { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213,
+ 0x0001e213 },
+ { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b,
+ 0x0002121b },
+ { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412,
+ 0x00024412 },
+ { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414,
+ 0x00028414 },
+ { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a,
+ 0x0002b44a },
+ { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649,
+ 0x00030649 },
+ { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b,
+ 0x0003364b },
+ { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49,
+ 0x00038a49 },
+ { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48,
+ 0x0003be48 },
+ { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a,
+ 0x0003ee4a },
+ { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88,
+ 0x00042e88 },
+ { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a,
+ 0x00046e8a },
+ { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9,
+ 0x00049ec9 },
+ { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42,
+ 0x0004bf42 },
+ { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c,
+ 0x0e4d048c },
+ { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828,
+ 0x12035828 },
+ { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000,
+ 0x807ec000 },
+ { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000,
+ 0x00110000 },
+};
+
+static const uint32_t ar9280Common_9280[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00007010, 0x00000033 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a82301a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0x00000000 },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c4, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x00008300, 0x00000000 },
+ { 0x00008304, 0x00000000 },
+ { 0x00008308, 0x00000000 },
+ { 0x0000830c, 0x00000000 },
+ { 0x00008310, 0x00000000 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008318, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00000000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00008344, 0x00000000 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xaf268e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x00009840, 0x206a01ae },
+ { 0x0000984c, 0x0040233c },
+ { 0x0000a84c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x0000a920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0xe250a51e },
+ { 0x00009958, 0x3388ffff },
+ { 0x00009940, 0x00781204 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x0000c968, 0x000003ce },
+ { 0x00009970, 0x190fb514 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x006f00c4 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099fc, 0x00001042 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x40206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x23277200 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c889af },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00007bb6 },
+ { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a24c, 0x00000001 },
+ { 0x0000a250, 0x001da000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cdbd380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9c6 },
+ { 0x0000b26c, 0x0ebae9c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000a27c, 0x050701ce },
+ { 0x0000a358, 0x7999aa0f },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f38081 },
+ { 0x00007800, 0x00040000 },
+ { 0x00007804, 0xdb005012 },
+ { 0x00007808, 0x04924914 },
+ { 0x0000780c, 0x21084210 },
+ { 0x00007810, 0x6d801300 },
+ { 0x00007814, 0x0019beff },
+ { 0x00007818, 0x07e40000 },
+ { 0x0000781c, 0x00492000 },
+ { 0x00007820, 0x92492480 },
+ { 0x00007824, 0x00040000 },
+ { 0x00007828, 0xdb005012 },
+ { 0x0000782c, 0x04924914 },
+ { 0x00007830, 0x21084210 },
+ { 0x00007834, 0x6d801300 },
+ { 0x00007838, 0x0019beff },
+ { 0x0000783c, 0x07e40000 },
+ { 0x00007840, 0x00492000 },
+ { 0x00007844, 0x92492480 },
+ { 0x00007848, 0x00120000 },
+ { 0x00007850, 0x54214514 },
+ { 0x00007858, 0x92592692 },
+ { 0x00007860, 0x52802000 },
+ { 0x00007864, 0x0a8e370e },
+ { 0x00007868, 0xc0102850 },
+ { 0x0000786c, 0x812d4000 },
+ { 0x00007874, 0x001b6db0 },
+ { 0x00007878, 0x00376b63 },
+ { 0x0000787c, 0x06db6db6 },
+ { 0x00007880, 0x006d8000 },
+ { 0x00007884, 0xffeffffe },
+ { 0x00007888, 0xffeffffe },
+ { 0x00007890, 0x00060aeb },
+ { 0x00007894, 0x5a108000 },
+ { 0x00007898, 0x2a850160 },
+};
+
+/* XXX 9280 2 */
+static const uint32_t ar9280Modes_9280_2[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160,
+ 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c,
+ 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38,
+ 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00,
+ 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b,
+ 0x0988004f },
+ { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440,
+ 0x00006880 },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300,
+ 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200,
+ 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001,
+ 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007 },
+ { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e,
+ 0x206a012e },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0,
+ 0x037216a0 },
+ { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2,
+ 0x6c4000e2 },
+ { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e,
+ 0x7ec84d2e },
+ { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e,
+ 0x31395d5e },
+ { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20,
+ 0x00048d18 },
+ { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00,
+ 0x0001ce00 },
+ { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0,
+ 0x5ac640d0 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881,
+ 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898,
+ 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b,
+ 0x00000016 },
+ { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d,
+ 0xd00a8a0d },
+ { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010,
+ 0xffbc1010 },
+ { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010 },
+ { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010 },
+ { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210,
+ 0x00000210 },
+ { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c,
+ 0x0000001c },
+ { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00,
+ 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4,
+ 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77,
+ 0x06336f77 },
+ { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329,
+ 0x60f65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8,
+ 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384,
+ 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444,
+ 0x00000444 },
+ { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019,
+ 0x0001f019 },
+ { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019,
+ 0x0001f019 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a,
+ 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108,
+ 0x00000000 },
+ { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000,
+ 0x0004a000 },
+ { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652,
+ 0x0a1aa652 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e,
+ 0x7999aa0e },
+ { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000,
+ 0x5a508000 },
+};
+
+static const uint32_t ar9280Common_9280_2[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00007010, 0x00000033 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00008344, 0x00581043 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafa68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x0000a84c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x01002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x0000a920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x2108ecff },
+ { 0x00009940, 0x14750604 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x00009968, 0x000003ce },
+ { 0x00009970, 0x190fb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x006f0000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x000099fc, 0x00001042 },
+ { 0x0000a208, 0x803e4788 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x40206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x233f7180 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c88000 },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00007bb6 },
+ { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cdbd380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9c6 },
+ { 0x0000b26c, 0x0ebae9c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x00007800, 0x00040000 },
+ { 0x00007804, 0xdb005012 },
+ { 0x00007808, 0x04924914 },
+ { 0x0000780c, 0x21084210 },
+ { 0x00007810, 0x6d801300 },
+ { 0x00007818, 0x07e41000 },
+ { 0x0000781c, 0x00392000 },
+ { 0x00007820, 0x92592480 },
+ { 0x00007824, 0x00040000 },
+ { 0x00007828, 0xdb005012 },
+ { 0x0000782c, 0x04924914 },
+ { 0x00007830, 0x21084210 },
+ { 0x00007834, 0x6d801300 },
+ { 0x0000783c, 0x07e40000 },
+ { 0x00007840, 0x00392000 },
+ { 0x00007844, 0x92592480 },
+ { 0x00007848, 0x00100000 },
+ { 0x0000784c, 0x773f0567 },
+ { 0x00007850, 0x54214514 },
+ { 0x00007854, 0x12035828 },
+ { 0x00007858, 0x9259269a },
+ { 0x00007860, 0x52802000 },
+ { 0x00007864, 0x0a8e370e },
+ { 0x00007868, 0xc0102850 },
+ { 0x0000786c, 0x812d4000 },
+ { 0x00007870, 0x807ec400 },
+ { 0x00007874, 0x001b6db0 },
+ { 0x00007878, 0x00376b63 },
+ { 0x0000787c, 0x06db6db6 },
+ { 0x00007880, 0x006d8000 },
+ { 0x00007884, 0xffeffffe },
+ { 0x00007888, 0xffeffffe },
+ { 0x0000788c, 0x00010000 },
+ { 0x00007890, 0x02060aeb },
+ { 0x00007898, 0x2a850160 },
+};
+
+static const uint32_t ar9280Modes_fast_clock_9280_2[][3] = {
+ { 0x00001030, 0x00000268, 0x000004d0 },
+ { 0x00001070, 0x0000018c, 0x00000318 },
+ { 0x000010b0, 0x00000fd0, 0x00001fa0 },
+ { 0x00008014, 0x044c044c, 0x08980898 },
+ { 0x0000801c, 0x148ec02b, 0x148ec057 },
+ { 0x00008318, 0x000044c0, 0x00008980 },
+ { 0x00009820, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000f0f, 0x00000f0f },
+ { 0x00009828, 0x0b020001, 0x0b020001 },
+ { 0x00009834, 0x00000f0f, 0x00000f0f },
+ { 0x00009844, 0x03721821, 0x03721821 },
+ { 0x00009914, 0x00000898, 0x00001130 },
+ { 0x00009918, 0x0000000b, 0x00000016 },
+ { 0x00009944, 0xdfbc1210, 0xdfbc1210 },
+};
+
+static const uint32_t ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290,
+ 0x00000290 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300,
+ 0x00000300 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304,
+ 0x00000304 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308,
+ 0x00000308 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c,
+ 0x0000030c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000,
+ 0x00008000 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004,
+ 0x00008004 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008,
+ 0x00008008 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c,
+ 0x0000800c },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080,
+ 0x00008080 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084,
+ 0x00008084 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088,
+ 0x00008088 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c,
+ 0x0000808c },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100,
+ 0x00008100 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104,
+ 0x00008104 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108,
+ 0x00008108 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c,
+ 0x0000810c },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110,
+ 0x00008110 },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114,
+ 0x00008114 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180,
+ 0x00008180 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184,
+ 0x00008184 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188,
+ 0x00008188 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c,
+ 0x0000818c },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190,
+ 0x00008190 },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194,
+ 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0,
+ 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c,
+ 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8,
+ 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284,
+ 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288,
+ 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224,
+ 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290,
+ 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300,
+ 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304,
+ 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308,
+ 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c,
+ 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380,
+ 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384,
+ 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700,
+ 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704,
+ 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708,
+ 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c,
+ 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780,
+ 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784,
+ 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00,
+ 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04,
+ 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08,
+ 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c,
+ 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10,
+ 0x00008b10 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14,
+ 0x00008b14 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01,
+ 0x00008b01 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05,
+ 0x00008b05 },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09,
+ 0x00008b09 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d,
+ 0x00008b0d },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11,
+ 0x00008b11 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15,
+ 0x00008b15 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02,
+ 0x00008b02 },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06,
+ 0x00008b06 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a,
+ 0x00008b0a },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e,
+ 0x00008b0e },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12,
+ 0x00008b12 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16,
+ 0x00008b16 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03,
+ 0x00008b03 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07,
+ 0x00008b07 },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b,
+ 0x00008b0b },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f,
+ 0x00008b0f },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13,
+ 0x00008b13 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17,
+ 0x00008b17 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23,
+ 0x00008b23 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27,
+ 0x00008b27 },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b,
+ 0x00008b2b },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f,
+ 0x00008b2f },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33,
+ 0x00008b33 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37,
+ 0x00008b37 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43,
+ 0x00008b43 },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47,
+ 0x00008b47 },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b,
+ 0x00008b4b },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f,
+ 0x00008b4f },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53,
+ 0x00008b53 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57,
+ 0x00008b57 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050,
+ 0x00001050 },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050,
+ 0x00001050 },
+};
+
+static const uint32_t ar9280Modes_original_rxgain_9280_2[][6] = {
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290,
+ 0x00000290 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300,
+ 0x00000300 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304,
+ 0x00000304 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308,
+ 0x00000308 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c,
+ 0x0000030c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000,
+ 0x00008000 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004,
+ 0x00008004 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008,
+ 0x00008008 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c,
+ 0x0000800c },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080,
+ 0x00008080 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084,
+ 0x00008084 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088,
+ 0x00008088 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c,
+ 0x0000808c },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100,
+ 0x00008100 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104,
+ 0x00008104 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108,
+ 0x00008108 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c,
+ 0x0000810c },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110,
+ 0x00008110 },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114,
+ 0x00008114 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180,
+ 0x00008180 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184,
+ 0x00008184 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188,
+ 0x00008188 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c,
+ 0x0000818c },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190,
+ 0x00008190 },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194,
+ 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0,
+ 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c,
+ 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8,
+ 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284,
+ 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288,
+ 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224,
+ 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290,
+ 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300,
+ 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304,
+ 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308,
+ 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c,
+ 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380,
+ 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384,
+ 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700,
+ 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704,
+ 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708,
+ 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c,
+ 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780,
+ 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784,
+ 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00,
+ 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04,
+ 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08,
+ 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c,
+ 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80,
+ 0x00008b80 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84,
+ 0x00008b84 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88,
+ 0x00008b88 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c,
+ 0x00008b8c },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90,
+ 0x00008b90 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80,
+ 0x00008f80 },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84,
+ 0x00008f84 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88,
+ 0x00008f88 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c,
+ 0x00008f8c },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90,
+ 0x00008f90 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c,
+ 0x0000930c },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310,
+ 0x00009310 },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384,
+ 0x00009384 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388,
+ 0x00009388 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324,
+ 0x00009324 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704,
+ 0x00009704 },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4,
+ 0x000096a4 },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8,
+ 0x000096a8 },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710,
+ 0x00009710 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714,
+ 0x00009714 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720,
+ 0x00009720 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724,
+ 0x00009724 },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728,
+ 0x00009728 },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c,
+ 0x0000972c },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0,
+ 0x000097a0 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4,
+ 0x000097a4 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8,
+ 0x000097a8 },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0,
+ 0x000097b0 },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4,
+ 0x000097b4 },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8,
+ 0x000097b8 },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5,
+ 0x000097a5 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9,
+ 0x000097a9 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad,
+ 0x000097ad },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1,
+ 0x000097b1 },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5,
+ 0x000097b5 },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9,
+ 0x000097b9 },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5,
+ 0x000097c5 },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9,
+ 0x000097c9 },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1,
+ 0x000097d1 },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5,
+ 0x000097d5 },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9,
+ 0x000097d9 },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6,
+ 0x000097c6 },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca,
+ 0x000097ca },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce,
+ 0x000097ce },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2,
+ 0x000097d2 },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6,
+ 0x000097d6 },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3,
+ 0x000097c3 },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7,
+ 0x000097c7 },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb,
+ 0x000097cb },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf,
+ 0x000097cf },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7,
+ 0x000097d7 },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db,
+ 0x000097db },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063,
+ 0x00001063 },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063,
+ 0x00001063 },
+};
+
+static const uint32_t ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290,
+ 0x00000290 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300,
+ 0x00000300 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304,
+ 0x00000304 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308,
+ 0x00000308 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c,
+ 0x0000030c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000,
+ 0x00008000 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004,
+ 0x00008004 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008,
+ 0x00008008 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c,
+ 0x0000800c },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080,
+ 0x00008080 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084,
+ 0x00008084 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088,
+ 0x00008088 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c,
+ 0x0000808c },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100,
+ 0x00008100 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104,
+ 0x00008104 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108,
+ 0x00008108 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c,
+ 0x0000810c },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110,
+ 0x00008110 },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114,
+ 0x00008114 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180,
+ 0x00008180 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184,
+ 0x00008184 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188,
+ 0x00008188 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c,
+ 0x0000818c },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190,
+ 0x00008190 },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194,
+ 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0,
+ 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c,
+ 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8,
+ 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284,
+ 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288,
+ 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224,
+ 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290,
+ 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300,
+ 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304,
+ 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308,
+ 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c,
+ 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380,
+ 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384,
+ 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700,
+ 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704,
+ 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708,
+ 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c,
+ 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780,
+ 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784,
+ 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00,
+ 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04,
+ 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08,
+ 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c,
+ 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80,
+ 0x00008b80 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84,
+ 0x00008b84 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88,
+ 0x00008b88 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c,
+ 0x00008b8c },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90,
+ 0x00008b90 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80,
+ 0x00008f80 },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84,
+ 0x00008f84 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88,
+ 0x00008f88 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c,
+ 0x00008f8c },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90,
+ 0x00008f90 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310,
+ 0x00009310 },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314,
+ 0x00009314 },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320,
+ 0x00009320 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324,
+ 0x00009324 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328,
+ 0x00009328 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c,
+ 0x0000932c },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330,
+ 0x00009330 },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334,
+ 0x00009334 },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321,
+ 0x00009321 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325,
+ 0x00009325 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329,
+ 0x00009329 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d,
+ 0x0000932d },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331,
+ 0x00009331 },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335,
+ 0x00009335 },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322,
+ 0x00009322 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326,
+ 0x00009326 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a,
+ 0x0000932a },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e,
+ 0x0000932e },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332,
+ 0x00009332 },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336,
+ 0x00009336 },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323,
+ 0x00009323 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327,
+ 0x00009327 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b,
+ 0x0000932b },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f,
+ 0x0000932f },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333,
+ 0x00009333 },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337,
+ 0x00009337 },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343,
+ 0x00009343 },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347,
+ 0x00009347 },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b,
+ 0x0000934b },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f,
+ 0x0000934f },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353,
+ 0x00009353 },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357,
+ 0x00009357 },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b,
+ 0x0000935b },
+ { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a,
+ 0x0000105a },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a,
+ 0x0000105a },
+};
+
+static const uint32_t ar9280Modes_high_power_tx_gain_9280_2[][6] = {
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002,
+ 0x00004002 },
+ { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008,
+ 0x00007008 },
+ { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010,
+ 0x0000c010 },
+ { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012,
+ 0x00010012 },
+ { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014,
+ 0x00013014 },
+ { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a,
+ 0x0001820a },
+ { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211,
+ 0x0001b211 },
+ { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213,
+ 0x0001e213 },
+ { 0x0000a324, 0x00020092, 0x00020092, 0x00022411, 0x00022411,
+ 0x00022411 },
+ { 0x0000a328, 0x0002410a, 0x0002410a, 0x00025413, 0x00025413,
+ 0x00025413 },
+ { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00029811, 0x00029811,
+ 0x00029811 },
+ { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002c813, 0x0002c813,
+ 0x0002c813 },
+ { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030a14, 0x00030a14,
+ 0x00030a14 },
+ { 0x0000a338, 0x000321ec, 0x000321ec, 0x00035a50, 0x00035a50,
+ 0x00035a50 },
+ { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00039c4c, 0x00039c4c,
+ 0x00039c4c },
+ { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003de8a, 0x0003de8a,
+ 0x0003de8a },
+ { 0x0000a344, 0x000321ec, 0x000321ec, 0x00042e92, 0x00042e92,
+ 0x00042e92 },
+ { 0x0000a348, 0x000321ec, 0x000321ec, 0x00046ed2, 0x00046ed2,
+ 0x00046ed2 },
+ { 0x0000a34c, 0x000321ec, 0x000321ec, 0x0004bed5, 0x0004bed5,
+ 0x0004bed5 },
+ { 0x0000a350, 0x000321ec, 0x000321ec, 0x0004ff54, 0x0004ff54,
+ 0x0004ff54 },
+ { 0x0000a354, 0x000321ec, 0x000321ec, 0x00053fd5, 0x00053fd5,
+ 0x00053fd5 },
+ { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff,
+ 0x00198eff },
+ { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff,
+ 0x00198eff },
+ { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce,
+ 0x050739ce },
+};
+
+static const uint32_t ar9280Modes_original_tx_gain_9280_2[][6] = {
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002,
+ 0x00003002 },
+ { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009,
+ 0x00008009 },
+ { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b,
+ 0x0000b00b },
+ { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012,
+ 0x0000e012 },
+ { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048,
+ 0x00012048 },
+ { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a,
+ 0x0001604a },
+ { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211,
+ 0x0001a211 },
+ { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213,
+ 0x0001e213 },
+ { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b,
+ 0x0002121b },
+ { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412,
+ 0x00024412 },
+ { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414,
+ 0x00028414 },
+ { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a,
+ 0x0002b44a },
+ { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649,
+ 0x00030649 },
+ { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b,
+ 0x0003364b },
+ { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49,
+ 0x00038a49 },
+ { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48,
+ 0x0003be48 },
+ { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a,
+ 0x0003ee4a },
+ { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88,
+ 0x00042e88 },
+ { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a,
+ 0x00046e8a },
+ { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9,
+ 0x00049ec9 },
+ { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42,
+ 0x0004bf42 },
+ { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff,
+ 0x0019beff },
+ { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff,
+ 0x0019beff },
+ { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce,
+ 0x050701ce },
+};
+
+static const uint32_t ar9280PciePhy_clkreq_off_L1_9280[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+static const uint32_t ar9280PciePhy_clkreq_always_on_L1_9280[][2] =
+{
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 }
+};
+
+/* AR9285 */
+static const uint32_t ar9285Modes_9285[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160,
+ 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c,
+ 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38,
+ 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00,
+ 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b,
+ 0x0988004f },
+ { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440,
+ 0x00006880 },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300,
+ 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200,
+ 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001,
+ 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007 },
+ { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e,
+ 0x206a012e },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020,
+ 0x037216a0 },
+ { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e,
+ 0x00001059 },
+ { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2,
+ 0x6d4000e2 },
+ { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e,
+ 0x7ec84d2e },
+ { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e,
+ 0x3139605e },
+ { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20,
+ 0x00058d18 },
+ { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00,
+ 0x0001ce00 },
+ { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0,
+ 0x5ac640d0 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881,
+ 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898,
+ 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b,
+ 0x00000016 },
+ { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d,
+ 0xd00a800d },
+ { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020,
+ 0xdfbc1010 },
+ { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c,
+ 0x00cf4d1c },
+ { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00,
+ 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4,
+ 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77,
+ 0x06336f77 },
+ { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329,
+ 0x60f65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8,
+ 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384,
+ 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084,
+ 0x00000000 },
+ { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088,
+ 0x00000000 },
+ { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c,
+ 0x00000000 },
+ { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100,
+ 0x00000000 },
+ { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104,
+ 0x00000000 },
+ { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108,
+ 0x00000000 },
+ { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c,
+ 0x00000000 },
+ { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110,
+ 0x00000000 },
+ { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114,
+ 0x00000000 },
+ { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180,
+ 0x00000000 },
+ { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184,
+ 0x00000000 },
+ { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188,
+ 0x00000000 },
+ { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c,
+ 0x00000000 },
+ { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190,
+ 0x00000000 },
+ { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194,
+ 0x00000000 },
+ { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0,
+ 0x00000000 },
+ { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c,
+ 0x00000000 },
+ { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8,
+ 0x00000000 },
+ { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284,
+ 0x00000000 },
+ { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288,
+ 0x00000000 },
+ { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220,
+ 0x00000000 },
+ { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290,
+ 0x00000000 },
+ { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300,
+ 0x00000000 },
+ { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304,
+ 0x00000000 },
+ { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308,
+ 0x00000000 },
+ { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c,
+ 0x00000000 },
+ { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380,
+ 0x00000000 },
+ { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384,
+ 0x00000000 },
+ { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700,
+ 0x00000000 },
+ { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704,
+ 0x00000000 },
+ { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708,
+ 0x00000000 },
+ { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c,
+ 0x00000000 },
+ { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780,
+ 0x00000000 },
+ { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784,
+ 0x00000000 },
+ { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04,
+ 0x00000000 },
+ { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08,
+ 0x00000000 },
+ { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08,
+ 0x00000000 },
+ { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c,
+ 0x00000000 },
+ { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80,
+ 0x00000000 },
+ { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84,
+ 0x00000000 },
+ { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88,
+ 0x00000000 },
+ { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c,
+ 0x00000000 },
+ { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90,
+ 0x00000000 },
+ { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80,
+ 0x00000000 },
+ { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84,
+ 0x00000000 },
+ { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88,
+ 0x00000000 },
+ { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c,
+ 0x00000000 },
+ { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90,
+ 0x00000000 },
+ { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c,
+ 0x00000000 },
+ { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310,
+ 0x00000000 },
+ { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384,
+ 0x00000000 },
+ { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388,
+ 0x00000000 },
+ { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324,
+ 0x00000000 },
+ { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704,
+ 0x00000000 },
+ { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4,
+ 0x00000000 },
+ { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8,
+ 0x00000000 },
+ { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710,
+ 0x00000000 },
+ { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714,
+ 0x00000000 },
+ { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720,
+ 0x00000000 },
+ { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724,
+ 0x00000000 },
+ { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728,
+ 0x00000000 },
+ { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c,
+ 0x00000000 },
+ { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0,
+ 0x00000000 },
+ { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4,
+ 0x00000000 },
+ { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8,
+ 0x00000000 },
+ { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0,
+ 0x00000000 },
+ { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4,
+ 0x00000000 },
+ { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8,
+ 0x00000000 },
+ { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5,
+ 0x00000000 },
+ { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9,
+ 0x00000000 },
+ { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad,
+ 0x00000000 },
+ { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1,
+ 0x00000000 },
+ { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5,
+ 0x00000000 },
+ { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9,
+ 0x00000000 },
+ { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5,
+ 0x00000000 },
+ { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9,
+ 0x00000000 },
+ { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1,
+ 0x00000000 },
+ { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5,
+ 0x00000000 },
+ { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9,
+ 0x00000000 },
+ { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6,
+ 0x00000000 },
+ { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca,
+ 0x00000000 },
+ { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce,
+ 0x00000000 },
+ { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2,
+ 0x00000000 },
+ { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6,
+ 0x00000000 },
+ { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3,
+ 0x00000000 },
+ { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7,
+ 0x00000000 },
+ { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb,
+ 0x00000000 },
+ { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf,
+ 0x00000000 },
+ { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7,
+ 0x00000000 },
+ { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c,
+ 0x00000000 },
+ { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080,
+ 0x00000000 },
+ { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084,
+ 0x00000000 },
+ { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088,
+ 0x00000000 },
+ { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c,
+ 0x00000000 },
+ { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100,
+ 0x00000000 },
+ { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104,
+ 0x00000000 },
+ { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108,
+ 0x00000000 },
+ { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c,
+ 0x00000000 },
+ { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110,
+ 0x00000000 },
+ { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110,
+ 0x00000000 },
+ { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180,
+ 0x00000000 },
+ { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184,
+ 0x00000000 },
+ { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188,
+ 0x00000000 },
+ { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c,
+ 0x00000000 },
+ { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190,
+ 0x00000000 },
+ { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194,
+ 0x00000000 },
+ { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0,
+ 0x00000000 },
+ { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c,
+ 0x00000000 },
+ { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8,
+ 0x00000000 },
+ { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac,
+ 0x00000000 },
+ { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c,
+ 0x00000000 },
+ { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224,
+ 0x00000000 },
+ { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290,
+ 0x00000000 },
+ { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300,
+ 0x00000000 },
+ { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308,
+ 0x00000000 },
+ { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c,
+ 0x00000000 },
+ { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310,
+ 0x00000000 },
+ { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788,
+ 0x00000000 },
+ { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c,
+ 0x00000000 },
+ { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790,
+ 0x00000000 },
+ { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794,
+ 0x00000000 },
+ { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798,
+ 0x00000000 },
+ { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c,
+ 0x00000000 },
+ { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89,
+ 0x00000000 },
+ { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d,
+ 0x00000000 },
+ { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91,
+ 0x00000000 },
+ { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95,
+ 0x00000000 },
+ { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99,
+ 0x00000000 },
+ { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5,
+ 0x00000000 },
+ { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9,
+ 0x00000000 },
+ { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad,
+ 0x00000000 },
+ { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c,
+ 0x00000000 },
+ { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10,
+ 0x00000000 },
+ { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14,
+ 0x00000000 },
+ { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84,
+ 0x00000000 },
+ { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84,
+ 0x00000000 },
+ { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88,
+ 0x00000000 },
+ { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380,
+ 0x00000000 },
+ { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384,
+ 0x00000000 },
+ { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388,
+ 0x00000000 },
+ { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c,
+ 0x00000000 },
+ { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394,
+ 0x00000000 },
+ { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798,
+ 0x00000000 },
+ { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c,
+ 0x00000000 },
+ { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710,
+ 0x00000000 },
+ { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714,
+ 0x00000000 },
+ { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718,
+ 0x00000000 },
+ { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705,
+ 0x00000000 },
+ { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709,
+ 0x00000000 },
+ { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d,
+ 0x00000000 },
+ { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711,
+ 0x00000000 },
+ { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715,
+ 0x00000000 },
+ { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719,
+ 0x00000000 },
+ { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4,
+ 0x00000000 },
+ { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8,
+ 0x00000000 },
+ { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac,
+ 0x00000000 },
+ { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac,
+ 0x00000000 },
+ { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0,
+ 0x00000000 },
+ { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8,
+ 0x00000000 },
+ { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc,
+ 0x00000000 },
+ { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1,
+ 0x00000000 },
+ { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5,
+ 0x00000000 },
+ { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9,
+ 0x00000000 },
+ { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1,
+ 0x00000000 },
+ { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5,
+ 0x00000000 },
+ { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd,
+ 0x00000000 },
+ { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9,
+ 0x00000000 },
+ { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd,
+ 0x00000000 },
+ { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1,
+ 0x00000000 },
+ { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9,
+ 0x00000000 },
+ { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2,
+ 0x00000000 },
+ { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6,
+ 0x00000000 },
+ { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca,
+ 0x00000000 },
+ { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce,
+ 0x00000000 },
+ { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2,
+ 0x00000000 },
+ { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6,
+ 0x00000000 },
+ { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3,
+ 0x00000000 },
+ { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb,
+ 0x00000000 },
+ { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004,
+ 0x00000004 },
+ { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000,
+ 0x0001f000 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a,
+ 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108,
+ 0x00000000 },
+ { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000,
+ 0x001da000 },
+ { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652,
+ 0x0a82a652 },
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201,
+ 0x00000000 },
+ { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408,
+ 0x00000000 },
+ { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a,
+ 0x00000000 },
+ { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818,
+ 0x00000000 },
+ { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858,
+ 0x00000000 },
+ { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859,
+ 0x00000000 },
+ { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b,
+ 0x00000000 },
+ { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a,
+ 0x00000000 },
+ { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b,
+ 0x00000000 },
+ { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c,
+ 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d,
+ 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e,
+ 0x00000000 },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de,
+ 0x00000000 },
+ { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e,
+ 0x00000000 },
+ { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e,
+ 0x00000000 },
+ { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df,
+ 0x00000000 },
+ { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df,
+ 0x00000000 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e,
+ 0x7999aa0e },
+};
+
+static const uint32_t ar9285Common_9285[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020045 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00007010, 0x00000031 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x00000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0x00000000 },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000001 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00000000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x00010380 },
+ { 0x00008344, 0x00581043 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafe68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x01002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009940, 0x14750604 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x2108ecff },
+ { 0x00009968, 0x000003ce },
+ { 0x00009970, 0x1927b515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x2def0a00 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x0000a208, 0x803e6788 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x00206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x00000000 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a244, 0x00000000 },
+ { 0x0000a248, 0xfffffffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0ccb5380 },
+ { 0x0000a25c, 0x15151501 },
+ { 0x0000a260, 0xdfa90f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9e6 },
+ { 0x0000d270, 0x0d820820 },
+ { 0x0000a278, 0x39ce739c },
+ { 0x0000a27c, 0x050e039c },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x39ce739c },
+ { 0x0000a398, 0x0000039c },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x39ce739c },
+ { 0x0000a3e0, 0x0000039c },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x00007800, 0x00140000 },
+ { 0x00007804, 0x0e4548d8 },
+ { 0x00007808, 0x54214514 },
+ { 0x0000780c, 0x02025820 },
+ { 0x00007810, 0x71c0d388 },
+ { 0x00007814, 0x924934a8 },
+ { 0x0000781c, 0x00000000 },
+ { 0x00007820, 0x00000c04 },
+ { 0x00007824, 0x00d86fff },
+ { 0x00007828, 0x26d2491b },
+ { 0x0000782c, 0x6e36d97b },
+ { 0x00007830, 0xedb6d96c },
+ { 0x00007834, 0x71400086 },
+ { 0x00007838, 0xfac68800 },
+ { 0x0000783c, 0x0001fffe },
+ { 0x00007840, 0xffeb1a20 },
+ { 0x00007844, 0x000c0db6 },
+ { 0x00007848, 0x6db61b6f },
+ { 0x0000784c, 0x6d9b66db },
+ { 0x00007850, 0x6d8c6dba },
+ { 0x00007854, 0x00040000 },
+ { 0x00007858, 0xdb003012 },
+ { 0x0000785c, 0x04924914 },
+ { 0x00007860, 0x21084210 },
+ { 0x00007864, 0xf7d7ffde },
+ { 0x00007868, 0xc2034080 },
+ { 0x0000786c, 0x48609eb4 },
+ { 0x00007870, 0x10142c00 },
+};
+
+static const uint32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+static const uint32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+static const uint32_t ar9285Modes_9285_1_2[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160,
+ 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c,
+ 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38,
+ 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00,
+ 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b,
+ 0x0988004f },
+ { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440,
+ 0x00006880 },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300,
+ 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200,
+ 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001,
+ 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e,
+ 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007 },
+ { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e,
+ 0x206a012e },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020,
+ 0x037216a0 },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00000057, 0x00000057,
+ 0x00001059 },
+ { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2,
+ 0x6d4000e2 },
+ { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e,
+ 0x7ec84d2e },
+ { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e,
+ 0x3139605e },
+ { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20,
+ 0x00058d18 },
+ { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00,
+ 0x0001ce00 },
+ { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0,
+ 0x5ac640d0 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881,
+ 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898,
+ 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b,
+ 0x00000016 },
+ { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d,
+ 0xd00a800d },
+ { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020,
+ 0xffbc1010 },
+ { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c,
+ 0x0000421c },
+ { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00,
+ 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4,
+ 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77,
+ 0x06336f77 },
+ { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329,
+ 0x60f65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8,
+ 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384,
+ 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084,
+ 0x00000000 },
+ { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088,
+ 0x00000000 },
+ { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c,
+ 0x00000000 },
+ { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100,
+ 0x00000000 },
+ { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104,
+ 0x00000000 },
+ { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108,
+ 0x00000000 },
+ { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c,
+ 0x00000000 },
+ { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110,
+ 0x00000000 },
+ { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114,
+ 0x00000000 },
+ { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180,
+ 0x00000000 },
+ { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184,
+ 0x00000000 },
+ { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188,
+ 0x00000000 },
+ { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c,
+ 0x00000000 },
+ { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190,
+ 0x00000000 },
+ { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194,
+ 0x00000000 },
+ { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0,
+ 0x00000000 },
+ { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c,
+ 0x00000000 },
+ { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8,
+ 0x00000000 },
+ { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284,
+ 0x00000000 },
+ { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288,
+ 0x00000000 },
+ { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220,
+ 0x00000000 },
+ { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290,
+ 0x00000000 },
+ { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300,
+ 0x00000000 },
+ { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304,
+ 0x00000000 },
+ { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308,
+ 0x00000000 },
+ { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c,
+ 0x00000000 },
+ { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380,
+ 0x00000000 },
+ { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384,
+ 0x00000000 },
+ { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700,
+ 0x00000000 },
+ { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704,
+ 0x00000000 },
+ { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708,
+ 0x00000000 },
+ { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c,
+ 0x00000000 },
+ { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780,
+ 0x00000000 },
+ { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784,
+ 0x00000000 },
+ { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04,
+ 0x00000000 },
+ { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08,
+ 0x00000000 },
+ { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08,
+ 0x00000000 },
+ { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c,
+ 0x00000000 },
+ { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80,
+ 0x00000000 },
+ { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84,
+ 0x00000000 },
+ { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88,
+ 0x00000000 },
+ { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c,
+ 0x00000000 },
+ { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90,
+ 0x00000000 },
+ { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80,
+ 0x00000000 },
+ { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84,
+ 0x00000000 },
+ { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88,
+ 0x00000000 },
+ { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c,
+ 0x00000000 },
+ { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90,
+ 0x00000000 },
+ { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c,
+ 0x00000000 },
+ { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310,
+ 0x00000000 },
+ { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384,
+ 0x00000000 },
+ { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388,
+ 0x00000000 },
+ { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324,
+ 0x00000000 },
+ { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704,
+ 0x00000000 },
+ { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4,
+ 0x00000000 },
+ { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8,
+ 0x00000000 },
+ { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710,
+ 0x00000000 },
+ { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714,
+ 0x00000000 },
+ { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720,
+ 0x00000000 },
+ { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724,
+ 0x00000000 },
+ { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728,
+ 0x00000000 },
+ { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c,
+ 0x00000000 },
+ { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0,
+ 0x00000000 },
+ { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4,
+ 0x00000000 },
+ { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8,
+ 0x00000000 },
+ { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0,
+ 0x00000000 },
+ { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4,
+ 0x00000000 },
+ { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8,
+ 0x00000000 },
+ { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5,
+ 0x00000000 },
+ { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9,
+ 0x00000000 },
+ { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad,
+ 0x00000000 },
+ { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1,
+ 0x00000000 },
+ { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5,
+ 0x00000000 },
+ { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9,
+ 0x00000000 },
+ { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5,
+ 0x00000000 },
+ { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9,
+ 0x00000000 },
+ { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1,
+ 0x00000000 },
+ { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5,
+ 0x00000000 },
+ { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9,
+ 0x00000000 },
+ { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6,
+ 0x00000000 },
+ { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca,
+ 0x00000000 },
+ { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce,
+ 0x00000000 },
+ { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2,
+ 0x00000000 },
+ { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6,
+ 0x00000000 },
+ { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3,
+ 0x00000000 },
+ { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7,
+ 0x00000000 },
+ { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb,
+ 0x00000000 },
+ { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf,
+ 0x00000000 },
+ { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7,
+ 0x00000000 },
+ { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db,
+ 0x00000000 },
+ { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c,
+ 0x00000000 },
+ { 0x0000aa04, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c,
+ 0x00000000 },
+ { 0x0000aa08, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c,
+ 0x00000000 },
+ { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068080, 0x00068080,
+ 0x00000000 },
+ { 0x0000aa10, 0x00000000, 0x00000000, 0x00068084, 0x00068084,
+ 0x00000000 },
+ { 0x0000aa14, 0x00000000, 0x00000000, 0x00068088, 0x00068088,
+ 0x00000000 },
+ { 0x0000aa18, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c,
+ 0x00000000 },
+ { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068100, 0x00068100,
+ 0x00000000 },
+ { 0x0000aa20, 0x00000000, 0x00000000, 0x00068104, 0x00068104,
+ 0x00000000 },
+ { 0x0000aa24, 0x00000000, 0x00000000, 0x00068108, 0x00068108,
+ 0x00000000 },
+ { 0x0000aa28, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c,
+ 0x00000000 },
+ { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068110, 0x00068110,
+ 0x00000000 },
+ { 0x0000aa30, 0x00000000, 0x00000000, 0x00068110, 0x00068110,
+ 0x00000000 },
+ { 0x0000aa34, 0x00000000, 0x00000000, 0x00068180, 0x00068180,
+ 0x00000000 },
+ { 0x0000aa38, 0x00000000, 0x00000000, 0x00068184, 0x00068184,
+ 0x00000000 },
+ { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068188, 0x00068188,
+ 0x00000000 },
+ { 0x0000aa40, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c,
+ 0x00000000 },
+ { 0x0000aa44, 0x00000000, 0x00000000, 0x00068190, 0x00068190,
+ 0x00000000 },
+ { 0x0000aa48, 0x00000000, 0x00000000, 0x00068194, 0x00068194,
+ 0x00000000 },
+ { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0,
+ 0x00000000 },
+ { 0x0000aa50, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c,
+ 0x00000000 },
+ { 0x0000aa54, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8,
+ 0x00000000 },
+ { 0x0000aa58, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac,
+ 0x00000000 },
+ { 0x0000aa5c, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c,
+ 0x00000000 },
+ { 0x0000aa60, 0x00000000, 0x00000000, 0x00068224, 0x00068224,
+ 0x00000000 },
+ { 0x0000aa64, 0x00000000, 0x00000000, 0x00068290, 0x00068290,
+ 0x00000000 },
+ { 0x0000aa68, 0x00000000, 0x00000000, 0x00068300, 0x00068300,
+ 0x00000000 },
+ { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068308, 0x00068308,
+ 0x00000000 },
+ { 0x0000aa70, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c,
+ 0x00000000 },
+ { 0x0000aa74, 0x00000000, 0x00000000, 0x00068310, 0x00068310,
+ 0x00000000 },
+ { 0x0000aa78, 0x00000000, 0x00000000, 0x00068788, 0x00068788,
+ 0x00000000 },
+ { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c,
+ 0x00000000 },
+ { 0x0000aa80, 0x00000000, 0x00000000, 0x00068790, 0x00068790,
+ 0x00000000 },
+ { 0x0000aa84, 0x00000000, 0x00000000, 0x00068794, 0x00068794,
+ 0x00000000 },
+ { 0x0000aa88, 0x00000000, 0x00000000, 0x00068798, 0x00068798,
+ 0x00000000 },
+ { 0x0000aa8c, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c,
+ 0x00000000 },
+ { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89,
+ 0x00000000 },
+ { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d,
+ 0x00000000 },
+ { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91,
+ 0x00000000 },
+ { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95,
+ 0x00000000 },
+ { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99,
+ 0x00000000 },
+ { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5,
+ 0x00000000 },
+ { 0x0000aaa8, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9,
+ 0x00000000 },
+ { 0x0000aaac, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad,
+ 0x00000000 },
+ { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c,
+ 0x00000000 },
+ { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10,
+ 0x00000000 },
+ { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14,
+ 0x00000000 },
+ { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84,
+ 0x00000000 },
+ { 0x0000aac0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84,
+ 0x00000000 },
+ { 0x0000aac4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88,
+ 0x00000000 },
+ { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380,
+ 0x00000000 },
+ { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384,
+ 0x00000000 },
+ { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388,
+ 0x00000000 },
+ { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c,
+ 0x00000000 },
+ { 0x0000aad8, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394,
+ 0x00000000 },
+ { 0x0000aadc, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798,
+ 0x00000000 },
+ { 0x0000aae0, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c,
+ 0x00000000 },
+ { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710,
+ 0x00000000 },
+ { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714,
+ 0x00000000 },
+ { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718,
+ 0x00000000 },
+ { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705,
+ 0x00000000 },
+ { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709,
+ 0x00000000 },
+ { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d,
+ 0x00000000 },
+ { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711,
+ 0x00000000 },
+ { 0x0000ab00, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715,
+ 0x00000000 },
+ { 0x0000ab04, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719,
+ 0x00000000 },
+ { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4,
+ 0x00000000 },
+ { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8,
+ 0x00000000 },
+ { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac,
+ 0x00000000 },
+ { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac,
+ 0x00000000 },
+ { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0,
+ 0x00000000 },
+ { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8,
+ 0x00000000 },
+ { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc,
+ 0x00000000 },
+ { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1,
+ 0x00000000 },
+ { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5,
+ 0x00000000 },
+ { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9,
+ 0x00000000 },
+ { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1,
+ 0x00000000 },
+ { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5,
+ 0x00000000 },
+ { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd,
+ 0x00000000 },
+ { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9,
+ 0x00000000 },
+ { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd,
+ 0x00000000 },
+ { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1,
+ 0x00000000 },
+ { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9,
+ 0x00000000 },
+ { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2,
+ 0x00000000 },
+ { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6,
+ 0x00000000 },
+ { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca,
+ 0x00000000 },
+ { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce,
+ 0x00000000 },
+ { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2,
+ 0x00000000 },
+ { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6,
+ 0x00000000 },
+ { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3,
+ 0x00000000 },
+ { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb,
+ 0x00000000 },
+ { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3,
+ 0x00000000 },
+ { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004,
+ 0x00000004 },
+ { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000,
+ 0x0001f000 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a,
+ 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108,
+ 0x00000000 },
+ { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000,
+ 0x0004a000 },
+ { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652,
+ 0x0a82a652 },
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 },
+ { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201,
+ 0x00000000 },
+ { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408,
+ 0x00000000 },
+ { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a,
+ 0x00000000 },
+ { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818,
+ 0x00000000 },
+ { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858,
+ 0x00000000 },
+ { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859,
+ 0x00000000 },
+ { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b,
+ 0x00000000 },
+ { 0x0000a320, 0x00000000, 0x00000000, 0x0002b89a, 0x0002b89a,
+ 0x00000000 },
+ { 0x0000a324, 0x00000000, 0x00000000, 0x0002d89b, 0x0002d89b,
+ 0x00000000 },
+ { 0x0000a328, 0x00000000, 0x00000000, 0x0002f89c, 0x0002f89c,
+ 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x0003189d, 0x0003189d,
+ 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x0003389e, 0x0003389e,
+ 0x00000000 },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x000368de, 0x000368de,
+ 0x00000000 },
+ { 0x0000a338, 0x00000000, 0x00000000, 0x0003891e, 0x0003891e,
+ 0x00000000 },
+ { 0x0000a33c, 0x00000000, 0x00000000, 0x0003a95e, 0x0003a95e,
+ 0x00000000 },
+ { 0x0000a340, 0x00000000, 0x00000000, 0x0003e9df, 0x0003e9df,
+ 0x00000000 },
+ { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df,
+ 0x00000000 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e,
+ 0x7999aa0e },
+};
+
+static const uint32_t ar9285Common_9285_1_2[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020045 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00007010, 0x00000031 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x00000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000001 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x00010380 },
+ { 0x00008344, 0x00581043 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafe68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x01002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009940, 0x14750604 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x2108ecff },
+ { 0x00009968, 0x000003ce },
+ { 0x00009970, 0x192bb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x2def1000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x0000a208, 0x803e6788 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x00206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x00000000 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a244, 0x00000000 },
+ { 0x0000a248, 0xfffffffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0ccb5380 },
+ { 0x0000a25c, 0x15151501 },
+ { 0x0000a260, 0xdfa90f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9e6 },
+ { 0x0000d270, 0x0d820820 },
+ { 0x0000a278, 0x318c6318 },
+ { 0x0000a27c, 0x050c0318 },
+ { 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, 0x318c6318 },
+ { 0x0000a398, 0x00000318 },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x318c6318 },
+ { 0x0000a3e0, 0x00000318 },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x00007800, 0x00140000 },
+ { 0x00007804, 0x0e4548d8 },
+ { 0x00007808, 0x54214514 },
+ { 0x0000780c, 0x02025820 },
+ { 0x00007810, 0x71c0d388 },
+ { 0x00007814, 0x924934a8 },
+ { 0x0000781c, 0x00000000 },
+ { 0x00007820, 0x00000c04 },
+ { 0x00007824, 0x00d86fff },
+ { 0x00007828, 0x26d2491b },
+ { 0x0000782c, 0x6e36d97b },
+ { 0x00007830, 0xedb6d96e },
+ { 0x00007834, 0x71400087 },
+ { 0x00007838, 0xfac68801 },
+ { 0x0000783c, 0x0001fffe },
+ { 0x00007840, 0xffeb1a20 },
+ { 0x00007844, 0x000c0db6 },
+ { 0x00007848, 0x6db61b6f },
+ { 0x0000784c, 0x6d9b66db },
+ { 0x00007850, 0x6d8c6dba },
+ { 0x00007854, 0x00040000 },
+ { 0x00007858, 0xdb003012 },
+ { 0x0000785c, 0x04924914 },
+ { 0x00007860, 0x21084210 },
+ { 0x00007864, 0xf7d7ffde },
+ { 0x00007868, 0xc2034080 },
+ { 0x0000786c, 0x48609eb4 },
+ { 0x00007870, 0x10142c00 },
+};
+
+static const uint32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+static const uint32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARN_INITVALS_H */
diff --git a/usr/src/uts/common/io/arn/arn_mac.c b/usr/src/uts/common/io/arn/arn_mac.c
new file mode 100644
index 0000000000..757791a392
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_mac.c
@@ -0,0 +1,1107 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include <sys/ddi.h>
+
+#include "arn_core.h"
+#include "arn_hw.h"
+#include "arn_reg.h"
+#include "arn_phy.h"
+
+/* ARGSUSED */
+static void
+ath9k_hw_set_txq_interrupts(struct ath_hal *ah,
+ struct ath9k_tx_queue_info *qi)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ ARN_DBG((ARN_DBG_INTERRUPT,
+ "%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));
+
+ REG_WRITE(ah, AR_IMR_S0,
+ SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) |
+ SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC));
+ REG_WRITE(ah, AR_IMR_S1,
+ SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)|
+ SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL));
+ REG_RMW_FIELD(ah, AR_IMR_S2,
+ AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
+}
+
+void
+ath9k_hw_dmaRegDump(struct ath_hal *ah)
+{
+ uint32_t val[ATH9K_NUM_DMA_DEBUG_REGS];
+ int qcuOffset = 0, dcuOffset = 0;
+ uint32_t *qcuBase = &val[0], *dcuBase = &val[4];
+ int i;
+
+ REG_WRITE(ah, AR_MACMISC,
+ ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+ (AR_MACMISC_MISC_OBS_BUS_1 <<
+ AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+ ARN_DBG((ARN_DBG_REG_IO, "Raw DMA Debug values:\n"));
+
+ for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
+ if (i % 4 == 0)
+ ARN_DBG((ARN_DBG_REG_IO, "\n"));
+
+ val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof (uint32_t)));
+ ARN_DBG((ARN_DBG_REG_IO, "%d: %08x ", i, val[i]));
+ }
+
+ ARN_DBG((ARN_DBG_REG_IO, "\n\n"));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"));
+
+ for (i = 0; i < ATH9K_NUM_QUEUES;
+ i++, qcuOffset += 4, dcuOffset += 5) {
+ if (i == 8) {
+ qcuOffset = 0;
+ qcuBase++;
+ }
+
+ if (i == 6) {
+ dcuOffset = 0;
+ dcuBase++;
+ }
+
+ ARN_DBG((ARN_DBG_REG_IO,
+ "%2d %2x %1x %2x %2x\n",
+ i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+ (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
+ val[2] & (0x7 << (i * 3)) >> (i * 3),
+ (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset));
+ }
+
+ ARN_DBG((ARN_DBG_REG_IO, "\n"));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "qcu_stitch state: %2x qcu_fetch state: %2x\n",
+ (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "qcu_complete state: %2x dcu_complete state: %2x\n",
+ (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "dcu_arb state: %2x dcu_fp state: %2x\n",
+ (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
+ (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
+ (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
+ (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17));
+
+ ARN_DBG((ARN_DBG_REG_IO, "pcu observe 0x%x \n",
+ REG_READ(ah, AR_OBS_BUS_1)));
+ ARN_DBG((ARN_DBG_REG_IO,
+ "AR_CR 0x%x \n", REG_READ(ah, AR_CR)));
+}
+
+uint32_t
+ath9k_hw_gettxbuf(struct ath_hal *ah, uint32_t q)
+{
+ return (REG_READ(ah, AR_QTXDP(q)));
+}
+
+boolean_t
+ath9k_hw_puttxbuf(struct ath_hal *ah, uint32_t q, uint32_t txdp)
+{
+ REG_WRITE(ah, AR_QTXDP(q), txdp);
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_txstart(struct ath_hal *ah, uint32_t q)
+{
+ ARN_DBG((ARN_DBG_XMIT, "arn: ath9k_hw_txstart(): "
+ "tramist queue is %u\n", q));
+
+ REG_WRITE(ah, AR_Q_TXE, 1 << q);
+
+ return (B_TRUE);
+}
+
+uint32_t
+ath9k_hw_numtxpending(struct ath_hal *ah, uint32_t q)
+{
+ uint32_t npend;
+
+ npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
+ if (npend == 0) {
+
+ if (REG_READ(ah, AR_Q_TXE) & (1 << q))
+ npend = 1;
+ }
+
+ return (npend);
+}
+
+boolean_t
+ath9k_hw_updatetxtriglevel(struct ath_hal *ah, boolean_t bIncTrigLevel)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t txcfg, curLevel, newLevel;
+ enum ath9k_int omask;
+
+ if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD)
+ return (B_FALSE);
+
+ omask = ath9k_hw_set_interrupts(ah,
+ ahp->ah_maskReg & ~ATH9K_INT_GLOBAL);
+
+ txcfg = REG_READ(ah, AR_TXCFG);
+ curLevel = MS(txcfg, AR_FTRIG);
+ newLevel = curLevel;
+ if (bIncTrigLevel) {
+ if (curLevel < MAX_TX_FIFO_THRESHOLD)
+ newLevel++;
+ } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
+ newLevel--;
+ if (newLevel != curLevel)
+ REG_WRITE(ah, AR_TXCFG,
+ (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
+
+ (void) ath9k_hw_set_interrupts(ah, omask);
+
+ ah->ah_txTrigLevel = (uint16_t)newLevel; /* ??? */
+
+ return (newLevel != curLevel);
+}
+
+boolean_t
+ath9k_hw_stoptxdma(struct ath_hal *ah, uint32_t q)
+{
+ uint32_t tsfLow, j, wait;
+
+ REG_WRITE(ah, AR_Q_TXD, 1 << q);
+
+ for (wait = 1000; wait != 0; wait--) {
+ if (ath9k_hw_numtxpending(ah, q) == 0)
+ break;
+ drv_usecwait(100);
+ }
+
+ if (ath9k_hw_numtxpending(ah, q)) {
+ ARN_DBG((ARN_DBG_QUEUE,
+ "%s: Num of pending TX Frames %d on Q %d\n",
+ __func__, ath9k_hw_numtxpending(ah, q), q));
+
+ for (j = 0; j < 2; j++) {
+ tsfLow = REG_READ(ah, AR_TSF_L32);
+ REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR));
+ REG_WRITE(ah, AR_QUIET_PERIOD, 100);
+ REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
+ REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+
+ if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
+ break;
+ ARN_DBG((ARN_DBG_QUEUE,
+ "%s: TSF have moved while trying to set "
+ "quiet time TSF: 0x%08x\n",
+ __func__, tsfLow));
+ }
+
+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+
+ drv_usecwait(200);
+ REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+
+ wait = 1000;
+
+ while (ath9k_hw_numtxpending(ah, q)) {
+ if ((--wait) == 0) {
+ ARN_DBG((ARN_DBG_XMIT,
+ "%s: Failed to stop Tx DMA in 100 "
+ "msec after killing last frame\n",
+ __func__));
+ break;
+ }
+ drv_usecwait(100);
+ }
+
+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+ }
+
+ REG_WRITE(ah, AR_Q_TXD, 0);
+
+ return (wait != 0);
+}
+
+/* ARGSUSED */
+boolean_t
+ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t segLen, boolean_t firstSeg,
+ boolean_t lastSeg, const struct ath_desc *ds0)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ if (firstSeg) {
+ ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
+ } else if (lastSeg) {
+ ads->ds_ctl0 = 0;
+ ads->ds_ctl1 = segLen;
+ ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+ ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+ } else {
+ ads->ds_ctl0 = 0;
+ ads->ds_ctl1 = segLen | AR_TxMore;
+ ads->ds_ctl2 = 0;
+ ads->ds_ctl3 = 0;
+ }
+ ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+ ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+ ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+ ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+ ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+
+ return (B_TRUE);
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+ ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+ ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+ ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+ ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+}
+
+int
+ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ if ((ads->ds_txstatus9 & AR_TxDone) == 0)
+ return (EINPROGRESS);
+
+ ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
+ ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
+ ds->ds_txstat.ts_status = 0;
+ ds->ds_txstat.ts_flags = 0;
+
+ if (ads->ds_txstatus1 & AR_ExcessiveRetries) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_XRETRY\n"));
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
+ }
+ if (ads->ds_txstatus1 & AR_Filtered) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: AR_Filtered\n"));
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
+ }
+ if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_FIFO\n"));
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
+ (void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
+ }
+ if (ads->ds_txstatus9 & AR_TxOpExceeded) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_XTXOP\n"));
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
+ }
+ if (ads->ds_txstatus1 & AR_TxTimerExpired) {
+ ARN_DBG((ARN_DBG_INTERRUPT,
+ "arn: ATH9K_TXERR_TIMER_EXPIRED\n"));
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+ }
+
+ if (ads->ds_txstatus1 & AR_DescCfgErr) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TX_DESC_CFG_ERR\n"));
+ ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+ }
+ if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
+ ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+ (void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
+ }
+ if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
+ ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+ (void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
+ }
+ if (ads->ds_txstatus0 & AR_TxBaStatus) {
+ ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
+ ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
+ ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
+ }
+
+ ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
+ switch (ds->ds_txstat.ts_rateindex) {
+ case 0:
+ ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
+ break;
+ case 1:
+ ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
+ break;
+ case 2:
+ ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
+ break;
+ case 3:
+ ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
+ break;
+ }
+
+ ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
+ ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
+ ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
+ ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
+ ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
+ ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
+ ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
+ ds->ds_txstat.evm0 = ads->AR_TxEVM0;
+ ds->ds_txstat.evm1 = ads->AR_TxEVM1;
+ ds->ds_txstat.evm2 = ads->AR_TxEVM2;
+ ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
+ ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
+ ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
+ ds->ds_txstat.ts_antenna = 1;
+
+ return (0);
+}
+
+void
+ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t pktLen, enum ath9k_pkt_type type, uint32_t txPower,
+ uint32_t keyIx, enum ath9k_key_type keyType, uint32_t flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ txPower += ahp->ah_txPowerIndexOffset;
+ if (txPower > 63)
+ txPower = 63;
+
+ ads->ds_ctl0 = (pktLen & AR_FrameLen) |
+ (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
+ SM(txPower, AR_XmitPower) |
+ (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
+ (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) |
+ (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) |
+ (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
+
+ ads->ds_ctl1 =
+ (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) |
+ SM(type, AR_FrameType) |
+ (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) |
+ (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) |
+ (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+ ads->ds_ctl6 = SM(keyType, AR_EncrType);
+
+ if (AR_SREV_9285(ah)) {
+ ads->ds_ctl8 = 0;
+ ads->ds_ctl9 = 0;
+ ads->ds_ctl10 = 0;
+ ads->ds_ctl11 = 0;
+ }
+
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
+ struct ath_desc *lastds,
+ uint32_t durUpdateEn, uint32_t rtsctsRate,
+ uint32_t rtsctsDuration,
+ struct ath9k_11n_rate_series series[],
+ uint32_t nseries, uint32_t flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ar5416_desc *last_ads = AR5416DESC(lastds);
+ uint32_t ds_ctl0;
+
+ (void) nseries;
+ (void) rtsctsDuration;
+
+ if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
+ ds_ctl0 = ads->ds_ctl0;
+
+ if (flags & ATH9K_TXDESC_RTSENA) {
+ ds_ctl0 &= ~AR_CTSEnable;
+ ds_ctl0 |= AR_RTSEnable;
+ } else {
+ ds_ctl0 &= ~AR_RTSEnable;
+ ds_ctl0 |= AR_CTSEnable;
+ }
+
+ ads->ds_ctl0 = ds_ctl0;
+ } else {
+ ads->ds_ctl0 =
+ (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
+ }
+
+ ads->ds_ctl2 = set11nTries(series, 0) |
+ set11nTries(series, 1) |
+ set11nTries(series, 2) |
+ set11nTries(series, 3) |
+ (durUpdateEn ? AR_DurUpdateEna : 0) |
+ SM(0, AR_BurstDur);
+
+ ads->ds_ctl3 = set11nRate(series, 0) |
+ set11nRate(series, 1) |
+ set11nRate(series, 2) |
+ set11nRate(series, 3);
+
+ ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) |
+ set11nPktDurRTSCTS(series, 1);
+
+ ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) |
+ set11nPktDurRTSCTS(series, 3);
+
+ ads->ds_ctl7 = set11nRateFlags(series, 0) |
+ set11nRateFlags(series, 1) |
+ set11nRateFlags(series, 2) |
+ set11nRateFlags(series, 3) |
+ SM(rtsctsRate, AR_RTSCTSRate);
+ last_ads->ds_ctl2 = ads->ds_ctl2;
+ last_ads->ds_ctl3 = ads->ds_ctl3;
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t aggrLen)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+ ads->ds_ctl6 &= ~AR_AggrLen;
+ ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t numDelims)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ unsigned int ctl6;
+
+ ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+
+ ctl6 = ads->ds_ctl6;
+ ctl6 &= ~AR_PadDelim;
+ ctl6 |= SM(numDelims, AR_PadDelim);
+ ads->ds_ctl6 = ctl6;
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 |= AR_IsAggr;
+ ads->ds_ctl1 &= ~AR_MoreAggr;
+ ads->ds_ctl6 &= ~AR_PadDelim;
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t burstDuration)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl2 &= ~AR_BurstDur;
+ ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t vmf)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ if (vmf)
+ ads->ds_ctl0 |= AR_VirtMoreFrag;
+ else
+ ads->ds_ctl0 &= ~AR_VirtMoreFrag;
+}
+
+void
+ath9k_hw_gettxintrtxqs(struct ath_hal *ah, uint32_t *txqs)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ *txqs &= ahp->ah_intrTxqs;
+ ahp->ah_intrTxqs &= ~(*txqs);
+}
+
+boolean_t
+ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
+ const struct ath9k_tx_queue_info *qinfo)
+{
+ uint32_t cw;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ struct ath9k_tx_queue_info *qi;
+
+ if (q >= pCap->total_queues) {
+ ARN_DBG((ARN_DBG_QUEUE, "%s: invalid queue num %u\n",
+ __func__, q));
+ return (B_FALSE);
+ }
+
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ ARN_DBG((ARN_DBG_QUEUE, "%s: inactive queue\n",
+ __func__));
+ return (B_FALSE);
+ }
+
+ ARN_DBG((ARN_DBG_QUEUE, "%s: queue %p\n", __func__, qi));
+
+ qi->tqi_ver = qinfo->tqi_ver;
+ qi->tqi_subtype = qinfo->tqi_subtype;
+ qi->tqi_qflags = qinfo->tqi_qflags;
+ qi->tqi_priority = qinfo->tqi_priority;
+ if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
+ qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
+ else
+ qi->tqi_aifs = INIT_AIFS;
+ if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
+ cw = min(qinfo->tqi_cwmin, 1024U);
+ qi->tqi_cwmin = 1;
+ while (qi->tqi_cwmin < cw)
+ qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
+ } else
+ qi->tqi_cwmin = qinfo->tqi_cwmin;
+ if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
+ cw = min(qinfo->tqi_cwmax, 1024U);
+ qi->tqi_cwmax = 1;
+ while (qi->tqi_cwmax < cw)
+ qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
+ } else
+ qi->tqi_cwmax = INIT_CWMAX;
+
+ if (qinfo->tqi_shretry != 0)
+ qi->tqi_shretry = min((uint32_t)qinfo->tqi_shretry, 15U);
+ else
+ qi->tqi_shretry = INIT_SH_RETRY;
+ if (qinfo->tqi_lgretry != 0)
+ qi->tqi_lgretry = min((uint32_t)qinfo->tqi_lgretry, 15U);
+ else
+ qi->tqi_lgretry = INIT_LG_RETRY;
+ qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
+ qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
+ qi->tqi_burstTime = qinfo->tqi_burstTime;
+ qi->tqi_readyTime = qinfo->tqi_readyTime;
+
+ switch (qinfo->tqi_subtype) {
+ case ATH9K_WME_UPSD:
+ if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
+ qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
+ break;
+ default:
+ break;
+ }
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
+ struct ath9k_tx_queue_info *qinfo)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ struct ath9k_tx_queue_info *qi;
+
+ if (q >= pCap->total_queues) {
+ ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_get_txq_props(): "
+ "invalid queue num %u\n", q));
+ return (B_FALSE);
+ }
+
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_get_txq_props(): "
+ "inactive queue\n"));
+ return (B_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 (B_TRUE);
+}
+
+int
+ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
+ const struct ath9k_tx_queue_info *qinfo)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_tx_queue_info *qi;
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ int q;
+
+ switch (type) {
+ case ATH9K_TX_QUEUE_BEACON:
+ q = pCap->total_queues - 1;
+ break;
+ case ATH9K_TX_QUEUE_CAB:
+ q = pCap->total_queues - 2;
+ break;
+ case ATH9K_TX_QUEUE_PSPOLL:
+ q = 1;
+ break;
+ case ATH9K_TX_QUEUE_UAPSD:
+ q = pCap->total_queues - 3;
+ break;
+ case ATH9K_TX_QUEUE_DATA:
+ for (q = 0; q < pCap->total_queues; q++)
+ if (ahp->ah_txq[q].tqi_type ==
+ ATH9K_TX_QUEUE_INACTIVE)
+ break;
+ if (q == pCap->total_queues) {
+ ARN_DBG((ARN_DBG_QUEUE,
+ "arn: ath9k_hw_setuptxqueue(): "
+ "no available tx queue\n"));
+ return (-1);
+ }
+ break;
+ default:
+ ARN_DBG((ARN_DBG_QUEUE,
+ "arn: ath9k_hw_setuptxqueue(): "
+ "bad tx queue type %u\n", type));
+
+ return (-1);
+ }
+
+ ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_setuptxqueue(): "
+ "queue %u\n", q));
+
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
+ ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_setuptxqueue(): "
+ "tx queue %u already active\n", q));
+
+ return (-1);
+ }
+ (void) memset(qi, 0, sizeof (struct ath9k_tx_queue_info));
+ qi->tqi_type = type;
+ if (qinfo == NULL) {
+ qi->tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
+ TXQ_FLAG_TXERRINT_ENABLE |
+ TXQ_FLAG_TXDESCINT_ENABLE |
+ TXQ_FLAG_TXURNINT_ENABLE;
+ qi->tqi_aifs = INIT_AIFS;
+ qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+ qi->tqi_cwmax = INIT_CWMAX;
+ qi->tqi_shretry = INIT_SH_RETRY;
+ qi->tqi_lgretry = INIT_LG_RETRY;
+ qi->tqi_physCompBuf = 0;
+ } else {
+ qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+ (void) ath9k_hw_set_txq_props(ah, q, qinfo);
+ }
+
+ return (q);
+}
+
+boolean_t
+ath9k_hw_releasetxqueue(struct ath_hal *ah, uint32_t q)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ struct ath9k_tx_queue_info *qi;
+
+ if (q >= pCap->total_queues) {
+ ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
+ "invalid queue num %u\n", q));
+ return (B_FALSE);
+ }
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
+ "inactive queue %u\n", q));
+ return (B_FALSE);
+ }
+
+ ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
+ "release queue %u\n", q));
+
+
+ qi->tqi_type = ATH9K_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);
+ ath9k_hw_set_txq_interrupts(ah, qi);
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_resettxqueue(struct ath_hal *ah, uint32_t q)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ struct ath9k_channel *chan = ah->ah_curchan;
+ struct ath9k_tx_queue_info *qi;
+ uint32_t cwMin, chanCwMin, value;
+
+ if (q >= pCap->total_queues) {
+ ARN_DBG((ARN_DBG_QUEUE, "%s: invalid queue num %u\n",
+ __func__, q));
+
+ return (B_FALSE);
+ }
+
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ ARN_DBG((ARN_DBG_QUEUE, "%s: inactive queue %u\n",
+ __func__, q));
+
+ return (B_TRUE);
+ }
+
+ ARN_DBG((ARN_DBG_QUEUE,
+ "%s: reset queue %u\n", __func__, q));
+
+ if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
+ if (chan && IS_CHAN_B(chan))
+ chanCwMin = INIT_CWMIN_11B;
+ else
+ chanCwMin = INIT_CWMIN;
+
+ for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) {
+ /* Nothing to do */
+ }
+ } else
+ cwMin = qi->tqi_cwmin;
+
+ REG_WRITE(ah, AR_DLCL_IFS(q),
+ SM(cwMin, AR_D_LCL_IFS_CWMIN) |
+ SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
+ SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+
+ REG_WRITE(ah, AR_DRETRY_LIMIT(q),
+ SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
+ SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
+ SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
+
+ REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
+ REG_WRITE(ah, AR_DMISC(q),
+ AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
+
+ if (qi->tqi_cbrPeriod) {
+ REG_WRITE(ah, AR_QCBRCFG(q),
+ SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
+ SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
+ REG_WRITE(ah, AR_QMISC(q),
+ REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
+ (qi->tqi_cbrOverflowLimit ?
+ AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
+ }
+ if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
+ REG_WRITE(ah, AR_QRDYTIMECFG(q),
+ SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
+ AR_Q_RDYTIMECFG_EN);
+ }
+
+ REG_WRITE(ah, AR_DCHNTIME(q),
+ SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
+ (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
+
+ if (qi->tqi_burstTime &&
+ (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
+ REG_WRITE(ah, AR_QMISC(q),
+ REG_READ(ah, AR_QMISC(q)) |
+ AR_Q_MISC_RDYTIME_EXP_POLICY);
+
+ }
+
+ if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
+ REG_WRITE(ah, AR_DMISC(q),
+ REG_READ(ah, AR_DMISC(q)) |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+ }
+ if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
+ REG_WRITE(ah, AR_DMISC(q),
+ REG_READ(ah, AR_DMISC(q)) |
+ AR_D_MISC_FRAG_BKOFF_EN);
+ }
+ switch (qi->tqi_type) {
+ case ATH9K_TX_QUEUE_BEACON:
+ REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) |
+ AR_Q_MISC_FSP_DBA_GATED |
+ AR_Q_MISC_BEACON_USE |
+ AR_Q_MISC_CBR_INCR_DIS1);
+
+ REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
+ (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+ AR_D_MISC_ARB_LOCKOUT_CNTRL_S) |
+ AR_D_MISC_BEACON_USE |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+ break;
+ case ATH9K_TX_QUEUE_CAB:
+ REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) |
+ AR_Q_MISC_FSP_DBA_GATED |
+ AR_Q_MISC_CBR_INCR_DIS1 |
+ AR_Q_MISC_CBR_INCR_DIS0);
+ value = (qi->tqi_readyTime -
+ (ah->ah_config.sw_beacon_response_time -
+ ah->ah_config.dma_beacon_response_time) -
+ ah->ah_config.additional_swba_backoff) * 1024;
+ REG_WRITE(ah, AR_QRDYTIMECFG(q),
+ value | AR_Q_RDYTIMECFG_EN);
+ REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
+ (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+ AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
+ break;
+ case ATH9K_TX_QUEUE_PSPOLL:
+ REG_WRITE(ah, AR_QMISC(q),
+ REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
+ break;
+ case ATH9K_TX_QUEUE_UAPSD:
+ REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+ break;
+ default:
+ break;
+ }
+
+ if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
+ REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
+ SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+ AR_D_MISC_ARB_LOCKOUT_CNTRL) |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+ }
+
+ if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
+ ahp->ah_txOkInterruptMask |= 1 << q;
+ else
+ ahp->ah_txOkInterruptMask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
+ ahp->ah_txErrInterruptMask |= 1 << q;
+ else
+ ahp->ah_txErrInterruptMask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
+ ahp->ah_txDescInterruptMask |= 1 << q;
+ else
+ ahp->ah_txDescInterruptMask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
+ ahp->ah_txEolInterruptMask |= 1 << q;
+ else
+ ahp->ah_txEolInterruptMask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
+ ahp->ah_txUrnInterruptMask |= 1 << q;
+ else
+ ahp->ah_txUrnInterruptMask &= ~(1 << q);
+ ath9k_hw_set_txq_interrupts(ah, qi);
+
+ return (B_TRUE);
+}
+
+/* ARGSUSED */
+int
+ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t pa,
+ struct ath_desc *nds,
+ uint64_t tsf)
+{
+ struct ar5416_desc ads;
+ struct ar5416_desc *adsp = AR5416DESC(ds);
+ uint32_t phyerr;
+
+ if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
+ return (EINPROGRESS);
+
+ ads.u.rx = adsp->u.rx;
+
+ ds->ds_rxstat.rs_status = 0;
+ ds->ds_rxstat.rs_flags = 0;
+
+ ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
+ ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
+
+ ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+ ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
+ ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
+ ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
+ ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
+ ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
+ ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
+ if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+ ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
+ else
+ ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
+
+ ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
+ ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+
+ ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+ ds->ds_rxstat.rs_moreaggr =
+ (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
+ ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
+ ds->ds_rxstat.rs_flags =
+ (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
+ ds->ds_rxstat.rs_flags |=
+ (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
+
+ if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
+ ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
+ if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
+ ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
+ if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
+ ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+
+ if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+ if (ads.ds_rxstatus8 & AR_CRCErr)
+ ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
+ else if (ads.ds_rxstatus8 & AR_PHYErr) {
+ ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
+ phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
+ ds->ds_rxstat.rs_phyerr = (uint8_t)phyerr; /* LINT */
+ } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+ ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
+ else if (ads.ds_rxstatus8 & AR_MichaelErr)
+ ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
+ }
+
+ return (0);
+}
+
+boolean_t
+ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
+ uint32_t size, uint32_t flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+ ads->ds_ctl1 = size & AR_BufLen;
+ if (flags & ATH9K_RXDESC_INTREQ)
+ ads->ds_ctl1 |= AR_RxIntrReq;
+
+ ads->ds_rxstatus8 &= ~AR_RxDone;
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+ (void) memset(&(ads->u), 0, sizeof (ads->u));
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_setrxabort(struct ath_hal *ah, boolean_t set)
+{
+ uint32_t reg;
+
+ if (set) {
+ REG_SET_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+ if (!ath9k_hw_wait(ah, AR_OBS_BUS_1,
+ AR_OBS_BUS_1_RX_STATE, 0)) {
+ REG_CLR_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+ reg = REG_READ(ah, AR_OBS_BUS_1);
+
+ ARN_DBG((ARN_DBG_FATAL,
+ "%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
+ __func__, reg));
+
+ return (B_FALSE);
+ }
+ } else {
+ REG_CLR_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+ }
+
+ return (B_TRUE);
+}
+
+void
+ath9k_hw_putrxbuf(struct ath_hal *ah, uint32_t rxdp)
+{
+ REG_WRITE(ah, AR_RXDP, rxdp);
+}
+
+void
+ath9k_hw_rxena(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+void
+ath9k_hw_startpcureceive(struct ath_hal *ah)
+{
+ ath9k_enable_mib_counters(ah);
+
+ ath9k_ani_reset(ah);
+
+ REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+}
+
+void
+ath9k_hw_stoppcurecv(struct ath_hal *ah)
+{
+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
+
+ ath9k_hw_disable_mib_counters(ah);
+}
+
+boolean_t
+ath9k_hw_stopdmarecv(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_CR, AR_CR_RXD);
+
+ if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
+ ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_stopdmarecv(): "
+ "dma failed to stop in 10ms\n"
+ "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
+ REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)));
+ return (B_FALSE);
+ } else {
+ return (B_TRUE);
+ }
+}
diff --git a/usr/src/uts/common/io/arn/arn_main.c b/usr/src/uts/common/io/arn/arn_main.c
new file mode 100644
index 0000000000..d81326de0c
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_main.c
@@ -0,0 +1,3190 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/stream.h>
+#include <sys/termio.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <sys/cmn_err.h>
+#include <sys/stropts.h>
+#include <sys/strsubr.h>
+#include <sys/strtty.h>
+#include <sys/kbio.h>
+#include <sys/cred.h>
+#include <sys/stat.h>
+#include <sys/consdev.h>
+#include <sys/kmem.h>
+#include <sys/modctl.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/pci.h>
+#include <sys/errno.h>
+#include <sys/mac_provider.h>
+#include <sys/dlpi.h>
+#include <sys/ethernet.h>
+#include <sys/list.h>
+#include <sys/byteorder.h>
+#include <sys/strsun.h>
+#include <sys/policy.h>
+#include <inet/common.h>
+#include <inet/nd.h>
+#include <inet/mi.h>
+#include <inet/wifi_ioctl.h>
+#include <sys/mac_wifi.h>
+
+#include "arn_ath9k.h"
+#include "arn_core.h"
+#include "arn_reg.h"
+#include "arn_hw.h"
+
+#define ARN_MAX_RSSI 63 /* max rssi */
+
+/*
+ * PIO access attributes for registers
+ */
+static ddi_device_acc_attr_t arn_reg_accattr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_STRUCTURE_LE_ACC,
+ DDI_STRICTORDER_ACC
+};
+
+/*
+ * DMA access attributes for descriptors: NOT to be byte swapped.
+ */
+static ddi_device_acc_attr_t arn_desc_accattr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_STRUCTURE_LE_ACC,
+ DDI_STRICTORDER_ACC
+};
+
+/*
+ * Describes the chip's DMA engine
+ */
+static ddi_dma_attr_t arn_dma_attr = {
+ DMA_ATTR_V0, /* version number */
+ 0, /* low address */
+ 0xffffffffU, /* high address */
+ 0x3ffffU, /* counter register max */
+ 1, /* alignment */
+ 0xFFF, /* burst sizes */
+ 1, /* minimum transfer size */
+ 0x3ffffU, /* max transfer size */
+ 0xffffffffU, /* address register max */
+ 1, /* no scatter-gather */
+ 1, /* granularity of device */
+ 0, /* DMA flags */
+};
+
+static ddi_dma_attr_t arn_desc_dma_attr = {
+ DMA_ATTR_V0, /* version number */
+ 0, /* low address */
+ 0xffffffffU, /* high address */
+ 0xffffffffU, /* counter register max */
+ 0x1000, /* alignment */
+ 0xFFF, /* burst sizes */
+ 1, /* minimum transfer size */
+ 0xffffffffU, /* max transfer size */
+ 0xffffffffU, /* address register max */
+ 1, /* no scatter-gather */
+ 1, /* granularity of device */
+ 0, /* DMA flags */
+};
+
+#define ATH_DEF_CACHE_BYTES 32 /* default cache line size */
+
+static kmutex_t arn_loglock;
+static void *arn_soft_state_p = NULL;
+/* scan interval, ms? */
+static int arn_dwelltime = 200; /* 150 */
+
+static int arn_m_stat(void *, uint_t, uint64_t *);
+static int arn_m_start(void *);
+static void arn_m_stop(void *);
+static int arn_m_promisc(void *, boolean_t);
+static int arn_m_multicst(void *, boolean_t, const uint8_t *);
+static int arn_m_unicst(void *, const uint8_t *);
+static mblk_t *arn_m_tx(void *, mblk_t *);
+static void arn_m_ioctl(void *, queue_t *, mblk_t *);
+static int arn_m_setprop(void *, const char *, mac_prop_id_t,
+ uint_t, const void *);
+static int arn_m_getprop(void *, const char *, mac_prop_id_t,
+ uint_t, uint_t, void *, uint_t *);
+
+/* MAC Callcack Functions */
+static mac_callbacks_t arn_m_callbacks = {
+ MC_IOCTL | MC_SETPROP | MC_GETPROP,
+ arn_m_stat,
+ arn_m_start,
+ arn_m_stop,
+ arn_m_promisc,
+ arn_m_multicst,
+ arn_m_unicst,
+ arn_m_tx,
+ arn_m_ioctl,
+ NULL,
+ NULL,
+ NULL,
+ arn_m_setprop,
+ arn_m_getprop
+};
+
+/*
+ * ARN_DBG_HW
+ * ARN_DBG_REG_IO
+ * ARN_DBG_QUEUE
+ * ARN_DBG_EEPROM
+ * ARN_DBG_XMIT
+ * ARN_DBG_RECV
+ * ARN_DBG_CALIBRATE
+ * ARN_DBG_CHANNEL
+ * ARN_DBG_INTERRUPT
+ * ARN_DBG_REGULATORY
+ * ARN_DBG_ANI
+ * ARN_DBG_POWER_MGMT
+ * ARN_DBG_KEYCACHE
+ * ARN_DBG_BEACON
+ * ARN_DBG_RATE
+ * ARN_DBG_INIT
+ * ARN_DBG_ATTACH
+ * ARN_DBG_DEATCH
+ * ARN_DBG_AGGR
+ * ARN_DBG_RESET
+ * ARN_DBG_FATAL
+ * ARN_DBG_ANY
+ * ARN_DBG_ALL
+ */
+uint32_t arn_dbg_mask = 0;
+
+/*
+ * Exception/warning cases not leading to panic.
+ */
+void
+arn_problem(const int8_t *fmt, ...)
+{
+ va_list args;
+
+ mutex_enter(&arn_loglock);
+
+ va_start(args, fmt);
+ vcmn_err(CE_WARN, fmt, args);
+ va_end(args);
+
+ mutex_exit(&arn_loglock);
+}
+
+/*
+ * Normal log information independent of debug.
+ */
+void
+arn_log(const int8_t *fmt, ...)
+{
+ va_list args;
+
+ mutex_enter(&arn_loglock);
+
+ va_start(args, fmt);
+ vcmn_err(CE_CONT, fmt, args);
+ va_end(args);
+
+ mutex_exit(&arn_loglock);
+}
+
+void
+arn_dbg(uint32_t dbg_flags, const int8_t *fmt, ...)
+{
+ va_list args;
+
+ if (dbg_flags & arn_dbg_mask) {
+ mutex_enter(&arn_loglock);
+ va_start(args, fmt);
+ vcmn_err(CE_CONT, fmt, args);
+ va_end(args);
+ mutex_exit(&arn_loglock);
+ }
+}
+
+/*
+ * Read and write, they both share the same lock. We do this to serialize
+ * reads and writes on Atheros 802.11n PCI devices only. This is required
+ * as the FIFO on these devices can only accept sanely 2 requests. After
+ * that the device goes bananas. Serializing the reads/writes prevents this
+ * from happening.
+ */
+void
+arn_iowrite32(struct ath_hal *ah, uint32_t reg_offset, uint32_t val)
+{
+ struct arn_softc *sc = ah->ah_sc;
+ if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) {
+ mutex_enter(&sc->sc_serial_rw);
+ ddi_put32(sc->sc_io_handle,
+ (uint32_t *)((uintptr_t)(sc->mem) + (reg_offset)), val);
+ mutex_exit(&sc->sc_serial_rw);
+ } else {
+ ddi_put32(sc->sc_io_handle,
+ (uint32_t *)((uintptr_t)(sc->mem) + (reg_offset)), val);
+ }
+}
+
+unsigned int
+arn_ioread32(struct ath_hal *ah, uint32_t reg_offset)
+{
+ uint32_t val;
+ struct arn_softc *sc = ah->ah_sc;
+ if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) {
+ mutex_enter(&sc->sc_serial_rw);
+ val = ddi_get32(sc->sc_io_handle,
+ (uint32_t *)((uintptr_t)(sc->mem) + (reg_offset)));
+ mutex_exit(&sc->sc_serial_rw);
+ } else {
+ val = ddi_get32(sc->sc_io_handle,
+ (uint32_t *)((uintptr_t)(sc->mem) + (reg_offset)));
+ }
+
+ return (val);
+}
+
+void
+arn_rx_buf_link(struct arn_softc *sc, struct ath_buf *bf)
+{
+ struct ath_desc *ds;
+
+ ds = bf->bf_desc;
+ ds->ds_link = bf->bf_daddr;
+ ds->ds_data = bf->bf_dma.cookie.dmac_address;
+ /* virtual addr of the beginning of the buffer. */
+ ds->ds_vdata = bf->bf_dma.mem_va;
+
+ /*
+ * setup rx descriptors. The bf_dma.alength here tells the H/W
+ * how much data it can DMA to us and that we are prepared
+ * to process
+ */
+ (void) ath9k_hw_setuprxdesc(sc->sc_ah, ds,
+ bf->bf_dma.alength, /* buffer size */
+ 0);
+
+ if (sc->sc_rxlink != NULL)
+ *sc->sc_rxlink = bf->bf_daddr;
+ sc->sc_rxlink = &ds->ds_link;
+}
+
+/*
+ * Allocate an area of memory and a DMA handle for accessing it
+ */
+static int
+arn_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, size_t memsize,
+ ddi_device_acc_attr_t *attr_p, uint_t alloc_flags,
+ uint_t bind_flags, dma_area_t *dma_p)
+{
+ int err;
+
+ /*
+ * Allocate handle
+ */
+ err = ddi_dma_alloc_handle(devinfo, dma_attr,
+ DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
+ if (err != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ /*
+ * Allocate memory
+ */
+ err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p,
+ alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va,
+ &dma_p->alength, &dma_p->acc_hdl);
+ if (err != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ /*
+ * Bind the two together
+ */
+ err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
+ dma_p->mem_va, dma_p->alength, bind_flags,
+ DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies);
+ if (err != DDI_DMA_MAPPED)
+ return (DDI_FAILURE);
+
+ dma_p->nslots = ~0U;
+ dma_p->size = ~0U;
+ dma_p->token = ~0U;
+ dma_p->offset = 0;
+ return (DDI_SUCCESS);
+}
+
+/*
+ * Free one allocated area of DMAable memory
+ */
+static void
+arn_free_dma_mem(dma_area_t *dma_p)
+{
+ if (dma_p->dma_hdl != NULL) {
+ (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
+ if (dma_p->acc_hdl != NULL) {
+ ddi_dma_mem_free(&dma_p->acc_hdl);
+ dma_p->acc_hdl = NULL;
+ }
+ ddi_dma_free_handle(&dma_p->dma_hdl);
+ dma_p->ncookies = 0;
+ dma_p->dma_hdl = NULL;
+ }
+}
+
+/*
+ * Initialize tx, rx. or beacon buffer list. Allocate DMA memory for
+ * each buffer.
+ */
+static int
+arn_buflist_setup(dev_info_t *devinfo, struct arn_softc *sc, list_t *bflist,
+ struct ath_buf **pbf, struct ath_desc **pds, int nbuf, uint_t dmabflags)
+{
+ int i, err;
+ struct ath_buf *bf = *pbf;
+ struct ath_desc *ds = *pds;
+
+ list_create(bflist, sizeof (struct ath_buf),
+ offsetof(struct ath_buf, bf_node));
+ for (i = 0; i < nbuf; i++, bf++, ds++) {
+ bf->bf_desc = ds;
+ bf->bf_daddr = sc->sc_desc_dma.cookie.dmac_address +
+ ((uintptr_t)ds - (uintptr_t)sc->sc_desc);
+ list_insert_tail(bflist, bf);
+
+ /* alloc DMA memory */
+ err = arn_alloc_dma_mem(devinfo, &arn_dma_attr,
+ sc->sc_dmabuf_size, &arn_desc_accattr, DDI_DMA_STREAMING,
+ dmabflags, &bf->bf_dma);
+ if (err != DDI_SUCCESS)
+ return (err);
+ }
+ *pbf = bf;
+ *pds = ds;
+
+ return (DDI_SUCCESS);
+}
+
+/*
+ * Destroy tx, rx or beacon buffer list. Free DMA memory.
+ */
+static void
+arn_buflist_cleanup(list_t *buflist)
+{
+ struct ath_buf *bf;
+
+ if (!buflist)
+ return;
+
+ bf = list_head(buflist);
+ while (bf != NULL) {
+ if (bf->bf_m != NULL) {
+ freemsg(bf->bf_m);
+ bf->bf_m = NULL;
+ }
+ /* Free DMA buffer */
+ arn_free_dma_mem(&bf->bf_dma);
+ if (bf->bf_in != NULL) {
+ ieee80211_free_node(bf->bf_in);
+ bf->bf_in = NULL;
+ }
+ list_remove(buflist, bf);
+ bf = list_head(buflist);
+ }
+ list_destroy(buflist);
+}
+
+static void
+arn_desc_free(struct arn_softc *sc)
+{
+ arn_buflist_cleanup(&sc->sc_txbuf_list);
+ arn_buflist_cleanup(&sc->sc_rxbuf_list);
+#ifdef ARN_IBSS
+ arn_buflist_cleanup(&sc->sc_bcbuf_list);
+#endif
+
+ /* Free descriptor DMA buffer */
+ arn_free_dma_mem(&sc->sc_desc_dma);
+
+ kmem_free((void *)sc->sc_vbufptr, sc->sc_vbuflen);
+ sc->sc_vbufptr = NULL;
+}
+
+static int
+arn_desc_alloc(dev_info_t *devinfo, struct arn_softc *sc)
+{
+ int err;
+ size_t size;
+ struct ath_desc *ds;
+ struct ath_buf *bf;
+
+#ifdef ARN_IBSS
+ size = sizeof (struct ath_desc) * (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF);
+#else
+ size = sizeof (struct ath_desc) * (ATH_TXBUF + ATH_RXBUF);
+#endif
+
+ err = arn_alloc_dma_mem(devinfo, &arn_desc_dma_attr, size,
+ &arn_desc_accattr, DDI_DMA_CONSISTENT,
+ DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &sc->sc_desc_dma);
+
+ /* virtual address of the first descriptor */
+ sc->sc_desc = (struct ath_desc *)sc->sc_desc_dma.mem_va;
+
+ ds = sc->sc_desc;
+ ARN_DBG((ARN_DBG_INIT, "arn: arn_desc_alloc(): DMA map: "
+ "%p (%d) -> %p\n",
+ sc->sc_desc, sc->sc_desc_dma.alength,
+ sc->sc_desc_dma.cookie.dmac_address));
+
+ /* allocate data structures to describe TX/RX DMA buffers */
+#ifdef ARN_IBSS
+ sc->sc_vbuflen = sizeof (struct ath_buf) * (ATH_TXBUF + ATH_RXBUF +
+ ATH_BCBUF);
+#else
+ sc->sc_vbuflen = sizeof (struct ath_buf) * (ATH_TXBUF + ATH_RXBUF);
+#endif
+ bf = (struct ath_buf *)kmem_zalloc(sc->sc_vbuflen, KM_SLEEP);
+ sc->sc_vbufptr = bf;
+
+ /* DMA buffer size for each TX/RX packet */
+ sc->sc_dmabuf_size = roundup(1000 + sizeof (struct ieee80211_frame) +
+ IEEE80211_MTU + IEEE80211_CRC_LEN +
+ (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
+ IEEE80211_WEP_CRCLEN), sc->sc_cachelsz);
+
+ /* create RX buffer list */
+ err = arn_buflist_setup(devinfo, sc, &sc->sc_rxbuf_list, &bf, &ds,
+ ATH_RXBUF, DDI_DMA_READ | DDI_DMA_STREAMING);
+ if (err != DDI_SUCCESS) {
+ arn_desc_free(sc);
+ return (err);
+ }
+
+ /* create TX buffer list */
+ err = arn_buflist_setup(devinfo, sc, &sc->sc_txbuf_list, &bf, &ds,
+ ATH_TXBUF, DDI_DMA_STREAMING);
+ if (err != DDI_SUCCESS) {
+ arn_desc_free(sc);
+ return (err);
+ }
+
+ /* create beacon buffer list */
+#ifdef ARN_IBSS
+ err = arn_buflist_setup(devinfo, sc, &sc->sc_bcbuf_list, &bf, &ds,
+ ATH_BCBUF, DDI_DMA_STREAMING);
+ if (err != DDI_SUCCESS) {
+ arn_desc_free(sc);
+ return (err);
+ }
+#endif
+
+ return (DDI_SUCCESS);
+}
+
+static struct ath_rate_table *
+/* LINTED E_STATIC_UNUSED */
+arn_get_ratetable(struct arn_softc *sc, uint32_t mode)
+{
+ struct ath_rate_table *rate_table = NULL;
+
+ switch (mode) {
+ case IEEE80211_MODE_11A:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
+ break;
+ case IEEE80211_MODE_11B:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11B];
+ break;
+ case IEEE80211_MODE_11G:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
+ break;
+#ifdef ARB_11N
+ case IEEE80211_MODE_11NA_HT20:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
+ break;
+ case IEEE80211_MODE_11NG_HT20:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
+ break;
+ case IEEE80211_MODE_11NA_HT40PLUS:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS];
+ break;
+ case IEEE80211_MODE_11NA_HT40MINUS:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS];
+ break;
+ case IEEE80211_MODE_11NG_HT40PLUS:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS];
+ break;
+ case IEEE80211_MODE_11NG_HT40MINUS:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS];
+ break;
+#endif
+ default:
+ ARN_DBG((ARN_DBG_FATAL, "arn: arn_get_ratetable(): "
+ "invalid mode %u\n", mode));
+ return (NULL);
+ }
+
+ return (rate_table);
+
+}
+
+static void
+arn_setcurmode(struct arn_softc *sc, enum wireless_mode mode)
+{
+ struct ath_rate_table *rt;
+ int i;
+
+ for (i = 0; i < sizeof (sc->asc_rixmap); i++)
+ sc->asc_rixmap[i] = 0xff;
+
+ rt = sc->hw_rate_table[mode];
+ ASSERT(rt != NULL);
+
+ for (i = 0; i < rt->rate_cnt; i++)
+ sc->asc_rixmap[rt->info[i].dot11rate &
+ IEEE80211_RATE_VAL] = (uint8_t)i; /* LINT */
+
+ sc->sc_currates = rt;
+ sc->sc_curmode = mode;
+
+ /*
+ * All protection frames are transmited at 2Mb/s for
+ * 11g, otherwise at 1Mb/s.
+ * XXX select protection rate index from rate table.
+ */
+ sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0);
+}
+
+static enum wireless_mode
+arn_chan2mode(struct ath9k_channel *chan)
+{
+ if (chan->chanmode == CHANNEL_A)
+ return (ATH9K_MODE_11A);
+ else if (chan->chanmode == CHANNEL_G)
+ return (ATH9K_MODE_11G);
+ else if (chan->chanmode == CHANNEL_B)
+ return (ATH9K_MODE_11B);
+ else if (chan->chanmode == CHANNEL_A_HT20)
+ return (ATH9K_MODE_11NA_HT20);
+ else if (chan->chanmode == CHANNEL_G_HT20)
+ return (ATH9K_MODE_11NG_HT20);
+ else if (chan->chanmode == CHANNEL_A_HT40PLUS)
+ return (ATH9K_MODE_11NA_HT40PLUS);
+ else if (chan->chanmode == CHANNEL_A_HT40MINUS)
+ return (ATH9K_MODE_11NA_HT40MINUS);
+ else if (chan->chanmode == CHANNEL_G_HT40PLUS)
+ return (ATH9K_MODE_11NG_HT40PLUS);
+ else if (chan->chanmode == CHANNEL_G_HT40MINUS)
+ return (ATH9K_MODE_11NG_HT40MINUS);
+
+ return (ATH9K_MODE_11B);
+}
+
+static void
+arn_update_txpow(struct arn_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ uint32_t txpow;
+
+ if (sc->sc_curtxpow != sc->sc_config.txpowlimit) {
+ (void) ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit);
+ /* read back in case value is clamped */
+ (void) ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
+ sc->sc_curtxpow = (uint32_t)txpow;
+ }
+}
+
+static void
+arn_setup_rates(struct arn_softc *sc, uint32_t mode)
+{
+ int i, maxrates;
+ struct ath_rate_table *rate_table = NULL;
+ struct ieee80211_rateset *rateset;
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+
+ /* rate_table = arn_get_ratetable(sc, mode); */
+ switch (mode) {
+ case IEEE80211_MODE_11A:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
+ break;
+ case IEEE80211_MODE_11B:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11B];
+ break;
+ case IEEE80211_MODE_11G:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
+ break;
+#ifdef ARN_11N
+ case IEEE80211_MODE_11NA_HT20:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
+ break;
+ case IEEE80211_MODE_11NG_HT20:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
+ break;
+ case IEEE80211_MODE_11NA_HT40PLUS:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS];
+ break;
+ case IEEE80211_MODE_11NA_HT40MINUS:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS];
+ break;
+ case IEEE80211_MODE_11NG_HT40PLUS:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS];
+ break;
+ case IEEE80211_MODE_11NG_HT40MINUS:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS];
+ break;
+#endif
+ default:
+ ARN_DBG((ARN_DBG_RATE, "arn: arn_get_ratetable(): "
+ "invalid mode %u\n", mode));
+ break;
+ }
+ if (rate_table == NULL)
+ return;
+ if (rate_table->rate_cnt > ATH_RATE_MAX) {
+ ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_setup(): "
+ "rate table too small (%u > %u)\n",
+ rate_table->rate_cnt, IEEE80211_RATE_MAXSIZE));
+ maxrates = ATH_RATE_MAX;
+ } else
+ maxrates = rate_table->rate_cnt;
+
+ ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_setup(): "
+ "maxrates is %d\n", maxrates));
+
+ rateset = &ic->ic_sup_rates[mode];
+ for (i = 0; i < maxrates; i++) {
+ rateset->ir_rates[i] = rate_table->info[i].dot11rate;
+ ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_setup(): "
+ "%d\n", rate_table->info[i].dot11rate));
+ }
+ rateset->ir_nrates = (uint8_t)maxrates; /* ??? */
+}
+
+static int
+arn_setup_channels(struct arn_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ int nchan, i, index;
+ uint8_t regclassids[ATH_REGCLASSIDS_MAX];
+ uint32_t nregclass = 0;
+ struct ath9k_channel *c;
+
+ /* Fill in ah->ah_channels */
+ if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (uint32_t *)&nchan,
+ regclassids, ATH_REGCLASSIDS_MAX, &nregclass, CTRY_DEFAULT,
+ B_FALSE, 1)) {
+ uint32_t rd = ah->ah_currentRD;
+ ARN_DBG((ARN_DBG_CHANNEL, "arn: arn_setup_channels(): "
+ "unable to collect channel list; "
+ "regdomain likely %u country code %u\n",
+ rd, CTRY_DEFAULT));
+ return (EINVAL);
+ }
+
+ ARN_DBG((ARN_DBG_CHANNEL, "arn: arn_setup_channels(): "
+ "number of channel is %d\n", nchan));
+
+ for (i = 0; i < nchan; i++) {
+ c = &ah->ah_channels[i];
+ uint16_t flags;
+ index = ath9k_hw_mhz2ieee(ah, c->channel, c->channelFlags);
+
+ if (index > IEEE80211_CHAN_MAX) {
+ ARN_DBG((ARN_DBG_CHANNEL,
+ "arn: arn_setup_channels(): "
+ "bad hal channel %d (%u/%x) ignored\n",
+ index, c->channel, c->channelFlags));
+ continue;
+ }
+ /* NB: flags are known to be compatible */
+ if (index < 0) {
+ /*
+ * can't handle frequency <2400MHz (negative
+ * channels) right now
+ */
+ ARN_DBG((ARN_DBG_CHANNEL,
+ "arn: arn_setup_channels(): "
+ "hal channel %d (%u/%x) "
+ "cannot be handled, ignored\n",
+ index, c->channel, c->channelFlags));
+ continue;
+ }
+
+ /*
+ * Calculate net80211 flags; most are compatible
+ * but some need massaging. Note the static turbo
+ * conversion can be removed once net80211 is updated
+ * to understand static vs. dynamic turbo.
+ */
+
+ flags = c->channelFlags & (CHANNEL_ALL | CHANNEL_PASSIVE);
+
+ if (ic->ic_sup_channels[index].ich_freq == 0) {
+ ic->ic_sup_channels[index].ich_freq = c->channel;
+ ic->ic_sup_channels[index].ich_flags = flags;
+ } else {
+ /* channels overlap; e.g. 11g and 11b */
+ ic->ic_sup_channels[index].ich_flags |= flags;
+ }
+ if ((c->channelFlags & CHANNEL_G) == CHANNEL_G) {
+ sc->sc_have11g = 1;
+ ic->ic_caps |= IEEE80211_C_SHPREAMBLE |
+ IEEE80211_C_SHSLOT; /* short slot time */
+ }
+ }
+
+ return (0);
+}
+
+uint32_t
+arn_chan2flags(ieee80211com_t *isc, struct ieee80211_channel *chan)
+{
+ static const uint32_t modeflags[] = {
+ 0, /* IEEE80211_MODE_AUTO */
+ CHANNEL_A, /* IEEE80211_MODE_11A */
+ CHANNEL_B, /* IEEE80211_MODE_11B */
+ CHANNEL_G, /* IEEE80211_MODE_11G */
+ 0, /* */
+ 0, /* */
+ 0 /* */
+ };
+ return (modeflags[ieee80211_chan2mode(isc, chan)]);
+}
+
+/*
+ * Update internal state after a channel change.
+ */
+void
+arn_chan_change(struct arn_softc *sc, struct ieee80211_channel *chan)
+{
+ struct ieee80211com *ic = &sc->sc_isc;
+ enum ieee80211_phymode mode;
+ enum wireless_mode wlmode;
+
+ /*
+ * Change channels and update the h/w rate map
+ * if we're switching; e.g. 11a to 11b/g.
+ */
+ mode = ieee80211_chan2mode(ic, chan);
+ switch (mode) {
+ case IEEE80211_MODE_11A:
+ wlmode = ATH9K_MODE_11A;
+ break;
+ case IEEE80211_MODE_11B:
+ wlmode = ATH9K_MODE_11B;
+ break;
+ case IEEE80211_MODE_11G:
+ wlmode = ATH9K_MODE_11B;
+ break;
+ default:
+ break;
+ }
+ if (wlmode != sc->sc_curmode)
+ arn_setcurmode(sc, wlmode);
+
+}
+
+/*
+ * Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+ */
+static int
+arn_set_channel(struct arn_softc *sc, struct ath9k_channel *hchan)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ ieee80211com_t *ic = &sc->sc_isc;
+ boolean_t fastcc = B_TRUE;
+ boolean_t stopped;
+ struct ieee80211_channel chan;
+ enum wireless_mode curmode;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return (EIO);
+
+ if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
+ hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
+ (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
+ (sc->sc_flags & SC_OP_FULL_RESET)) {
+ int status;
+
+ /*
+ * This is only performed if the channel settings have
+ * actually changed.
+ *
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+ * hardware at the new frequency, and then re-enable
+ * the relevant bits of the h/w.
+ */
+ (void) ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
+ arn_draintxq(sc, B_FALSE); /* clear pending tx frames */
+ stopped = arn_stoprecv(sc); /* turn off frame recv */
+
+ /*
+ * XXX: do not flush receive queue here. We don't want
+ * to flush data frames already in queue because of
+ * changing channel.
+ */
+
+ if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
+ fastcc = B_FALSE;
+
+ ARN_DBG((ARN_DBG_CHANNEL, "arn: arn_set_channel(): "
+ "(%u MHz) -> (%u MHz), cflags:%x, chanwidth: %d\n",
+ sc->sc_ah->ah_curchan->channel,
+ hchan->channel, hchan->channelFlags, sc->tx_chan_width));
+
+ if (!ath9k_hw_reset(ah, hchan, sc->tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, fastcc, &status)) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: arn_set_channel(): "
+ "unable to reset channel %u (%uMhz) "
+ "flags 0x%x hal status %u\n",
+ ath9k_hw_mhz2ieee(ah, hchan->channel,
+ hchan->channelFlags),
+ hchan->channel, hchan->channelFlags, status));
+ return (EIO);
+ }
+
+ sc->sc_curchan = *hchan;
+
+ sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
+ sc->sc_flags &= ~SC_OP_FULL_RESET;
+
+ if (arn_startrecv(sc) != 0) {
+ arn_problem("arn: arn_set_channel(): "
+ "unable to restart recv logic\n");
+ return (EIO);
+ }
+
+ chan.ich_freq = hchan->channel;
+ chan.ich_flags = hchan->channelFlags;
+ ic->ic_ibss_chan = &chan;
+
+ /*
+ * Change channels and update the h/w rate map
+ * if we're switching; e.g. 11a to 11b/g.
+ */
+ curmode = arn_chan2mode(hchan);
+ if (curmode != sc->sc_curmode)
+ arn_setcurmode(sc, arn_chan2mode(hchan));
+
+ arn_update_txpow(sc);
+
+ (void) ath9k_hw_set_interrupts(ah, sc->sc_imask);
+ }
+
+ return (0);
+}
+
+/*
+ * This routine performs the periodic noise floor calibration function
+ * that is used to adjust and optimize the chip performance. This
+ * takes environmental changes (location, temperature) into account.
+ * When the task is complete, it reschedules itself depending on the
+ * appropriate interval that was calculated.
+ */
+static void
+arn_ani_calibrate(void *arg)
+
+{
+ ieee80211com_t *ic = (ieee80211com_t *)arg;
+ struct arn_softc *sc = (struct arn_softc *)ic;
+ struct ath_hal *ah = sc->sc_ah;
+ boolean_t longcal = B_FALSE;
+ boolean_t shortcal = B_FALSE;
+ boolean_t aniflag = B_FALSE;
+ unsigned int timestamp = drv_hztousec(ddi_get_lbolt())/1000;
+ uint32_t cal_interval;
+
+ /*
+ * don't calibrate when we're scanning.
+ * we are most likely not on our home channel.
+ */
+ if (ic->ic_state != IEEE80211_S_RUN)
+ goto settimer;
+
+ /* Long calibration runs independently of short calibration. */
+ if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) {
+ longcal = B_TRUE;
+ ARN_DBG((ARN_DBG_CALIBRATE, "arn: "
+ "%s: longcal @%lu\n", __func__, drv_hztousec));
+ sc->sc_ani.sc_longcal_timer = timestamp;
+ }
+
+ /* Short calibration applies only while sc_caldone is FALSE */
+ if (!sc->sc_ani.sc_caldone) {
+ if ((timestamp - sc->sc_ani.sc_shortcal_timer) >=
+ ATH_SHORT_CALINTERVAL) {
+ shortcal = B_TRUE;
+ ARN_DBG((ARN_DBG_CALIBRATE, "arn: "
+ "%s: shortcal @%lu\n",
+ __func__, drv_hztousec));
+ sc->sc_ani.sc_shortcal_timer = timestamp;
+ sc->sc_ani.sc_resetcal_timer = timestamp;
+ }
+ } else {
+ if ((timestamp - sc->sc_ani.sc_resetcal_timer) >=
+ ATH_RESTART_CALINTERVAL) {
+ ath9k_hw_reset_calvalid(ah, ah->ah_curchan,
+ &sc->sc_ani.sc_caldone);
+ if (sc->sc_ani.sc_caldone)
+ sc->sc_ani.sc_resetcal_timer = timestamp;
+ }
+ }
+
+ /* Verify whether we must check ANI */
+ if ((timestamp - sc->sc_ani.sc_checkani_timer) >=
+ ATH_ANI_POLLINTERVAL) {
+ aniflag = B_TRUE;
+ sc->sc_ani.sc_checkani_timer = timestamp;
+ }
+
+ /* Skip all processing if there's nothing to do. */
+ if (longcal || shortcal || aniflag) {
+ /* Call ANI routine if necessary */
+ if (aniflag)
+ ath9k_hw_ani_monitor(ah, &sc->sc_halstats,
+ ah->ah_curchan);
+
+ /* Perform calibration if necessary */
+ if (longcal || shortcal) {
+ boolean_t iscaldone = B_FALSE;
+
+ if (ath9k_hw_calibrate(ah, ah->ah_curchan,
+ sc->sc_rx_chainmask, longcal, &iscaldone)) {
+ if (longcal)
+ sc->sc_ani.sc_noise_floor =
+ ath9k_hw_getchan_noise(ah,
+ ah->ah_curchan);
+
+ ARN_DBG((ARN_DBG_CALIBRATE, "arn: "
+ "%s: calibrate chan %u/%x nf: %d\n",
+ __func__,
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags,
+ sc->sc_ani.sc_noise_floor));
+ } else {
+ ARN_DBG((ARN_DBG_CALIBRATE, "arn: "
+ "%s: calibrate chan %u/%x failed\n",
+ __func__,
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags));
+ }
+ sc->sc_ani.sc_caldone = iscaldone;
+ }
+ }
+
+settimer:
+ /*
+ * Set timer interval based on previous results.
+ * The interval must be the shortest necessary to satisfy ANI,
+ * short calibration and long calibration.
+ */
+ cal_interval = ATH_LONG_CALINTERVAL;
+ if (sc->sc_ah->ah_config.enable_ani)
+ cal_interval =
+ min(cal_interval, (uint32_t)ATH_ANI_POLLINTERVAL);
+
+ if (!sc->sc_ani.sc_caldone)
+ cal_interval = min(cal_interval,
+ (uint32_t)ATH_SHORT_CALINTERVAL);
+
+ sc->sc_scan_timer = 0;
+ sc->sc_scan_timer = timeout(arn_ani_calibrate, (void *)sc,
+ drv_usectohz(cal_interval * 1000));
+}
+
+static void
+arn_stop_caltimer(struct arn_softc *sc)
+{
+ timeout_id_t tmp_id = 0;
+
+ while ((sc->sc_cal_timer != 0) && (tmp_id != sc->sc_cal_timer)) {
+ tmp_id = sc->sc_cal_timer;
+ (void) untimeout(tmp_id);
+ }
+ sc->sc_cal_timer = 0;
+}
+
+static uint_t
+arn_isr(caddr_t arg)
+{
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ struct arn_softc *sc = (struct arn_softc *)arg;
+ struct ath_hal *ah = sc->sc_ah;
+ enum ath9k_int status;
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+
+ ARN_LOCK(sc);
+
+ if (sc->sc_flags & SC_OP_INVALID) {
+ /*
+ * The hardware is not ready/present, don't
+ * touch anything. Note this can happen early
+ * on if the IRQ is shared.
+ */
+ ARN_UNLOCK(sc);
+ return (DDI_INTR_UNCLAIMED);
+ }
+ if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */
+ ARN_UNLOCK(sc);
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ /*
+ * Figure out the reason(s) for the interrupt. Note
+ * that the hal returns a pseudo-ISR that may include
+ * bits we haven't explicitly enabled so we mask the
+ * value to insure we only process bits we requested.
+ */
+ (void) ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
+
+ status &= sc->sc_imask; /* discard unasked-for bits */
+
+ /*
+ * If there are no status bits set, then this interrupt was not
+ * for me (should have been caught above).
+ */
+ if (!status) {
+ ARN_UNLOCK(sc);
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ sc->sc_intrstatus = status;
+
+ if (status & ATH9K_INT_FATAL) {
+ /* need a chip reset */
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_FATAL\n"));
+ goto reset;
+ } else if (status & ATH9K_INT_RXORN) {
+ /* need a chip reset */
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_RXORN\n"));
+ goto reset;
+ } else {
+ if (status & ATH9K_INT_RXEOL) {
+ /*
+ * NB: the hardware should re-read the link when
+ * RXE bit is written, but it doesn't work
+ * at least on older hardware revs.
+ */
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_RXEOL\n"));
+ sc->sc_rxlink = NULL;
+ }
+ if (status & ATH9K_INT_TXURN) {
+ /* bump tx trigger level */
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_TXURN\n"));
+ (void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
+ }
+ /* XXX: optimize this */
+ if (status & ATH9K_INT_RX) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_RX\n"));
+ sc->sc_rx_pend = 1;
+ ddi_trigger_softintr(sc->sc_softint_id);
+ }
+ if (status & ATH9K_INT_TX) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_TX\n"));
+ if (ddi_taskq_dispatch(sc->sc_tq,
+ arn_tx_int_proc, sc, DDI_NOSLEEP) !=
+ DDI_SUCCESS) {
+ arn_problem("arn: arn_isr(): "
+ "No memory for tx taskq\n");
+ }
+ }
+#ifdef ARN_ATH9K_INT_MIB
+ if (status & ATH9K_INT_MIB) {
+ /*
+ * Disable interrupts until we service the MIB
+ * interrupt; otherwise it will continue to
+ * fire.
+ */
+ (void) ath9k_hw_set_interrupts(ah, 0);
+ /*
+ * Let the hal handle the event. We assume
+ * it will clear whatever condition caused
+ * the interrupt.
+ */
+ ath9k_hw_procmibevent(ah, &sc->sc_halstats);
+ (void) ath9k_hw_set_interrupts(ah, sc->sc_imask);
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_MIB\n"));
+ }
+#endif
+
+#ifdef ARN_ATH9K_INT_TIM_TIMER
+ if (status & ATH9K_INT_TIM_TIMER) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_TIM_TIMER\n"));
+ if (!(ah->ah_caps.hw_caps &
+ ATH9K_HW_CAP_AUTOSLEEP)) {
+ /*
+ * Clear RxAbort bit so that we can
+ * receive frames
+ */
+ ath9k_hw_setrxabort(ah, 0);
+ goto reset;
+ }
+ }
+#endif
+
+ if (status & ATH9K_INT_BMISS) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_BMISS\n"));
+
+ if (ddi_taskq_dispatch(sc->sc_tq, arn_bmiss_proc,
+ sc, DDI_NOSLEEP) != DDI_SUCCESS) {
+ arn_problem("arn: arn_isr(): "
+ "No memory available for bmiss taskq\n");
+ }
+ }
+
+ ARN_UNLOCK(sc);
+
+#ifdef ARN_ATH9K_INT_CST
+ /* carrier sense timeout */
+ if (status & ATH9K_INT_CST) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_CST\n"));
+ return (DDI_INTR_CLAIMED);
+ }
+#endif
+
+ if (status & ATH9K_INT_SWBA) {
+ ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): "
+ "ATH9K_INT_SWBA\n"));
+ /* This will occur only in Host-AP or Ad-Hoc mode */
+ return (DDI_INTR_CLAIMED);
+ }
+ }
+
+ return (DDI_INTR_CLAIMED);
+reset:
+ ARN_DBG((ARN_DBG_INTERRUPT, "Rset for fatal err\n"));
+ (void) arn_reset(ic);
+ ARN_UNLOCK(sc);
+ return (DDI_INTR_CLAIMED);
+}
+
+static int
+arn_get_channel(struct arn_softc *sc, struct ieee80211_channel *chan)
+{
+ int i;
+
+ for (i = 0; i < sc->sc_ah->ah_nchan; i++) {
+ if (sc->sc_ah->ah_channels[i].channel == chan->ich_freq)
+ return (i);
+ }
+
+ return (-1);
+}
+
+int
+arn_reset(ieee80211com_t *ic)
+{
+ struct arn_softc *sc = (struct arn_softc *)ic;
+ struct ath_hal *ah = sc->sc_ah;
+ int status;
+ int error = 0;
+
+ (void) ath9k_hw_set_interrupts(ah, 0);
+ arn_draintxq(sc, 0);
+ (void) arn_stoprecv(sc);
+
+ if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, sc->tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, B_FALSE, &status)) {
+ ARN_DBG((ARN_DBG_RESET, "arn: arn_reset(): "
+ "unable to reset hardware; hal status %u\n", status));
+ error = EIO;
+ }
+
+ if (arn_startrecv(sc) != 0)
+ ARN_DBG((ARN_DBG_RESET, "arn: arn_reset(): "
+ "unable to start recv logic\n"));
+
+ /*
+ * We may be doing a reset in response to a request
+ * that changes the channel so update any state that
+ * might change as a result.
+ */
+ arn_setcurmode(sc, arn_chan2mode(sc->sc_ah->ah_curchan));
+
+ arn_update_txpow(sc);
+
+ if (sc->sc_flags & SC_OP_BEACONS)
+ arn_beacon_config(sc); /* restart beacons */
+
+ (void) ath9k_hw_set_interrupts(ah, sc->sc_imask);
+
+ return (error);
+}
+
+int
+arn_get_hal_qnum(uint16_t queue, struct arn_softc *sc)
+{
+ int qnum;
+
+ switch (queue) {
+ case WME_AC_VO:
+ qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO];
+ break;
+ case WME_AC_VI:
+ qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI];
+ break;
+ case WME_AC_BE:
+ qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
+ break;
+ case WME_AC_BK:
+ qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK];
+ break;
+ default:
+ qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
+ break;
+ }
+
+ return (qnum);
+}
+
+static struct {
+ uint32_t version;
+ const char *name;
+} ath_mac_bb_names[] = {
+ { AR_SREV_VERSION_5416_PCI, "5416" },
+ { AR_SREV_VERSION_5416_PCIE, "5418" },
+ { AR_SREV_VERSION_9100, "9100" },
+ { AR_SREV_VERSION_9160, "9160" },
+ { AR_SREV_VERSION_9280, "9280" },
+ { AR_SREV_VERSION_9285, "9285" }
+};
+
+static struct {
+ uint16_t version;
+ const char *name;
+} ath_rf_names[] = {
+ { 0, "5133" },
+ { AR_RAD5133_SREV_MAJOR, "5133" },
+ { AR_RAD5122_SREV_MAJOR, "5122" },
+ { AR_RAD2133_SREV_MAJOR, "2133" },
+ { AR_RAD2122_SREV_MAJOR, "2122" }
+};
+
+/*
+ * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
+ */
+
+static const char *
+arn_mac_bb_name(uint32_t mac_bb_version)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ath_mac_bb_names); i++) {
+ if (ath_mac_bb_names[i].version == mac_bb_version) {
+ return (ath_mac_bb_names[i].name);
+ }
+ }
+
+ return ("????");
+}
+
+/*
+ * Return the RF name. "????" is returned if the RF is unknown.
+ */
+
+static const char *
+arn_rf_name(uint16_t rf_version)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ath_rf_names); i++) {
+ if (ath_rf_names[i].version == rf_version) {
+ return (ath_rf_names[i].name);
+ }
+ }
+
+ return ("????");
+}
+
+static void
+arn_next_scan(void *arg)
+{
+ ieee80211com_t *ic = arg;
+ struct arn_softc *sc = (struct arn_softc *)ic;
+
+ sc->sc_scan_timer = 0;
+ if (ic->ic_state == IEEE80211_S_SCAN) {
+ sc->sc_scan_timer = timeout(arn_next_scan, (void *)sc,
+ drv_usectohz(arn_dwelltime * 1000));
+ ieee80211_next_scan(ic);
+ }
+}
+
+static void
+arn_stop_scantimer(struct arn_softc *sc)
+{
+ timeout_id_t tmp_id = 0;
+
+ while ((sc->sc_scan_timer != 0) && (tmp_id != sc->sc_scan_timer)) {
+ tmp_id = sc->sc_scan_timer;
+ (void) untimeout(tmp_id);
+ }
+ sc->sc_scan_timer = 0;
+}
+
+static int32_t
+arn_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
+{
+ struct arn_softc *sc = (struct arn_softc *)ic;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_node *in;
+ int32_t i, error;
+ uint8_t *bssid;
+ uint32_t rfilt;
+ enum ieee80211_state ostate;
+ struct ath9k_channel *channel;
+ int pos;
+
+ /* Should set up & init LED here */
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return (0);
+
+ ostate = ic->ic_state;
+ ARN_DBG((ARN_DBG_INIT, "arn: arn_newstate(): "
+ "%x -> %x!\n", ostate, nstate));
+
+ ARN_LOCK(sc);
+
+ if (nstate != IEEE80211_S_SCAN)
+ arn_stop_scantimer(sc);
+ if (nstate != IEEE80211_S_RUN)
+ arn_stop_caltimer(sc);
+
+ /* Should set LED here */
+
+ if (nstate == IEEE80211_S_INIT) {
+ sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+ /*
+ * Disable interrupts.
+ */
+ (void) ath9k_hw_set_interrupts
+ (ah, sc->sc_imask &~ ATH9K_INT_GLOBAL);
+
+#ifdef ARN_IBSS
+ if (ic->ic_opmode == IEEE80211_M_IBSS) {
+ (void) ath9k_hw_stoptxdma(ah, sc->sc_beaconq);
+ arn_beacon_return(sc);
+ }
+#endif
+ ARN_UNLOCK(sc);
+ ieee80211_stop_watchdog(ic);
+ goto done;
+ }
+ in = ic->ic_bss;
+
+ pos = arn_get_channel(sc, ic->ic_curchan);
+
+ if (pos == -1) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: "
+ "%s: Invalid channel\n", __func__));
+ error = EINVAL;
+ ARN_UNLOCK(sc);
+ goto bad;
+ }
+ sc->tx_chan_width = ATH9K_HT_MACMODE_20;
+ sc->sc_ah->ah_channels[pos].chanmode =
+ arn_chan2flags(ic, ic->ic_curchan);
+ channel = &sc->sc_ah->ah_channels[pos];
+ if (channel == NULL) {
+ arn_problem("arn_newstate(): channel == NULL");
+ ARN_UNLOCK(sc);
+ goto bad;
+ }
+ error = arn_set_channel(sc, channel);
+ if (error != 0) {
+ if (nstate != IEEE80211_S_SCAN) {
+ ARN_UNLOCK(sc);
+ ieee80211_reset_chan(ic);
+ goto bad;
+ }
+ }
+
+ /*
+ * Get the receive filter according to the
+ * operating mode and state
+ */
+ rfilt = arn_calcrxfilter(sc);
+
+ if (nstate == IEEE80211_S_SCAN)
+ bssid = ic->ic_macaddr;
+ else
+ bssid = in->in_bssid;
+
+ ath9k_hw_setrxfilter(ah, rfilt);
+
+ if (nstate == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS)
+ ath9k_hw_write_associd(ah, bssid, in->in_associd);
+ else
+ ath9k_hw_write_associd(ah, bssid, 0);
+
+ /* Check for WLAN_CAPABILITY_PRIVACY ? */
+ if (ic->ic_flags & IEEE80211_F_PRIVACY) {
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ if (ath9k_hw_keyisvalid(ah, (uint16_t)i))
+ (void) ath9k_hw_keysetmac(ah, (uint16_t)i,
+ bssid);
+ }
+ }
+
+ if (nstate == IEEE80211_S_RUN) {
+ switch (ic->ic_opmode) {
+#ifdef ARN_IBSS
+ case IEEE80211_M_IBSS:
+ /*
+ * Allocate and setup the beacon frame.
+ * Stop any previous beacon DMA.
+ */
+ (void) ath9k_hw_stoptxdma(ah, sc->sc_beaconq);
+ arn_beacon_return(sc);
+ error = arn_beacon_alloc(sc, in);
+ if (error != 0) {
+ ARN_UNLOCK(sc);
+ goto bad;
+ }
+ /*
+ * If joining an adhoc network defer beacon timer
+ * configuration to the next beacon frame so we
+ * have a current TSF to use. Otherwise we're
+ * starting an ibss/bss so there's no need to delay.
+ */
+ if (ic->ic_opmode == IEEE80211_M_IBSS &&
+ ic->ic_bss->in_tstamp.tsf != 0) {
+ sc->sc_bsync = 1;
+ } else {
+ arn_beacon_config(sc);
+ }
+ break;
+#endif /* ARN_IBSS */
+ case IEEE80211_M_STA:
+ if (ostate != IEEE80211_S_RUN) {
+ /*
+ * Defer beacon timer configuration to the next
+ * beacon frame so we have a current TSF to use.
+ * Any TSF collected when scanning is likely old
+ */
+#ifdef ARN_IBSS
+ sc->sc_bsync = 1;
+#else
+ /* Configure the beacon and sleep timers. */
+ arn_beacon_config(sc);
+#endif /* ARN_IBSS */
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+ (void) ath9k_hw_set_interrupts(ah, sc->sc_imask);
+ }
+
+ /*
+ * Reset the rate control state.
+ */
+ arn_rate_ctl_reset(sc, nstate);
+
+ ARN_UNLOCK(sc);
+done:
+ /*
+ * Invoke the parent method to complete the work.
+ */
+ error = sc->sc_newstate(ic, nstate, arg);
+
+ /*
+ * Finally, start any timers.
+ */
+ if (nstate == IEEE80211_S_RUN) {
+ ieee80211_start_watchdog(ic, 1);
+ ASSERT(sc->sc_cal_timer == 0);
+ sc->sc_cal_timer = timeout(arn_ani_calibrate, (void *)sc,
+ drv_usectohz(100 * 1000));
+ } else if ((nstate == IEEE80211_S_SCAN) && (ostate != nstate)) {
+ /* start ap/neighbor scan timer */
+ /* ASSERT(sc->sc_scan_timer == 0); */
+ if (sc->sc_scan_timer != 0) {
+ (void) untimeout(sc->sc_scan_timer);
+ sc->sc_scan_timer = 0;
+ }
+ sc->sc_scan_timer = timeout(arn_next_scan, (void *)sc,
+ drv_usectohz(arn_dwelltime * 1000));
+ }
+
+bad:
+ return (error);
+}
+
+static void
+arn_watchdog(void *arg)
+{
+ struct arn_softc *sc = arg;
+ ieee80211com_t *ic = &sc->sc_isc;
+ int ntimer = 0;
+
+ ARN_LOCK(sc);
+ ic->ic_watchdog_timer = 0;
+ if (sc->sc_flags & SC_OP_INVALID) {
+ ARN_UNLOCK(sc);
+ return;
+ }
+
+ if (ic->ic_state == IEEE80211_S_RUN) {
+ /*
+ * Start the background rate control thread if we
+ * are not configured to use a fixed xmit rate.
+ */
+ if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
+ sc->sc_stats.ast_rate_calls ++;
+ if (ic->ic_opmode == IEEE80211_M_STA)
+ arn_rate_ctl(ic, ic->ic_bss);
+ else
+ ieee80211_iterate_nodes(&ic->ic_sta,
+ arn_rate_ctl, sc);
+ }
+
+ ntimer = 1;
+ }
+ ARN_UNLOCK(sc);
+
+ ieee80211_watchdog(ic);
+ if (ntimer != 0)
+ ieee80211_start_watchdog(ic, ntimer);
+}
+
+static struct ieee80211_node *
+arn_node_alloc(ieee80211com_t *ic)
+{
+ struct ath_node *an;
+ struct arn_softc *sc = (struct arn_softc *)ic;
+
+ an = kmem_zalloc(sizeof (struct ath_node), KM_SLEEP);
+ arn_rate_update(sc, &an->an_node, 0);
+
+ return ((an != NULL) ? &an->an_node : NULL);
+}
+
+static void
+arn_node_free(struct ieee80211_node *in)
+{
+ ieee80211com_t *ic = in->in_ic;
+ struct arn_softc *sc = (struct arn_softc *)ic;
+ struct ath_buf *bf;
+ struct ath_txq *txq;
+ int32_t i;
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ARN_TXQ_SETUP(sc, i)) {
+ txq = &sc->sc_txq[i];
+ mutex_enter(&txq->axq_lock);
+ bf = list_head(&txq->axq_list);
+ while (bf != NULL) {
+ if (bf->bf_in == in) {
+ bf->bf_in = NULL;
+ }
+ bf = list_next(&txq->axq_list, bf);
+ }
+ mutex_exit(&txq->axq_lock);
+ }
+ }
+
+ ic->ic_node_cleanup(in);
+ if (in->in_wpa_ie != NULL)
+ ieee80211_free(in->in_wpa_ie);
+ kmem_free(in, sizeof (struct ath_node));
+}
+
+/*
+ * Allocate tx/rx key slots for TKIP. We allocate one slot for
+ * each key. MIC is right after the decrypt/encrypt key.
+ */
+static uint16_t
+arn_key_alloc_pair(struct arn_softc *sc, ieee80211_keyix *txkeyix,
+ ieee80211_keyix *rxkeyix)
+{
+ uint16_t i, keyix;
+
+ ASSERT(!sc->sc_splitmic);
+ for (i = 0; i < ARRAY_SIZE(sc->sc_keymap)/4; i++) {
+ uint8_t b = sc->sc_keymap[i];
+ if (b == 0xff)
+ continue;
+ for (keyix = i * NBBY; keyix < (i + 1) * NBBY;
+ keyix++, b >>= 1) {
+ if ((b & 1) || is_set(keyix+64, sc->sc_keymap)) {
+ /* full pair unavailable */
+ continue;
+ }
+ set_bit(keyix, sc->sc_keymap);
+ set_bit(keyix+64, sc->sc_keymap);
+ ARN_DBG((ARN_DBG_KEYCACHE,
+ "arn_key_alloc_pair(): key pair %u,%u\n",
+ keyix, keyix+64));
+ *txkeyix = *rxkeyix = keyix;
+ return (1);
+ }
+ }
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn_key_alloc_pair():"
+ " out of pair space\n"));
+
+ return (0);
+}
+
+/*
+ * Allocate tx/rx key slots for TKIP. We allocate two slots for
+ * each key, one for decrypt/encrypt and the other for the MIC.
+ */
+static int
+arn_key_alloc_2pair(struct arn_softc *sc, ieee80211_keyix *txkeyix,
+ ieee80211_keyix *rxkeyix)
+{
+ uint16_t i, keyix;
+
+ ASSERT(sc->sc_splitmic);
+ for (i = 0; i < ARRAY_SIZE(sc->sc_keymap)/4; i++) {
+ uint8_t b = sc->sc_keymap[i];
+ if (b != 0xff) {
+ /*
+ * One or more slots in this byte are free.
+ */
+ keyix = i*NBBY;
+ while (b & 1) {
+ again:
+ keyix++;
+ b >>= 1;
+ }
+ /* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */
+ if (is_set(keyix+32, sc->sc_keymap) ||
+ is_set(keyix+64, sc->sc_keymap) ||
+ is_set(keyix+32+64, sc->sc_keymap)) {
+ /* full pair unavailable */
+ if (keyix == (i+1)*NBBY) {
+ /* no slots were appropriate, advance */
+ continue;
+ }
+ goto again;
+ }
+ set_bit(keyix, sc->sc_keymap);
+ set_bit(keyix+64, sc->sc_keymap);
+ set_bit(keyix+32, sc->sc_keymap);
+ set_bit(keyix+32+64, sc->sc_keymap);
+ ARN_DBG((ARN_DBG_KEYCACHE,
+ "arn_key_alloc_2pair(): key pair %u,%u %u,%u\n",
+ keyix, keyix+64,
+ keyix+32, keyix+32+64));
+ *txkeyix = *rxkeyix = keyix;
+ return (1);
+ }
+ }
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn_key_alloc_2pair(): "
+ " out of pair space\n"));
+
+ return (0);
+}
+/*
+ * Allocate a single key cache slot.
+ */
+static int
+arn_key_alloc_single(struct arn_softc *sc, ieee80211_keyix *txkeyix,
+ ieee80211_keyix *rxkeyix)
+{
+ uint16_t i, keyix;
+
+ /* try i,i+32,i+64,i+32+64 to minimize key pair conflicts */
+ for (i = 0; i < ARRAY_SIZE(sc->sc_keymap); i++) {
+ uint8_t b = sc->sc_keymap[i];
+
+ if (b != 0xff) {
+ /*
+ * One or more slots are free.
+ */
+ keyix = i*NBBY;
+ while (b & 1)
+ keyix++, b >>= 1;
+ set_bit(keyix, sc->sc_keymap);
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn_key_alloc_single(): "
+ "key %u\n", keyix));
+ *txkeyix = *rxkeyix = keyix;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Allocate one or more key cache slots for a unicast key. The
+ * key itself is needed only to identify the cipher. For hardware
+ * TKIP with split cipher+MIC keys we allocate two key cache slot
+ * pairs so that we can setup separate TX and RX MIC keys. Note
+ * that the MIC key for a TKIP key at slot i is assumed by the
+ * hardware to be at slot i+64. This limits TKIP keys to the first
+ * 64 entries.
+ */
+/* ARGSUSED */
+int
+arn_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k,
+ ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
+{
+ struct arn_softc *sc = (struct arn_softc *)ic;
+
+ /*
+ * We allocate two pair for TKIP when using the h/w to do
+ * the MIC. For everything else, including software crypto,
+ * we allocate a single entry. Note that s/w crypto requires
+ * a pass-through slot on the 5211 and 5212. The 5210 does
+ * not support pass-through cache entries and we map all
+ * those requests to slot 0.
+ */
+ if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
+ return (arn_key_alloc_single(sc, keyix, rxkeyix));
+ } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP &&
+ (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
+ if (sc->sc_splitmic)
+ return (arn_key_alloc_2pair(sc, keyix, rxkeyix));
+ else
+ return (arn_key_alloc_pair(sc, keyix, rxkeyix));
+ } else {
+ return (arn_key_alloc_single(sc, keyix, rxkeyix));
+ }
+}
+
+/*
+ * Delete an entry in the key cache allocated by ath_key_alloc.
+ */
+int
+arn_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k)
+{
+ struct arn_softc *sc = (struct arn_softc *)ic;
+ struct ath_hal *ah = sc->sc_ah;
+ const struct ieee80211_cipher *cip = k->wk_cipher;
+ ieee80211_keyix keyix = k->wk_keyix;
+
+ ARN_DBG((ARN_DBG_KEYCACHE, "arn_key_delete():"
+ " delete key %u ic_cipher=0x%x\n", keyix, cip->ic_cipher));
+
+ (void) ath9k_hw_keyreset(ah, keyix);
+ /*
+ * Handle split tx/rx keying required for TKIP with h/w MIC.
+ */
+ if (cip->ic_cipher == IEEE80211_CIPHER_TKIP &&
+ (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic)
+ (void) ath9k_hw_keyreset(ah, keyix+32); /* RX key */
+
+ if (keyix >= IEEE80211_WEP_NKID) {
+ /*
+ * Don't touch keymap entries for global keys so
+ * they are never considered for dynamic allocation.
+ */
+ clr_bit(keyix, sc->sc_keymap);
+ if (cip->ic_cipher == IEEE80211_CIPHER_TKIP &&
+ (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
+ /*
+ * If splitmic is true +64 is TX key MIC,
+ * else +64 is RX key + RX key MIC.
+ */
+ clr_bit(keyix+64, sc->sc_keymap);
+ if (sc->sc_splitmic) {
+ /* Rx key */
+ clr_bit(keyix+32, sc->sc_keymap);
+ /* RX key MIC */
+ clr_bit(keyix+32+64, sc->sc_keymap);
+ }
+ }
+ }
+ return (1);
+}
+
+/*
+ * Set a TKIP key into the hardware. This handles the
+ * potential distribution of key state to multiple key
+ * cache slots for TKIP.
+ */
+static int
+arn_keyset_tkip(struct arn_softc *sc, const struct ieee80211_key *k,
+ struct ath9k_keyval *hk, const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+ uint8_t *key_rxmic = NULL;
+ uint8_t *key_txmic = NULL;
+ uint8_t *key = (uint8_t *)&(k->wk_key[0]);
+ struct ath_hal *ah = sc->sc_ah;
+
+ key_txmic = key + 16;
+ key_rxmic = key + 24;
+
+ if (mac == NULL) {
+ /* Group key installation */
+ (void) memcpy(hk->kv_mic, key_rxmic, sizeof (hk->kv_mic));
+ return (ath9k_hw_set_keycache_entry(ah, k->wk_keyix, hk,
+ mac, B_FALSE));
+ }
+ if (!sc->sc_splitmic) {
+ /*
+ * data key goes at first index,
+ * the hal handles the MIC keys at index+64.
+ */
+ (void) memcpy(hk->kv_mic, key_rxmic, sizeof (hk->kv_mic));
+ (void) memcpy(hk->kv_txmic, key_txmic, sizeof (hk->kv_txmic));
+ return (ath9k_hw_set_keycache_entry(ah, k->wk_keyix, hk,
+ mac, B_FALSE));
+ }
+ /*
+ * TX key goes at first index, RX key at +32.
+ * The hal handles the MIC keys at index+64.
+ */
+ (void) memcpy(hk->kv_mic, key_txmic, sizeof (hk->kv_mic));
+ if (!(ath9k_hw_set_keycache_entry(ah, k->wk_keyix, hk, NULL,
+ B_FALSE))) {
+ /* Txmic entry failed. No need to proceed further */
+ ARN_DBG((ARN_DBG_KEYCACHE,
+ "%s Setting TX MIC Key Failed\n", __func__));
+ return (0);
+ }
+
+ (void) memcpy(hk->kv_mic, key_rxmic, sizeof (hk->kv_mic));
+
+ /* XXX delete tx key on failure? */
+ return (ath9k_hw_set_keycache_entry(ah, k->wk_keyix, hk, mac, B_FALSE));
+
+}
+
+int
+arn_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
+ const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+ struct arn_softc *sc = (struct arn_softc *)ic;
+ const struct ieee80211_cipher *cip = k->wk_cipher;
+ struct ath9k_keyval hk;
+
+ /* cipher table */
+ static const uint8_t ciphermap[] = {
+ ATH9K_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */
+ ATH9K_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */
+ ATH9K_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */
+ ATH9K_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */
+ ATH9K_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */
+ ATH9K_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */
+ };
+
+ bzero(&hk, sizeof (hk));
+
+ /*
+ * Software crypto uses a "clear key" so non-crypto
+ * state kept in the key cache are maintainedd so that
+ * rx frames have an entry to match.
+ */
+ if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) {
+ ASSERT(cip->ic_cipher < 6);
+ hk.kv_type = ciphermap[cip->ic_cipher];
+ hk.kv_len = k->wk_keylen;
+ bcopy(k->wk_key, hk.kv_val, k->wk_keylen);
+ } else {
+ hk.kv_type = ATH9K_CIPHER_CLR;
+ }
+
+ if (hk.kv_type == ATH9K_CIPHER_TKIP &&
+ (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
+ return (arn_keyset_tkip(sc, k, &hk, mac));
+ } else {
+ return (ath9k_hw_set_keycache_entry(sc->sc_ah,
+ k->wk_keyix, &hk, mac, B_FALSE));
+ }
+}
+
+/*
+ * Enable/Disable short slot timing
+ */
+void
+arn_set_shortslot(ieee80211com_t *ic, int onoff)
+{
+ struct ath_hal *ah = ((struct arn_softc *)ic)->sc_ah;
+
+ if (onoff)
+ (void) ath9k_hw_setslottime(ah, ATH9K_SLOT_TIME_9);
+ else
+ (void) ath9k_hw_setslottime(ah, ATH9K_SLOT_TIME_20);
+}
+
+static int
+arn_open(struct arn_softc *sc)
+{
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ieee80211_channel *curchan = ic->ic_curchan;
+ struct ath9k_channel *init_channel;
+ int error = 0, pos, status;
+
+ ARN_LOCK_ASSERT(sc);
+
+ pos = arn_get_channel(sc, curchan);
+ if (pos == -1) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: "
+ "%s: Invalid channel\n", __func__));
+ error = EINVAL;
+ goto error;
+ }
+
+ sc->tx_chan_width = ATH9K_HT_MACMODE_20;
+
+ if (sc->sc_curmode == ATH9K_MODE_11A) {
+ sc->sc_ah->ah_channels[pos].chanmode = CHANNEL_A;
+ } else {
+ sc->sc_ah->ah_channels[pos].chanmode = CHANNEL_G;
+ }
+
+ init_channel = &sc->sc_ah->ah_channels[pos];
+
+ /* Reset SERDES registers */
+ ath9k_hw_configpcipowersave(sc->sc_ah, 0);
+
+ /*
+ * The basic interface to setting the hardware in a good
+ * state is ``reset''. On return the hardware is known to
+ * be powered up and with interrupts disabled. This must
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+ if (!ath9k_hw_reset(sc->sc_ah, init_channel,
+ sc->tx_chan_width, sc->sc_tx_chainmask,
+ sc->sc_rx_chainmask, sc->sc_ht_extprotspacing,
+ B_FALSE, &status)) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: "
+ "%s: unable to reset hardware; hal status %u "
+ "(freq %u flags 0x%x)\n", __func__, status,
+ init_channel->channel, init_channel->channelFlags));
+
+ error = EIO;
+ goto error;
+ }
+
+ /*
+ * This is needed only to setup initial state
+ * but it's best done after a reset.
+ */
+ arn_update_txpow(sc);
+
+ /*
+ * Setup the hardware after reset:
+ * The receive engine is set going.
+ * Frame transmit is handled entirely
+ * in the frame output path; there's nothing to do
+ * here except setup the interrupt mask.
+ */
+ if (arn_startrecv(sc) != 0) {
+ ARN_DBG((ARN_DBG_INIT, "arn: "
+ "%s: unable to start recv logic\n", __func__));
+ error = EIO;
+ goto error;
+ }
+
+ /* Setup our intr mask. */
+ sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX |
+ ATH9K_INT_RXEOL | ATH9K_INT_RXORN |
+ ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
+#ifdef ARN_ATH9K_HW_CAP_GTT
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT)
+ sc->sc_imask |= ATH9K_INT_GTT;
+#endif
+
+#ifdef ARN_ATH9K_HW_CAP_GTT
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
+ sc->sc_imask |= ATH9K_INT_CST;
+#endif
+
+ /*
+ * Enable MIB interrupts when there are hardware phy counters.
+ * Note we only do this (at the moment) for station mode.
+ */
+#ifdef ARN_ATH9K_INT_MIB
+ if (ath9k_hw_phycounters(sc->sc_ah) &&
+ ((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
+ (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)))
+ sc->sc_imask |= ATH9K_INT_MIB;
+#endif
+ /*
+ * Some hardware processes the TIM IE and fires an
+ * interrupt when the TIM bit is set. For hardware
+ * that does, if not overridden by configuration,
+ * enable the TIM interrupt when operating as station.
+ */
+#ifdef ARN_ATH9K_INT_TIM
+ if ((sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
+ (sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
+ !sc->sc_config.swBeaconProcess)
+ sc->sc_imask |= ATH9K_INT_TIM;
+#endif
+ if (arn_chan2mode(init_channel) != sc->sc_curmode)
+ arn_setcurmode(sc, arn_chan2mode(init_channel));
+ ARN_DBG((ARN_DBG_INIT, "arn: "
+ "%s: current mode after arn_setcurmode is %d\n",
+ __func__, sc->sc_curmode));
+
+ sc->sc_isrunning = 1;
+
+ /* Disable BMISS interrupt when we're not associated */
+ sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+ (void) ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
+
+ return (0);
+
+error:
+ return (error);
+}
+
+static void
+arn_close(struct arn_softc *sc)
+{
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ath_hal *ah = sc->sc_ah;
+
+ ARN_LOCK_ASSERT(sc);
+
+ if (!sc->sc_isrunning)
+ return;
+
+ /*
+ * Shutdown the hardware and driver
+ * Note that some of this work is not possible if the
+ * hardware is gone (invalid).
+ */
+ ARN_UNLOCK(sc);
+ ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+ ieee80211_stop_watchdog(ic);
+ ARN_LOCK(sc);
+
+ /*
+ * make sure h/w will not generate any interrupt
+ * before setting the invalid flag.
+ */
+ (void) ath9k_hw_set_interrupts(ah, 0);
+
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ arn_draintxq(sc, 0);
+ (void) arn_stoprecv(sc);
+ (void) ath9k_hw_phy_disable(ah);
+ } else {
+ sc->sc_rxlink = NULL;
+ }
+
+ sc->sc_isrunning = 0;
+}
+
+/*
+ * MAC callback functions
+ */
+static int
+arn_m_stat(void *arg, uint_t stat, uint64_t *val)
+{
+ struct arn_softc *sc = arg;
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ieee80211_node *in;
+ struct ieee80211_rateset *rs;
+
+ ARN_LOCK(sc);
+ switch (stat) {
+ case MAC_STAT_IFSPEED:
+ in = ic->ic_bss;
+ rs = &in->in_rates;
+ *val = (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2 *
+ 1000000ull;
+ break;
+ case MAC_STAT_NOXMTBUF:
+ *val = sc->sc_stats.ast_tx_nobuf +
+ sc->sc_stats.ast_tx_nobufmgt;
+ break;
+ case MAC_STAT_IERRORS:
+ *val = sc->sc_stats.ast_rx_tooshort;
+ break;
+ case MAC_STAT_RBYTES:
+ *val = ic->ic_stats.is_rx_bytes;
+ break;
+ case MAC_STAT_IPACKETS:
+ *val = ic->ic_stats.is_rx_frags;
+ break;
+ case MAC_STAT_OBYTES:
+ *val = ic->ic_stats.is_tx_bytes;
+ break;
+ case MAC_STAT_OPACKETS:
+ *val = ic->ic_stats.is_tx_frags;
+ break;
+ case MAC_STAT_OERRORS:
+ case WIFI_STAT_TX_FAILED:
+ *val = sc->sc_stats.ast_tx_fifoerr +
+ sc->sc_stats.ast_tx_xretries +
+ sc->sc_stats.ast_tx_discard;
+ break;
+ case WIFI_STAT_TX_RETRANS:
+ *val = sc->sc_stats.ast_tx_xretries;
+ break;
+ case WIFI_STAT_FCS_ERRORS:
+ *val = sc->sc_stats.ast_rx_crcerr;
+ break;
+ case WIFI_STAT_WEP_ERRORS:
+ *val = sc->sc_stats.ast_rx_badcrypt;
+ break;
+ case WIFI_STAT_TX_FRAGS:
+ case WIFI_STAT_MCAST_TX:
+ case WIFI_STAT_RTS_SUCCESS:
+ case WIFI_STAT_RTS_FAILURE:
+ case WIFI_STAT_ACK_FAILURE:
+ case WIFI_STAT_RX_FRAGS:
+ case WIFI_STAT_MCAST_RX:
+ case WIFI_STAT_RX_DUPS:
+ ARN_UNLOCK(sc);
+ return (ieee80211_stat(ic, stat, val));
+ default:
+ ARN_UNLOCK(sc);
+ return (ENOTSUP);
+ }
+ ARN_UNLOCK(sc);
+
+ return (0);
+}
+
+int
+arn_m_start(void *arg)
+{
+ struct arn_softc *sc = arg;
+ int err = 0;
+
+ ARN_LOCK(sc);
+
+ /*
+ * Stop anything previously setup. This is safe
+ * whether this is the first time through or not.
+ */
+
+ arn_close(sc);
+
+ if ((err = arn_open(sc)) != 0) {
+ ARN_UNLOCK(sc);
+ return (err);
+ }
+
+ /* H/W is reday now */
+ sc->sc_flags &= ~SC_OP_INVALID;
+
+ ARN_UNLOCK(sc);
+
+ return (0);
+}
+
+static void
+arn_m_stop(void *arg)
+{
+ struct arn_softc *sc = arg;
+
+ ARN_LOCK(sc);
+ arn_close(sc);
+
+ /* disable HAL and put h/w to sleep */
+ (void) ath9k_hw_disable(sc->sc_ah);
+ ath9k_hw_configpcipowersave(sc->sc_ah, 1);
+
+ /* XXX: hardware will not be ready in suspend state */
+ sc->sc_flags |= SC_OP_INVALID;
+ ARN_UNLOCK(sc);
+}
+
+static int
+arn_m_promisc(void *arg, boolean_t on)
+{
+ struct arn_softc *sc = arg;
+ struct ath_hal *ah = sc->sc_ah;
+ uint32_t rfilt;
+
+ ARN_LOCK(sc);
+
+ rfilt = ath9k_hw_getrxfilter(ah);
+ if (on)
+ rfilt |= ATH9K_RX_FILTER_PROM;
+ else
+ rfilt &= ~ATH9K_RX_FILTER_PROM;
+ sc->sc_promisc = on;
+ ath9k_hw_setrxfilter(ah, rfilt);
+
+ ARN_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+arn_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
+{
+ struct arn_softc *sc = arg;
+ struct ath_hal *ah = sc->sc_ah;
+ uint32_t val, index, bit;
+ uint8_t pos;
+ uint32_t *mfilt = sc->sc_mcast_hash;
+
+ ARN_LOCK(sc);
+
+ /* calculate XOR of eight 6bit values */
+ val = ARN_LE_READ_32(mca + 0);
+ pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+ val = ARN_LE_READ_32(mca + 3);
+ pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+ pos &= 0x3f;
+ index = pos / 32;
+ bit = 1 << (pos % 32);
+
+ if (add) { /* enable multicast */
+ sc->sc_mcast_refs[pos]++;
+ mfilt[index] |= bit;
+ } else { /* disable multicast */
+ if (--sc->sc_mcast_refs[pos] == 0)
+ mfilt[index] &= ~bit;
+ }
+ ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
+
+ ARN_UNLOCK(sc);
+ return (0);
+}
+
+static int
+arn_m_unicst(void *arg, const uint8_t *macaddr)
+{
+ struct arn_softc *sc = arg;
+ struct ath_hal *ah = sc->sc_ah;
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+
+ ARN_DBG((ARN_DBG_XMIT, "ath: ath_gld_saddr(): "
+ "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ macaddr[0], macaddr[1], macaddr[2],
+ macaddr[3], macaddr[4], macaddr[5]));
+
+ ARN_LOCK(sc);
+ IEEE80211_ADDR_COPY(sc->sc_isc.ic_macaddr, macaddr);
+ (void) ath9k_hw_setmac(ah, sc->sc_isc.ic_macaddr);
+ (void) arn_reset(ic);
+ ARN_UNLOCK(sc);
+ return (0);
+}
+
+static mblk_t *
+arn_m_tx(void *arg, mblk_t *mp)
+{
+ struct arn_softc *sc = arg;
+ int error = 0;
+ mblk_t *next;
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+
+ /*
+ * No data frames go out unless we're associated; this
+ * should not happen as the 802.11 layer does not enable
+ * the xmit queue until we enter the RUN state.
+ */
+ if (ic->ic_state != IEEE80211_S_RUN) {
+ ARN_DBG((ARN_DBG_XMIT, "arn: arn_m_tx(): "
+ "discard, state %u\n", ic->ic_state));
+ sc->sc_stats.ast_tx_discard++;
+ freemsgchain(mp);
+ return (NULL);
+ }
+
+ while (mp != NULL) {
+ next = mp->b_next;
+ mp->b_next = NULL;
+ error = arn_tx(ic, mp, IEEE80211_FC0_TYPE_DATA);
+ if (error != 0) {
+ mp->b_next = next;
+ if (error == ENOMEM) {
+ break;
+ } else {
+ freemsgchain(mp);
+ return (NULL);
+ }
+ }
+ mp = next;
+ }
+
+ return (mp);
+}
+
+static void
+arn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
+{
+ struct arn_softc *sc = arg;
+ int32_t err;
+
+ err = ieee80211_ioctl(&sc->sc_isc, wq, mp);
+
+ ARN_LOCK(sc);
+ if (err == ENETRESET) {
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ ARN_UNLOCK(sc);
+
+ (void) arn_m_start(sc);
+
+ (void) ieee80211_new_state(&sc->sc_isc,
+ IEEE80211_S_SCAN, -1);
+ ARN_LOCK(sc);
+ }
+ }
+ ARN_UNLOCK(sc);
+}
+
+static int
+arn_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
+ uint_t wldp_length, const void *wldp_buf)
+{
+ struct arn_softc *sc = arg;
+ int err;
+
+ err = ieee80211_setprop(&sc->sc_isc, pr_name, wldp_pr_num,
+ wldp_length, wldp_buf);
+
+ ARN_LOCK(sc);
+
+ if (err == ENETRESET) {
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ ARN_UNLOCK(sc);
+ (void) arn_m_start(sc);
+ (void) ieee80211_new_state(&sc->sc_isc,
+ IEEE80211_S_SCAN, -1);
+ ARN_LOCK(sc);
+ }
+ err = 0;
+ }
+
+ ARN_UNLOCK(sc);
+
+ return (err);
+}
+
+/* ARGSUSED */
+static int
+arn_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
+ uint_t pr_flags, uint_t wldp_length, void *wldp_buf, uint_t *perm)
+{
+ struct arn_softc *sc = arg;
+ int err = 0;
+
+ err = ieee80211_getprop(&sc->sc_isc, pr_name, wldp_pr_num,
+ pr_flags, wldp_length, wldp_buf, perm);
+
+ return (err);
+}
+
+/* return bus cachesize in 4B word units */
+static void
+arn_pci_config_cachesize(struct arn_softc *sc)
+{
+ uint8_t csz;
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ csz = pci_config_get8(sc->sc_cfg_handle, PCI_CONF_CACHE_LINESZ);
+ if (csz == 0) {
+ /*
+ * We must have this setup properly for rx buffer
+ * DMA to work so force a reasonable value here if it
+ * comes up zero.
+ */
+ csz = ATH_DEF_CACHE_BYTES / sizeof (uint32_t);
+ pci_config_put8(sc->sc_cfg_handle, PCI_CONF_CACHE_LINESZ,
+ csz);
+ }
+ sc->sc_cachelsz = csz << 2;
+}
+
+static int
+arn_pci_setup(struct arn_softc *sc)
+{
+ uint16_t command;
+
+ /*
+ * Enable memory mapping and bus mastering
+ */
+ ASSERT(sc != NULL);
+ command = pci_config_get16(sc->sc_cfg_handle, PCI_CONF_COMM);
+ command |= PCI_COMM_MAE | PCI_COMM_ME;
+ pci_config_put16(sc->sc_cfg_handle, PCI_CONF_COMM, command);
+ command = pci_config_get16(sc->sc_cfg_handle, PCI_CONF_COMM);
+ if ((command & PCI_COMM_MAE) == 0) {
+ arn_problem("arn: arn_pci_setup(): "
+ "failed to enable memory mapping\n");
+ return (EIO);
+ }
+ if ((command & PCI_COMM_ME) == 0) {
+ arn_problem("arn: arn_pci_setup(): "
+ "failed to enable bus mastering\n");
+ return (EIO);
+ }
+ ARN_DBG((ARN_DBG_INIT, "arn: arn_pci_setup(): "
+ "set command reg to 0x%x \n", command));
+
+ return (0);
+}
+
+static void
+arn_get_hw_encap(struct arn_softc *sc)
+{
+ ieee80211com_t *ic;
+ struct ath_hal *ah;
+
+ ic = (ieee80211com_t *)sc;
+ ah = sc->sc_ah;
+
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_AES_CCM, NULL))
+ ic->ic_caps |= IEEE80211_C_AES_CCM;
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_AES_OCB, NULL))
+ ic->ic_caps |= IEEE80211_C_AES;
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_TKIP, NULL))
+ ic->ic_caps |= IEEE80211_C_TKIP;
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_WEP, NULL))
+ ic->ic_caps |= IEEE80211_C_WEP;
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_MIC, NULL))
+ ic->ic_caps |= IEEE80211_C_TKIPMIC;
+}
+
+static int
+arn_resume(dev_info_t *devinfo)
+{
+ struct arn_softc *sc;
+ int ret = DDI_SUCCESS;
+
+ sc = ddi_get_soft_state(arn_soft_state_p, ddi_get_instance(devinfo));
+ if (sc == NULL) {
+ ARN_DBG((ARN_DBG_INIT, "ath: ath_resume(): "
+ "failed to get soft state\n"));
+ return (DDI_FAILURE);
+ }
+
+ ARN_LOCK(sc);
+ /*
+ * Set up config space command register(s). Refuse
+ * to resume on failure.
+ */
+ if (arn_pci_setup(sc) != 0) {
+ ARN_DBG((ARN_DBG_INIT, "ath: ath_resume(): "
+ "ath_pci_setup() failed\n"));
+ ARN_UNLOCK(sc);
+ return (DDI_FAILURE);
+ }
+
+ if (!(sc->sc_flags & SC_OP_INVALID))
+ ret = arn_open(sc);
+ ARN_UNLOCK(sc);
+
+ return (ret);
+}
+
+static int
+arn_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
+{
+ struct arn_softc *sc;
+ int instance;
+ int status;
+ int32_t err;
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint32_t i;
+ uint32_t val;
+ char strbuf[32];
+ ieee80211com_t *ic;
+ struct ath_hal *ah;
+ wifi_data_t wd = { 0 };
+ mac_register_t *macp;
+
+ switch (cmd) {
+ case DDI_ATTACH:
+ break;
+ case DDI_RESUME:
+ return (arn_resume(devinfo));
+ default:
+ return (DDI_FAILURE);
+ }
+
+ instance = ddi_get_instance(devinfo);
+ if (ddi_soft_state_zalloc(arn_soft_state_p, instance) != DDI_SUCCESS) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: "
+ "%s: Unable to alloc softstate\n", __func__));
+ return (DDI_FAILURE);
+ }
+
+ sc = ddi_get_soft_state(arn_soft_state_p, ddi_get_instance(devinfo));
+ ic = (ieee80211com_t *)sc;
+ sc->sc_dev = devinfo;
+
+ mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&sc->sc_serial_rw, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&sc->sc_txbuflock, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&sc->sc_rxbuflock, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&sc->sc_resched_lock, NULL, MUTEX_DRIVER, NULL);
+#ifdef ARN_IBSS
+ mutex_init(&sc->sc_bcbuflock, NULL, MUTEX_DRIVER, NULL);
+#endif
+
+ sc->sc_flags |= SC_OP_INVALID;
+
+ err = pci_config_setup(devinfo, &sc->sc_cfg_handle);
+ if (err != DDI_SUCCESS) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "pci_config_setup() failed"));
+ goto attach_fail0;
+ }
+
+ if (arn_pci_setup(sc) != 0)
+ goto attach_fail1;
+
+ /* Cache line size set up */
+ arn_pci_config_cachesize(sc);
+
+ vendor_id = pci_config_get16(sc->sc_cfg_handle, PCI_CONF_VENID);
+ device_id = pci_config_get16(sc->sc_cfg_handle, PCI_CONF_DEVID);
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): vendor 0x%x, "
+ "device id 0x%x, cache size %d\n",
+ vendor_id, device_id,
+ pci_config_get8(sc->sc_cfg_handle, PCI_CONF_CACHE_LINESZ)));
+
+ pci_config_put8(sc->sc_cfg_handle, PCI_CONF_LATENCY_TIMER, 0xa8);
+ val = pci_config_get32(sc->sc_cfg_handle, 0x40);
+ if ((val & 0x0000ff00) != 0)
+ pci_config_put32(sc->sc_cfg_handle, 0x40, val & 0xffff00ff);
+
+ err = ddi_regs_map_setup(devinfo, 1,
+ &sc->mem, 0, 0, &arn_reg_accattr, &sc->sc_io_handle);
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "regs map1 = %x err=%d\n", sc->mem, err));
+ if (err != DDI_SUCCESS) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "ddi_regs_map_setup() failed"));
+ goto attach_fail1;
+ }
+
+ ah = ath9k_hw_attach(device_id, sc, sc->mem, &status);
+ if (ah == NULL) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "unable to attach hw: H/W status %u\n",
+ status));
+ goto attach_fail2;
+ }
+ sc->sc_ah = ah;
+
+ ath9k_hw_getmac(ah, ic->ic_macaddr);
+
+ /* Get the hardware key cache size. */
+ sc->sc_keymax = ah->ah_caps.keycache_size;
+ if (sc->sc_keymax > ATH_KEYMAX) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "Warning, using only %u entries in %u key cache\n",
+ ATH_KEYMAX, sc->sc_keymax));
+ sc->sc_keymax = ATH_KEYMAX;
+ }
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up.
+ */
+ for (i = 0; i < sc->sc_keymax; i++)
+ (void) ath9k_hw_keyreset(ah, (uint16_t)i);
+ /*
+ * Mark key cache slots associated with global keys
+ * as in use. If we knew TKIP was not to be used we
+ * could leave the +32, +64, and +32+64 slots free.
+ * XXX only for splitmic.
+ */
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ set_bit(i, sc->sc_keymap);
+ set_bit(i + 32, sc->sc_keymap);
+ set_bit(i + 64, sc->sc_keymap);
+ set_bit(i + 32 + 64, sc->sc_keymap);
+ }
+
+ /* Collect the channel list using the default country code */
+ err = arn_setup_channels(sc);
+ if (err == EINVAL) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "ERR:arn_setup_channels\n"));
+ goto attach_fail3;
+ }
+
+ /* default to STA mode */
+ sc->sc_ah->ah_opmode = ATH9K_M_STA;
+
+ /* Setup rate tables */
+ arn_rate_attach(sc);
+ arn_setup_rates(sc, IEEE80211_MODE_11A);
+ arn_setup_rates(sc, IEEE80211_MODE_11B);
+ arn_setup_rates(sc, IEEE80211_MODE_11G);
+
+ /* Setup current mode here */
+ arn_setcurmode(sc, ATH9K_MODE_11G);
+
+ /* 802.11g features */
+ if (sc->sc_have11g)
+ ic->ic_caps |= IEEE80211_C_SHPREAMBLE |
+ IEEE80211_C_SHSLOT; /* short slot time */
+
+ /* temp workaround */
+ sc->sc_mrretry = 1;
+
+ /* Setup tx/rx descriptors */
+ err = arn_desc_alloc(devinfo, sc);
+ if (err != DDI_SUCCESS) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "failed to allocate descriptors: %d\n", err));
+ goto attach_fail3;
+ }
+
+ if ((sc->sc_tq = ddi_taskq_create(devinfo, "ath_taskq", 1,
+ TASKQ_DEFAULTPRI, 0)) == NULL) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "ERR:ddi_taskq_create\n"));
+ goto attach_fail4;
+ }
+
+ /*
+ * Allocate hardware transmit queues: one queue for
+ * beacon frames and one data queue for each QoS
+ * priority. Note that the hal handles reseting
+ * these queues at the needed time.
+ */
+#ifdef ARN_IBSS
+ sc->sc_beaconq = arn_beaconq_setup(ah);
+ if (sc->sc_beaconq == (-1)) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "unable to setup a beacon xmit queue\n"));
+ goto attach_fail4;
+ }
+#endif
+#ifdef ARN_HOSTAP
+ sc->sc_cabq = arn_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
+ if (sc->sc_cabq == NULL) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "unable to setup CAB xmit queue\n"));
+ goto attach_fail4;
+ }
+
+ sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME;
+ ath_cabq_update(sc);
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++)
+ sc->sc_haltype2q[i] = -1;
+
+ /* Setup data queues */
+ /* NB: ensure BK queue is the lowest priority h/w queue */
+ if (!arn_tx_setup(sc, ATH9K_WME_AC_BK)) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "unable to setup xmit queue for BK traffic\n"));
+ goto attach_fail4;
+ }
+ if (!arn_tx_setup(sc, ATH9K_WME_AC_BE)) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "unable to setup xmit queue for BE traffic\n"));
+ goto attach_fail4;
+ }
+ if (!arn_tx_setup(sc, ATH9K_WME_AC_VI)) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "unable to setup xmit queue for VI traffic\n"));
+ goto attach_fail4;
+ }
+ if (!arn_tx_setup(sc, ATH9K_WME_AC_VO)) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "unable to setup xmit queue for VO traffic\n"));
+ goto attach_fail4;
+ }
+
+ /*
+ * Initializes the noise floor to a reasonable default value.
+ * Later on this will be updated during ANI processing.
+ */
+
+ sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
+
+
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_TKIP, NULL)) {
+ /*
+ * Whether we should enable h/w TKIP MIC.
+ * XXX: if we don't support WME TKIP MIC, then we wouldn't
+ * report WMM capable, so it's always safe to turn on
+ * TKIP MIC in this case.
+ */
+ (void) ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
+ 0, 1, NULL);
+ }
+
+ /* Get cipher releated capability information */
+ arn_get_hw_encap(sc);
+
+ /*
+ * Check whether the separate key cache entries
+ * are required to handle both tx+rx MIC keys.
+ * With split mic keys the number of stations is limited
+ * to 27 otherwise 59.
+ */
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_TKIP, NULL) &&
+ ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_MIC, NULL) &&
+ ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
+ 0, NULL))
+ sc->sc_splitmic = 1;
+
+ /* turn on mcast key search if possible */
+ if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
+ (void) ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
+ 1, NULL);
+
+ sc->sc_config.txpowlimit = ATH_TXPOWER_MAX;
+ sc->sc_config.txpowlimit_override = 0;
+
+#ifdef ARN_11N
+ /* 11n Capabilities */
+ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
+ sc->sc_flags |= SC_OP_TXAGGR;
+ sc->sc_flags |= SC_OP_RXAGGR;
+ }
+#endif
+
+#ifdef ARN_11N
+ sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
+ sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
+#else
+ sc->sc_tx_chainmask = 1;
+ sc->sc_rx_chainmask = 1;
+#endif
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "tx_chainmask = %d, rx_chainmask = %d\n",
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask));
+
+ (void) ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, B_TRUE, NULL);
+ sc->sc_defant = ath9k_hw_getdefantenna(ah);
+
+ ath9k_hw_getmac(ah, sc->sc_myaddr);
+ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) {
+ ath9k_hw_getbssidmask(ah, sc->sc_bssidmask);
+ ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask);
+ (void) ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
+ }
+
+ /* set default value to short slot time */
+ sc->sc_slottime = ATH9K_SLOT_TIME_9;
+ (void) ath9k_hw_setslottime(ah, ATH9K_SLOT_TIME_9);
+
+ /* initialize beacon slots */
+ for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++)
+ sc->sc_bslot[i] = ATH_IF_ID_ANY;
+
+ /* save MISC configurations */
+ sc->sc_config.swBeaconProcess = 1;
+
+
+ ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */
+ ic->ic_phytype = IEEE80211_T_OFDM;
+ ic->ic_opmode = IEEE80211_M_STA;
+ ic->ic_state = IEEE80211_S_INIT;
+ ic->ic_maxrssi = ARN_MAX_RSSI;
+ ic->ic_set_shortslot = arn_set_shortslot;
+ ic->ic_xmit = arn_tx;
+ ieee80211_attach(ic);
+
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "ic->ic_curchan->ich_freq: %d\n", ic->ic_curchan->ich_freq));
+
+ /* different instance has different WPA door */
+ (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR,
+ ddi_driver_name(devinfo),
+ ddi_get_instance(devinfo));
+
+ /* Override 80211 default routines */
+ ic->ic_reset = arn_reset;
+ sc->sc_newstate = ic->ic_newstate;
+ ic->ic_newstate = arn_newstate;
+#ifdef ARN_IBSS
+ sc->sc_recv_mgmt = ic->ic_recv_mgmt;
+ ic->ic_recv_mgmt = arn_recv_mgmt;
+#endif
+ ic->ic_watchdog = arn_watchdog;
+ ic->ic_node_alloc = arn_node_alloc;
+ ic->ic_node_free = arn_node_free;
+ ic->ic_crypto.cs_key_alloc = arn_key_alloc;
+ ic->ic_crypto.cs_key_delete = arn_key_delete;
+ ic->ic_crypto.cs_key_set = arn_key_set;
+
+ ieee80211_media_init(ic);
+
+ /*
+ * initialize default tx key
+ */
+ ic->ic_def_txkey = 0;
+
+ sc->sc_rx_pend = 0;
+ (void) ath9k_hw_set_interrupts(sc->sc_ah, 0);
+ err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW,
+ &sc->sc_softint_id, NULL, 0, arn_softint_handler, (caddr_t)sc);
+ if (err != DDI_SUCCESS) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "ddi_add_softintr() failed....\n"));
+ goto attach_fail5;
+ }
+
+ if (ddi_get_iblock_cookie(devinfo, 0, &sc->sc_iblock)
+ != DDI_SUCCESS) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "Can not get iblock cookie for INT\n"));
+ goto attach_fail6;
+ }
+
+ if (ddi_add_intr(devinfo, 0, NULL, NULL, arn_isr,
+ (caddr_t)sc) != DDI_SUCCESS) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "Can not set intr for ARN driver\n"));
+ goto attach_fail6;
+ }
+
+ /*
+ * Provide initial settings for the WiFi plugin; whenever this
+ * information changes, we need to call mac_plugindata_update()
+ */
+ wd.wd_opmode = ic->ic_opmode;
+ wd.wd_secalloc = WIFI_SEC_NONE;
+ IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
+
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid)"
+ "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ wd.wd_bssid[0], wd.wd_bssid[1], wd.wd_bssid[2],
+ wd.wd_bssid[3], wd.wd_bssid[4], wd.wd_bssid[5]));
+
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "MAC version mismatch\n"));
+ goto attach_fail7;
+ }
+
+ macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
+ macp->m_driver = sc;
+ macp->m_dip = devinfo;
+ macp->m_src_addr = ic->ic_macaddr;
+ macp->m_callbacks = &arn_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = IEEE80211_MTU;
+ macp->m_pdata = &wd;
+ macp->m_pdata_size = sizeof (wd);
+
+ err = mac_register(macp, &ic->ic_mach);
+ mac_free(macp);
+ if (err != 0) {
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "mac_register err %x\n", err));
+ goto attach_fail7;
+ }
+
+ /* Create minor node of type DDI_NT_NET_WIFI */
+ (void) snprintf(strbuf, sizeof (strbuf), "%s%d",
+ ARN_NODENAME, instance);
+ err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
+ instance + 1, DDI_NT_NET_WIFI, 0);
+ if (err != DDI_SUCCESS)
+ ARN_DBG((ARN_DBG_ATTACH, "WARN: arn: arn_attach(): "
+ "Create minor node failed - %d\n", err));
+
+ mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
+
+ sc->sc_promisc = B_FALSE;
+ bzero(sc->sc_mcast_refs, sizeof (sc->sc_mcast_refs));
+ bzero(sc->sc_mcast_hash, sizeof (sc->sc_mcast_hash));
+
+ ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): "
+ "Atheros AR%s MAC/BB Rev:%x "
+ "AR%s RF Rev:%x: mem=0x%lx\n",
+ arn_mac_bb_name(ah->ah_macVersion),
+ ah->ah_macRev,
+ arn_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)),
+ ah->ah_phyRev,
+ (unsigned long)sc->mem));
+
+ /* XXX: hardware will not be ready until arn_open() being called */
+ sc->sc_flags |= SC_OP_INVALID;
+ sc->sc_isrunning = 0;
+
+ return (DDI_SUCCESS);
+
+attach_fail7:
+ ddi_remove_intr(devinfo, 0, sc->sc_iblock);
+attach_fail6:
+ ddi_remove_softintr(sc->sc_softint_id);
+attach_fail5:
+ (void) ieee80211_detach(ic);
+attach_fail4:
+ arn_desc_free(sc);
+ if (sc->sc_tq)
+ ddi_taskq_destroy(sc->sc_tq);
+attach_fail3:
+ ath9k_hw_detach(ah);
+attach_fail2:
+ ddi_regs_map_free(&sc->sc_io_handle);
+attach_fail1:
+ pci_config_teardown(&sc->sc_cfg_handle);
+attach_fail0:
+ sc->sc_flags |= SC_OP_INVALID;
+ /* cleanup tx queues */
+ mutex_destroy(&sc->sc_txbuflock);
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ARN_TXQ_SETUP(sc, i)) {
+ /* arn_tx_cleanupq(asc, &asc->sc_txq[i]); */
+ mutex_destroy(&((&sc->sc_txq[i])->axq_lock));
+ }
+ }
+ mutex_destroy(&sc->sc_rxbuflock);
+ mutex_destroy(&sc->sc_serial_rw);
+ mutex_destroy(&sc->sc_genlock);
+ mutex_destroy(&sc->sc_resched_lock);
+#ifdef ARN_IBSS
+ mutex_destroy(&sc->sc_bcbuflock);
+#endif
+
+ ddi_soft_state_free(arn_soft_state_p, instance);
+
+ return (DDI_FAILURE);
+
+}
+
+/*
+ * Suspend transmit/receive for powerdown
+ */
+static int
+arn_suspend(struct arn_softc *sc)
+{
+ ARN_LOCK(sc);
+ arn_close(sc);
+ ARN_UNLOCK(sc);
+
+ return (DDI_SUCCESS);
+}
+
+static int32_t
+arn_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
+{
+ struct arn_softc *sc;
+ int i;
+
+ sc = ddi_get_soft_state(arn_soft_state_p, ddi_get_instance(devinfo));
+ ASSERT(sc != NULL);
+
+ switch (cmd) {
+ case DDI_DETACH:
+ break;
+
+ case DDI_SUSPEND:
+ return (arn_suspend(sc));
+
+ default:
+ return (DDI_FAILURE);
+ }
+
+ if (mac_disable(sc->sc_isc.ic_mach) != 0)
+ return (DDI_FAILURE);
+
+ arn_stop_scantimer(sc);
+ arn_stop_caltimer(sc);
+
+ /* disable interrupts */
+ (void) ath9k_hw_set_interrupts(sc->sc_ah, 0);
+
+ /*
+ * Unregister from the MAC layer subsystem
+ */
+ (void) mac_unregister(sc->sc_isc.ic_mach);
+
+ /* free intterrupt resources */
+ ddi_remove_intr(devinfo, 0, sc->sc_iblock);
+ ddi_remove_softintr(sc->sc_softint_id);
+
+ /*
+ * NB: the order of these is important:
+ * o call the 802.11 layer before detaching the hal to
+ * insure callbacks into the driver to delete global
+ * key cache entries can be handled
+ * o reclaim the tx queue data structures after calling
+ * the 802.11 layer as we'll get called back to reclaim
+ * node state and potentially want to use them
+ * o to cleanup the tx queues the hal is called, so detach
+ * it last
+ */
+ ieee80211_detach(&sc->sc_isc);
+
+ arn_desc_free(sc);
+
+ ddi_taskq_destroy(sc->sc_tq);
+
+ if (!(sc->sc_flags & SC_OP_INVALID))
+ (void) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+
+ /* cleanup tx queues */
+ mutex_destroy(&sc->sc_txbuflock);
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ARN_TXQ_SETUP(sc, i)) {
+ arn_tx_cleanupq(sc, &sc->sc_txq[i]);
+ mutex_destroy(&((&sc->sc_txq[i])->axq_lock));
+ }
+ }
+
+ ath9k_hw_detach(sc->sc_ah);
+
+ /* free io handle */
+ ddi_regs_map_free(&sc->sc_io_handle);
+ pci_config_teardown(&sc->sc_cfg_handle);
+
+ /* destroy locks */
+ mutex_destroy(&sc->sc_genlock);
+ mutex_destroy(&sc->sc_serial_rw);
+ mutex_destroy(&sc->sc_rxbuflock);
+ mutex_destroy(&sc->sc_resched_lock);
+#ifdef ARN_IBSS
+ mutex_destroy(&sc->sc_bcbuflock);
+#endif
+
+ ddi_remove_minor_node(devinfo, NULL);
+ ddi_soft_state_free(arn_soft_state_p, ddi_get_instance(devinfo));
+
+ return (DDI_SUCCESS);
+}
+
+/*
+ * quiesce(9E) entry point.
+ *
+ * This function is called when the system is single-threaded at high
+ * PIL with preemption disabled. Therefore, this function must not be
+ * blocked.
+ *
+ * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
+ * DDI_FAILURE indicates an error condition and should almost never happen.
+ */
+static int32_t
+arn_quiesce(dev_info_t *devinfo)
+{
+ struct arn_softc *sc;
+ int i;
+ struct ath_hal *ah;
+
+ sc = ddi_get_soft_state(arn_soft_state_p, ddi_get_instance(devinfo));
+
+ if (sc == NULL || (ah = sc->sc_ah) == NULL)
+ return (DDI_FAILURE);
+
+ /*
+ * Disable interrupts
+ */
+ (void) ath9k_hw_set_interrupts(ah, 0);
+
+ /*
+ * Disable TX HW
+ */
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ARN_TXQ_SETUP(sc, i))
+ (void) ath9k_hw_stoptxdma(ah, sc->sc_txq[i].axq_qnum);
+ }
+
+ /*
+ * Disable RX HW
+ */
+ ath9k_hw_stoppcurecv(ah);
+ ath9k_hw_setrxfilter(ah, 0);
+ (void) ath9k_hw_stopdmarecv(ah);
+ drv_usecwait(3000);
+
+ /*
+ * Power down HW
+ */
+ (void) ath9k_hw_phy_disable(ah);
+
+ return (DDI_SUCCESS);
+}
+
+DDI_DEFINE_STREAM_OPS(arn_dev_ops, nulldev, nulldev, arn_attach, arn_detach,
+ nodev, NULL, D_MP, NULL, arn_quiesce);
+
+static struct modldrv arn_modldrv = {
+ &mod_driverops, /* Type of module. This one is a driver */
+ "arn-Atheros 9000 series driver:vertion 1.1", /* short description */
+ &arn_dev_ops /* driver specific ops */
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1, (void *)&arn_modldrv, NULL
+};
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
+}
+
+int
+_init(void)
+{
+ int status;
+
+ status = ddi_soft_state_init
+ (&arn_soft_state_p, sizeof (struct arn_softc), 1);
+ if (status != 0)
+ return (status);
+
+ mutex_init(&arn_loglock, NULL, MUTEX_DRIVER, NULL);
+ mac_init_ops(&arn_dev_ops, "arn");
+ status = mod_install(&modlinkage);
+ if (status != 0) {
+ mac_fini_ops(&arn_dev_ops);
+ mutex_destroy(&arn_loglock);
+ ddi_soft_state_fini(&arn_soft_state_p);
+ }
+
+ return (status);
+}
+
+int
+_fini(void)
+{
+ int status;
+
+ status = mod_remove(&modlinkage);
+ if (status == 0) {
+ mac_fini_ops(&arn_dev_ops);
+ mutex_destroy(&arn_loglock);
+ ddi_soft_state_fini(&arn_soft_state_p);
+ }
+ return (status);
+}
diff --git a/usr/src/uts/common/io/arn/arn_phy.c b/usr/src/uts/common/io/arn/arn_phy.c
new file mode 100644
index 0000000000..467c43cd0d
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_phy.c
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include "arn_core.h"
+#include "arn_hw.h"
+#include "arn_reg.h"
+#include "arn_phy.h"
+
+/* ARGSUSED */
+void
+ath9k_hw_write_regs(struct ath_hal *ah, uint32_t modesIndex, uint32_t freqIndex,
+ int regWrites)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ /* LINTED: E_CONSTANT_CONDITION */
+ REG_WRITE_ARRAY(&ahp->ah_iniBB_RfGain, freqIndex, regWrites);
+}
+
+boolean_t
+ath9k_hw_set_channel(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ uint32_t channelSel = 0;
+ uint32_t bModeSynth = 0;
+ uint32_t aModeRefSel = 0;
+ uint32_t reg32 = 0;
+ uint16_t freq;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(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 {
+ arn_problem("%s: invalid channel %u MHz\n",
+ __func__, freq);
+ return (B_FALSE);
+ }
+
+ channelSel = (channelSel << 2) & 0xff;
+ channelSel = ath9k_hw_reverse_bits(channelSel, 8);
+
+ txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+ if (freq == 2484) {
+
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+ } else {
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+ }
+
+ } else if ((freq % 20) == 0 && freq >= 5120) {
+ channelSel =
+ ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else if ((freq % 10) == 0) {
+ channelSel =
+ ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
+ aModeRefSel = ath9k_hw_reverse_bits(2, 2);
+ else
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else if ((freq % 5) == 0) {
+ channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else {
+ arn_problem("%s: invalid channel %u MHz\n", __func__, freq);
+ return (B_FALSE);
+ }
+
+ reg32 =
+ (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
+ (1 << 5) | 0x1;
+
+ REG_WRITE(ah, AR_PHY(0x37), reg32);
+
+ ah->ah_curchan = chan;
+
+ AH5416(ah)->ah_curchanRadIndex = -1;
+
+ return (B_TRUE);
+}
+
+boolean_t
+ath9k_hw_ar9280_set_channel(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ uint16_t bMode, fracMode, aModeRefSel = 0;
+ uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
+ struct chan_centers centers;
+ uint32_t refDivA = 24;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
+ reg32 &= 0xc0000000;
+
+ if (freq < 4800) {
+ uint32_t txctl;
+
+ bMode = 1;
+ fracMode = 1;
+ aModeRefSel = 0;
+ channelSel = (freq * 0x10000) / 15;
+
+ txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+ if (freq == 2484) {
+
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+ } else {
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+ }
+ } else {
+ bMode = 0;
+ fracMode = 0;
+
+ if ((freq % 20) == 0) {
+ aModeRefSel = 3;
+ } else if ((freq % 10) == 0) {
+ aModeRefSel = 2;
+ } else {
+ aModeRefSel = 0;
+
+ fracMode = 1;
+ refDivA = 1;
+ channelSel = (freq * 0x8000) / 15;
+
+ REG_RMW_FIELD(ah, AR_AN_SYNTH9,
+ AR_AN_SYNTH9_REFDIVA, refDivA);
+ }
+ if (!fracMode) {
+ ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
+ channelSel = ndiv & 0x1ff;
+ channelFrac = (ndiv & 0xfffffe00) * 2;
+ channelSel = (channelSel << 17) | channelFrac;
+ }
+ }
+
+ reg32 = reg32 |
+ (bMode << 29) |
+ (fracMode << 28) | (aModeRefSel << 26) | (channelSel);
+
+ REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
+
+ ah->ah_curchan = chan;
+
+ AH5416(ah)->ah_curchanRadIndex = -1;
+
+ return (B_TRUE);
+}
+
+static void
+ath9k_phy_modify_rx_buffer(uint32_t *rfBuf, uint32_t reg32,
+ uint32_t numBits, uint32_t firstBit, uint32_t column)
+{
+ uint32_t tmp32, mask, arrayEntry, lastBit;
+ int32_t bitPosition, bitsLeft;
+
+ tmp32 = ath9k_hw_reverse_bits(reg32, numBits);
+ arrayEntry = (firstBit - 1) / 8;
+ bitPosition = (firstBit - 1) % 8;
+ bitsLeft = numBits;
+ while (bitsLeft > 0) {
+ lastBit = (bitPosition + bitsLeft > 8) ?
+ 8 : bitPosition + bitsLeft;
+ mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
+ (column * 8);
+ rfBuf[arrayEntry] &= ~mask;
+ rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
+ (column * 8)) & mask;
+ bitsLeft -= 8 - bitPosition;
+ tmp32 = tmp32 >> (8 - bitPosition);
+ bitPosition = 0;
+ arrayEntry++;
+ }
+}
+
+boolean_t
+ath9k_hw_set_rf_regs(struct ath_hal *ah, struct ath9k_channel *chan,
+ uint16_t modesIndex)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ uint32_t eepMinorRev;
+ uint32_t ob5GHz = 0, db5GHz = 0;
+ uint32_t ob2GHz = 0, db2GHz = 0;
+ /* LINTED E_FUNC_SET_NOT_USED */
+ int regWrites = 0;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ return (B_TRUE);
+
+ eepMinorRev = ath9k_hw_get_eeprom(ah, EEP_MINOR_REV);
+
+ RF_BANK_SETUP(ahp->ah_analogBank0Data, &ahp->ah_iniBank0, 1);
+
+ RF_BANK_SETUP(ahp->ah_analogBank1Data, &ahp->ah_iniBank1, 1);
+
+ RF_BANK_SETUP(ahp->ah_analogBank2Data, &ahp->ah_iniBank2, 1);
+
+ RF_BANK_SETUP(ahp->ah_analogBank3Data, &ahp->ah_iniBank3,
+ modesIndex);
+ {
+ int i;
+ for (i = 0; i < ahp->ah_iniBank6TPC.ia_rows; i++) {
+ ahp->ah_analogBank6Data[i] =
+ INI_RA(&ahp->ah_iniBank6TPC, i, modesIndex);
+ }
+ }
+
+ if (eepMinorRev >= 2) {
+ if (IS_CHAN_2GHZ(chan)) {
+ ob2GHz = ath9k_hw_get_eeprom(ah, EEP_OB_2);
+ db2GHz = ath9k_hw_get_eeprom(ah, EEP_DB_2);
+ ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
+ ob2GHz, 3, 197, 0);
+ ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
+ db2GHz, 3, 194, 0);
+ } else {
+ ob5GHz = ath9k_hw_get_eeprom(ah, EEP_OB_5);
+ db5GHz = ath9k_hw_get_eeprom(ah, EEP_DB_5);
+ ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
+ ob5GHz, 3, 203, 0);
+ ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
+ db5GHz, 3, 200, 0);
+ }
+ }
+
+ RF_BANK_SETUP(ahp->ah_analogBank7Data, &ahp->ah_iniBank7, 1);
+
+ REG_WRITE_RF_ARRAY(&ahp->ah_iniBank0, ahp->ah_analogBank0Data,
+ regWrites);
+
+ REG_WRITE_RF_ARRAY(&ahp->ah_iniBank1, ahp->ah_analogBank1Data,
+ regWrites);
+
+ REG_WRITE_RF_ARRAY(&ahp->ah_iniBank2, ahp->ah_analogBank2Data,
+ regWrites);
+
+ REG_WRITE_RF_ARRAY(&ahp->ah_iniBank3, ahp->ah_analogBank3Data,
+ regWrites);
+
+ REG_WRITE_RF_ARRAY(&ahp->ah_iniBank6TPC, ahp->ah_analogBank6Data,
+ regWrites);
+
+ REG_WRITE_RF_ARRAY(&ahp->ah_iniBank7, ahp->ah_analogBank7Data,
+ regWrites);
+
+ return (B_TRUE);
+}
+
+void
+ath9k_hw_rfdetach(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (ahp->ah_analogBank0Data != NULL) {
+ kmem_free(ahp->ah_analogBank0Data,
+ (sizeof (uint32_t) * ahp->ah_iniBank0.ia_rows));
+ ahp->ah_analogBank0Data = NULL;
+ }
+ if (ahp->ah_analogBank1Data != NULL) {
+ kmem_free(ahp->ah_analogBank1Data,
+ (sizeof (uint32_t) * ahp->ah_iniBank1.ia_rows));
+ ahp->ah_analogBank1Data = NULL;
+ }
+ if (ahp->ah_analogBank2Data != NULL) {
+ kmem_free(ahp->ah_analogBank2Data,
+ (sizeof (uint32_t) * ahp->ah_iniBank2.ia_rows));
+ ahp->ah_analogBank2Data = NULL;
+ }
+ if (ahp->ah_analogBank3Data != NULL) {
+ kmem_free(ahp->ah_analogBank3Data,
+ (sizeof (uint32_t) * ahp->ah_iniBank3.ia_rows));
+ ahp->ah_analogBank3Data = NULL;
+ }
+ if (ahp->ah_analogBank6Data != NULL) {
+ kmem_free(ahp->ah_analogBank6Data,
+ (sizeof (uint32_t) * ahp->ah_iniBank6.ia_rows));
+ ahp->ah_analogBank6Data = NULL;
+ }
+ if (ahp->ah_analogBank6TPCData != NULL) {
+ kmem_free(ahp->ah_analogBank6TPCData,
+ (sizeof (uint32_t) * ahp->ah_iniBank6TPC.ia_rows));
+ ahp->ah_analogBank6TPCData = NULL;
+ }
+ if (ahp->ah_analogBank7Data != NULL) {
+ kmem_free(ahp->ah_analogBank7Data,
+ (sizeof (uint32_t) * ahp->ah_iniBank7.ia_rows));
+ ahp->ah_analogBank7Data = NULL;
+ }
+ if (ahp->ah_addac5416_21 != NULL) {
+ kmem_free(ahp->ah_addac5416_21,
+ (sizeof (uint32_t) * ahp->ah_iniAddac.ia_rows *
+ ahp->ah_iniAddac.ia_columns));
+ ahp->ah_addac5416_21 = NULL;
+ }
+ if (ahp->ah_bank6Temp != NULL) {
+ kmem_free(ahp->ah_bank6Temp,
+ (sizeof (uint32_t) * ahp->ah_iniBank6.ia_rows));
+ ahp->ah_bank6Temp = NULL;
+ }
+}
+
+boolean_t
+ath9k_hw_init_rf(struct ath_hal *ah, int *status)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (!AR_SREV_9280_10_OR_LATER(ah)) {
+
+ ahp->ah_analogBank0Data =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniBank0.ia_rows), KM_SLEEP);
+ ahp->ah_analogBank1Data =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniBank1.ia_rows), KM_SLEEP);
+ ahp->ah_analogBank2Data =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniBank2.ia_rows), KM_SLEEP);
+ ahp->ah_analogBank3Data =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniBank3.ia_rows), KM_SLEEP);
+ ahp->ah_analogBank6Data =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniBank6.ia_rows), KM_SLEEP);
+ ahp->ah_analogBank6TPCData =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniBank6TPC.ia_rows), KM_SLEEP);
+ ahp->ah_analogBank7Data =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniBank7.ia_rows), KM_SLEEP);
+
+ if (ahp->ah_analogBank0Data == NULL ||
+ ahp->ah_analogBank1Data == NULL ||
+ ahp->ah_analogBank2Data == NULL ||
+ ahp->ah_analogBank3Data == NULL ||
+ ahp->ah_analogBank6Data == NULL ||
+ ahp->ah_analogBank6TPCData == NULL ||
+ ahp->ah_analogBank7Data == NULL) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): "
+ "cannot allocate RF banks\n"));
+ *status = ENOMEM;
+ return (B_FALSE);
+ }
+
+ ahp->ah_addac5416_21 =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniAddac.ia_rows *
+ ahp->ah_iniAddac.ia_columns), KM_SLEEP);
+ if (ahp->ah_addac5416_21 == NULL) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): "
+ "cannot allocate ah_addac5416_21\n"));
+ *status = ENOMEM;
+ return (B_FALSE);
+ }
+
+ ahp->ah_bank6Temp =
+ kmem_zalloc((sizeof (uint32_t) *
+ ahp->ah_iniBank6.ia_rows), KM_SLEEP);
+ if (ahp->ah_bank6Temp == NULL) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): "
+ "cannot allocate ah_bank6Temp\n"));
+ *status = ENOMEM;
+ return (B_FALSE);
+ }
+ }
+
+ return (B_TRUE);
+}
+
+/* ARGSUSED */
+void
+ath9k_hw_decrease_chain_power(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ /* LINTED E_FUNC_SET_NOT_USED */
+ int i, regWrites = 0;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ uint32_t bank6SelMask;
+ uint32_t *bank6Temp = ahp->ah_bank6Temp;
+
+ switch (ahp->ah_diversityControl) {
+ case ATH9K_ANT_FIXED_A:
+ bank6SelMask =
+ (ahp-> ah_antennaSwitchSwap & ANTSWAP_AB) ? REDUCE_CHAIN_0 :
+ REDUCE_CHAIN_1;
+ break;
+ case ATH9K_ANT_FIXED_B:
+ bank6SelMask =
+ (ahp-> ah_antennaSwitchSwap & ANTSWAP_AB) ? REDUCE_CHAIN_1 :
+ REDUCE_CHAIN_0;
+ break;
+ case ATH9K_ANT_VARIABLE:
+ default:
+ return;
+ }
+
+ for (i = 0; i < ahp->ah_iniBank6.ia_rows; i++)
+ bank6Temp[i] = ahp->ah_analogBank6Data[i];
+
+ REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask);
+
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0);
+
+ REG_WRITE_RF_ARRAY(&ahp->ah_iniBank6, bank6Temp, regWrites);
+
+ REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053);
+#ifdef ALTER_SWITCH
+ REG_WRITE(ah, PHY_SWITCH_CHAIN_0,
+ (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38)
+ | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38));
+#endif
+}
diff --git a/usr/src/uts/common/io/arn/arn_phy.h b/usr/src/uts/common/io/arn/arn_phy.h
new file mode 100644
index 0000000000..ad58a6b06e
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_phy.h
@@ -0,0 +1,555 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARN_PHY_H
+#define _ARN_PHY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+boolean_t ath9k_hw_ar9280_set_channel(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+boolean_t ath9k_hw_set_channel(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+void ath9k_hw_write_regs(struct ath_hal *ah, uint32_t modesIndex,
+ uint32_t freqIndex, int regWrites);
+boolean_t ath9k_hw_set_rf_regs(struct ath_hal *ah,
+ struct ath9k_channel *chan, uint16_t modesIndex);
+void ath9k_hw_decrease_chain_power(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+boolean_t ath9k_hw_init_rf(struct ath_hal *ah, int *status);
+
+#define AR_PHY_BASE 0x9800
+#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2))
+
+#define AR_PHY_TEST 0x9800
+#define PHY_AGC_CLR 0x10000000
+#define RFSILENT_BB 0x00002000
+
+#define AR_PHY_TURBO 0x9804
+#define AR_PHY_FC_TURBO_MODE 0x00000001
+#define AR_PHY_FC_TURBO_SHORT 0x00000002
+#define AR_PHY_FC_DYN2040_EN 0x00000004
+#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008
+#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010
+#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020
+#define AR_PHY_FC_HT_EN 0x00000040
+#define AR_PHY_FC_SHORT_GI_40 0x00000080
+#define AR_PHY_FC_WALSH 0x00000100
+#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
+#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
+#define AR_PHY_TEST2 0x9808
+
+#define AR_PHY_TIMING2 0x9810
+#define AR_PHY_TIMING3 0x9814
+#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
+#define AR_PHY_TIMING3_DSC_MAN_S 17
+#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
+#define AR_PHY_TIMING3_DSC_EXP_S 13
+
+#define AR_PHY_CHIP_ID 0x9818
+#define AR_PHY_CHIP_ID_REV_0 0x80
+#define AR_PHY_CHIP_ID_REV_1 0x81
+#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
+
+#define AR_PHY_ACTIVE 0x981C
+#define AR_PHY_ACTIVE_EN 0x00000001
+#define AR_PHY_ACTIVE_DIS 0x00000000
+
+#define AR_PHY_RF_CTL2 0x9824
+#define AR_PHY_TX_END_DATA_START 0x000000FF
+#define AR_PHY_TX_END_DATA_START_S 0
+#define AR_PHY_TX_END_PA_ON 0x0000FF00
+#define AR_PHY_TX_END_PA_ON_S 8
+
+#define AR_PHY_RF_CTL3 0x9828
+#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
+
+#define AR_PHY_ADC_CTL 0x982C
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
+#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
+#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
+#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16
+
+#define AR_PHY_ADC_SERIAL_CTL 0x9830
+#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000
+#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001
+
+#define AR_PHY_RF_CTL4 0x9834
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
+#define AR_PHY_TSTDAC_CONST 0x983c
+
+#define AR_PHY_SETTLING 0x9844
+#define AR_PHY_SETTLING_SWITCH 0x00003F80
+#define AR_PHY_SETTLING_SWITCH_S 7
+
+#define AR_PHY_RXGAIN 0x9848
+#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
+#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
+#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
+
+#define AR_PHY_DESIRED_SZ 0x9850
+#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
+#define AR_PHY_DESIRED_SZ_ADC_S 0
+#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
+#define AR_PHY_DESIRED_SZ_PGA_S 8
+#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
+#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
+
+#define AR_PHY_FIND_SIG 0x9858
+#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
+#define AR_PHY_FIND_SIG_FIRSTEP_S 12
+#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
+#define AR_PHY_FIND_SIG_FIRPWR_S 18
+
+#define AR_PHY_AGC_CTL1 0x985C
+#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80
+#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7
+#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000
+#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15
+
+#define AR_PHY_AGC_CONTROL 0x9860
+#define AR_PHY_AGC_CONTROL_CAL 0x00000001
+#define AR_PHY_AGC_CONTROL_NF 0x00000002
+#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000
+#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000
+#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
+
+#define AR_PHY_CCA 0x9864
+#define AR_PHY_MINCCA_PWR 0x0FF80000
+#define AR_PHY_MINCCA_PWR_S 19
+#define AR_PHY_CCA_THRESH62 0x0007F000
+#define AR_PHY_CCA_THRESH62_S 12
+#define AR9280_PHY_MINCCA_PWR 0x1FF00000
+#define AR9280_PHY_MINCCA_PWR_S 20
+#define AR9280_PHY_CCA_THRESH62 0x000FF000
+#define AR9280_PHY_CCA_THRESH62_S 12
+
+#define AR_PHY_SFCORR_LOW 0x986C
+#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
+
+#define AR_PHY_SFCORR 0x9868
+#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
+#define AR_PHY_SFCORR_M2COUNT_THR_S 0
+#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
+#define AR_PHY_SFCORR_M1_THRESH_S 17
+#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
+#define AR_PHY_SFCORR_M2_THRESH_S 24
+
+#define AR_PHY_SLEEP_CTR_CONTROL 0x9870
+#define AR_PHY_SLEEP_CTR_LIMIT 0x9874
+#define AR_PHY_SYNTH_CONTROL 0x9874
+#define AR_PHY_SLEEP_SCAL 0x9878
+
+#define AR_PHY_PLL_CTL 0x987c
+#define AR_PHY_PLL_CTL_40 0xaa
+#define AR_PHY_PLL_CTL_40_5413 0x04
+#define AR_PHY_PLL_CTL_44 0xab
+#define AR_PHY_PLL_CTL_44_2133 0xeb
+#define AR_PHY_PLL_CTL_40_2133 0xea
+
+#define AR_PHY_RX_DELAY 0x9914
+#define AR_PHY_SEARCH_START_DELAY 0x9918
+#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
+
+#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12))
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
+#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
+#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000
+
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
+
+#define AR_PHY_TIMING5 0x9924
+#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
+#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
+
+#define AR_PHY_POWER_TX_RATE1 0x9934
+#define AR_PHY_POWER_TX_RATE2 0x9938
+#define AR_PHY_POWER_TX_RATE_MAX 0x993c
+#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+
+#define AR_PHY_FRAME_CTL 0x9944
+#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038
+#define AR_PHY_FRAME_CTL_TX_CLIP_S 3
+
+#define AR_PHY_TXPWRADJ 0x994C
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
+
+#define AR_PHY_RADAR_EXT 0x9940
+#define AR_PHY_RADAR_EXT_ENA 0x00004000
+
+#define AR_PHY_RADAR_0 0x9954
+#define AR_PHY_RADAR_0_ENA 0x00000001
+#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
+#define AR_PHY_RADAR_0_INBAND 0x0000003e
+#define AR_PHY_RADAR_0_INBAND_S 1
+#define AR_PHY_RADAR_0_PRSSI 0x00000FC0
+#define AR_PHY_RADAR_0_PRSSI_S 6
+#define AR_PHY_RADAR_0_HEIGHT 0x0003F000
+#define AR_PHY_RADAR_0_HEIGHT_S 12
+#define AR_PHY_RADAR_0_RRSSI 0x00FC0000
+#define AR_PHY_RADAR_0_RRSSI_S 18
+#define AR_PHY_RADAR_0_FIRPWR 0x7F000000
+#define AR_PHY_RADAR_0_FIRPWR_S 24
+
+#define AR_PHY_RADAR_1 0x9958
+#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
+#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
+#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
+#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
+#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
+#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
+#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
+#define AR_PHY_RADAR_1_MAXLEN_S 0
+
+#define AR_PHY_SWITCH_CHAIN_0 0x9960
+#define AR_PHY_SWITCH_COM 0x9964
+
+#define AR_PHY_SIGMA_DELTA 0x996C
+#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
+#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0
+#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8
+#define AR_PHY_SIGMA_DELTA_FILT2_S 3
+#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00
+#define AR_PHY_SIGMA_DELTA_FILT1_S 8
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+#define AR_PHY_RESTART 0x9970
+#define AR_PHY_RESTART_DIV_GC 0x001C0000
+#define AR_PHY_RESTART_DIV_GC_S 18
+
+#define AR_PHY_RFBUS_REQ 0x997C
+#define AR_PHY_RFBUS_REQ_EN 0x00000001
+
+#define AR_PHY_TIMING7 0x9980
+#define AR_PHY_TIMING8 0x9984
+#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF
+#define AR_PHY_TIMING8_PILOT_MASK_2_S 0
+
+#define AR_PHY_BIN_MASK2_1 0x9988
+#define AR_PHY_BIN_MASK2_2 0x998c
+#define AR_PHY_BIN_MASK2_3 0x9990
+#define AR_PHY_BIN_MASK2_4 0x9994
+
+#define AR_PHY_BIN_MASK_1 0x9900
+#define AR_PHY_BIN_MASK_2 0x9904
+#define AR_PHY_BIN_MASK_3 0x9908
+
+#define AR_PHY_MASK_CTL 0x990c
+
+#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF
+#define AR_PHY_BIN_MASK2_4_MASK_4_S 0
+
+#define AR_PHY_TIMING9 0x9998
+#define AR_PHY_TIMING10 0x999c
+#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF
+#define AR_PHY_TIMING10_PILOT_MASK_2_S 0
+
+#define AR_PHY_TIMING11 0x99a0
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
+#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
+#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
+#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
+#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
+
+#define AR_PHY_RX_CHAINMASK 0x99a4
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
+#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
+#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
+
+#define AR_PHY_EXT_CCA0 0x99b8
+#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
+#define AR_PHY_EXT_CCA0_THRESH62_S 0
+
+#define AR_PHY_EXT_CCA 0x99bc
+#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00
+#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9
+#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
+#define AR_PHY_EXT_CCA_THRESH62_S 16
+#define AR_PHY_EXT_MINCCA_PWR 0xFF800000
+#define AR_PHY_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000
+#define AR9280_PHY_EXT_MINCCA_PWR_S 16
+
+#define AR_PHY_SFCORR_EXT 0x99c0
+#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F
+#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
+#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80
+#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
+#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
+
+#define AR_PHY_HALFGI 0x99D0
+#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0
+#define AR_PHY_HALFGI_DSC_MAN_S 4
+#define AR_PHY_HALFGI_DSC_EXP 0x0000000F
+#define AR_PHY_HALFGI_DSC_EXP_S 0
+
+#define AR_PHY_CHAN_INFO_MEMORY 0x99DC
+#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
+
+#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0
+
+#define AR_PHY_M_SLEEP 0x99f0
+#define AR_PHY_REFCLKDLY 0x99f4
+#define AR_PHY_REFCLKPD 0x99f8
+
+#define AR_PHY_CALMODE 0x99f0
+
+#define AR_PHY_CALMODE_IQ 0x00000000
+#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
+#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
+#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
+
+#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12))
+
+#define AR_PHY_CURRENT_RSSI 0x9c1c
+#define AR9280_PHY_CURRENT_RSSI 0x9c3c
+
+#define AR_PHY_RFBUS_GRANT 0x9C20
+#define AR_PHY_RFBUS_GRANT_EN 0x00000001
+
+#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
+#define AR_PHY_CHAN_INFO_GAIN 0x9CFC
+
+#define AR_PHY_MODE 0xA200
+#define AR_PHY_MODE_AR2133 0x08
+#define AR_PHY_MODE_AR5111 0x00
+#define AR_PHY_MODE_AR5112 0x08
+#define AR_PHY_MODE_DYNAMIC 0x04
+#define AR_PHY_MODE_RF2GHZ 0x02
+#define AR_PHY_MODE_RF5GHZ 0x00
+#define AR_PHY_MODE_CCK 0x01
+#define AR_PHY_MODE_OFDM 0x00
+#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
+
+#define AR_PHY_CCK_TX_CTRL 0xA204
+#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
+
+#define AR_PHY_CCK_DETECT 0xA208
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
+/* [12:6] settling time for antenna switch */
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
+
+#define AR_PHY_GAIN_2GHZ 0xA20C
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
+
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
+
+#define AR_PHY_CCK_RXCTRL4 0xA21C
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
+
+#define AR_PHY_DAG_CTRLCCK 0xA228
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
+
+#define AR_PHY_FORCE_CLKEN_CCK 0xA22C
+#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
+
+#define AR_PHY_POWER_TX_RATE3 0xA234
+#define AR_PHY_POWER_TX_RATE4 0xA238
+
+#define AR_PHY_SCRM_SEQ_XR 0xA23C
+#define AR_PHY_HEADER_DETECT_XR 0xA240
+#define AR_PHY_CHIRP_DETECTED_XR 0xA244
+#define AR_PHY_BLUETOOTH 0xA254
+
+#define AR_PHY_TPCRG1 0xA258
+#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
+
+#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
+#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
+#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
+#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
+#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
+#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
+
+#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
+#define AR_PHY_MASK2_M_31_45 0xa3a4
+#define AR_PHY_MASK2_M_16_30 0xa3a8
+#define AR_PHY_MASK2_M_00_15 0xa3ac
+#define AR_PHY_MASK2_P_15_01 0xa3b8
+#define AR_PHY_MASK2_P_30_16 0xa3bc
+#define AR_PHY_MASK2_P_45_31 0xa3c0
+#define AR_PHY_MASK2_P_61_45 0xa3c4
+#define AR_PHY_SPUR_REG 0x994c
+
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18)
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
+
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9)
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9
+#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
+
+#define AR_PHY_PILOT_MASK_01_30 0xa3b0
+#define AR_PHY_PILOT_MASK_31_60 0xa3b4
+
+#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
+#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
+
+#define AR_PHY_ANALOG_SWAP 0xa268
+#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
+
+#define AR_PHY_TPCRG5 0xA26C
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
+
+#define AR_PHY_POWER_TX_RATE5 0xA38C
+#define AR_PHY_POWER_TX_RATE6 0xA390
+
+#define AR_PHY_CAL_CHAINMASK 0xA39C
+
+#define AR_PHY_POWER_TX_SUB 0xA3C8
+#define AR_PHY_POWER_TX_RATE7 0xA3CC
+#define AR_PHY_POWER_TX_RATE8 0xA3D0
+#define AR_PHY_POWER_TX_RATE9 0xA3D4
+
+#define AR_PHY_XPA_CFG 0xA3D8
+#define AR_PHY_FORCE_XPA_CFG 0x000000001
+#define AR_PHY_FORCE_XPA_CFG_S 0
+
+#define AR_PHY_CH1_CCA 0xa864
+#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000
+#define AR_PHY_CH1_MINCCA_PWR_S 19
+#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000
+#define AR9280_PHY_CH1_MINCCA_PWR_S 20
+
+#define AR_PHY_CH2_CCA 0xb864
+#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000
+#define AR_PHY_CH2_MINCCA_PWR_S 19
+
+#define AR_PHY_CH1_EXT_CCA 0xa9bc
+#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
+
+#define AR_PHY_CH2_EXT_CCA 0xb9bc
+#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
+
+#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \
+ int r; \
+ for (r = 0; r < ((iniarray)->ia_rows); r++) { \
+ REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \
+ } \
+ _NOTE(CONSTCOND) \
+ } while (0)
+
+#define ATH9K_KEY_XOR 0xaau
+
+#define ATH9K_IS_MIC_ENABLED(ah) \
+ (AH5416(ah)->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
+
+#define ANTSWAP_AB 0x0001
+#define REDUCE_CHAIN_0 0x00000050
+#define REDUCE_CHAIN_1 0x00000051
+
+#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \
+ int i; \
+ for (i = 0; i < (_iniarray)->ia_rows; i++) \
+ (_bank)[i] = INI_RA((_iniarray), i, _col); \
+ _NOTE(CONSTCOND) \
+ } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _ARN_PHY_H */
diff --git a/usr/src/uts/common/io/arn/arn_rc.c b/usr/src/uts/common/io/arn/arn_rc.c
new file mode 100644
index 0000000000..767a266453
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_rc.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * Copyright (c) 2004-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/ddi.h>
+
+#include "arn_core.h"
+
+static struct ath_rate_table ar5416_11na_ratetable = {
+ 42,
+ {0},
+ {
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+ 5400, 0x0b, 0x00, 12,
+ 0, 2, 1, 0, 0, 0, 0, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+ 7800, 0x0f, 0x00, 18,
+ 0, 3, 1, 1, 1, 1, 1, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+ 10000, 0x0a, 0x00, 24,
+ 2, 4, 2, 2, 2, 2, 2, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+ 13900, 0x0e, 0x00, 36,
+ 2, 6, 2, 3, 3, 3, 3, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+ 17300, 0x09, 0x00, 48,
+ 4, 10, 3, 4, 4, 4, 4, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+ 23000, 0x0d, 0x00, 72,
+ 4, 14, 3, 5, 5, 5, 5, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+ 27400, 0x08, 0x00, 96,
+ 4, 20, 3, 6, 6, 6, 6, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+ 29300, 0x0c, 0x00, 108,
+ 4, 23, 3, 7, 7, 7, 7, 0 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
+ 6400, 0x80, 0x00, 0,
+ 0, 2, 3, 8, 24, 8, 24, 3216 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
+ 12700, 0x81, 0x00, 1,
+ 2, 4, 3, 9, 25, 9, 25, 6434 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
+ 18800, 0x82, 0x00, 2,
+ 2, 6, 3, 10, 26, 10, 26, 9650 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
+ 25000, 0x83, 0x00, 3,
+ 4, 10, 3, 11, 27, 11, 27, 12868 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
+ 36700, 0x84, 0x00, 4,
+ 4, 14, 3, 12, 28, 12, 28, 19304 },
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
+ 48100, 0x85, 0x00, 5,
+ 4, 20, 3, 13, 29, 13, 29, 25740 },
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
+ 53500, 0x86, 0x00, 6,
+ 4, 23, 3, 14, 30, 14, 30, 28956 },
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
+ 59000, 0x87, 0x00, 7,
+ 4, 25, 3, 15, 31, 15, 32, 32180 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
+ 12700, 0x88, 0x00,
+ 8, 0, 2, 3, 16, 33, 16, 33, 6430 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
+ 24800, 0x89, 0x00, 9,
+ 2, 4, 3, 17, 34, 17, 34, 12860 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
+ 36600, 0x8a, 0x00, 10,
+ 2, 6, 3, 18, 35, 18, 35, 19300 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
+ 48100, 0x8b, 0x00, 11,
+ 4, 10, 3, 19, 36, 19, 36, 25736 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
+ 69500, 0x8c, 0x00, 12,
+ 4, 14, 3, 20, 37, 20, 37, 38600 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
+ 89500, 0x8d, 0x00, 13,
+ 4, 20, 3, 21, 38, 21, 38, 51472 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
+ 98900, 0x8e, 0x00, 14,
+ 4, 23, 3, 22, 39, 22, 39, 57890 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
+ 108300, 0x8f, 0x00, 15,
+ 4, 25, 3, 23, 40, 23, 41, 64320 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
+ 13200, 0x80, 0x00, 0,
+ 0, 2, 3, 8, 24, 24, 24, 6684 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
+ 25900, 0x81, 0x00, 1,
+ 2, 4, 3, 9, 25, 25, 25, 13368 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
+ 38600, 0x82, 0x00, 2,
+ 2, 6, 3, 10, 26, 26, 26, 20052 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
+ 49800, 0x83, 0x00, 3,
+ 4, 10, 3, 11, 27, 27, 27, 26738 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
+ 72200, 0x84, 0x00, 4,
+ 4, 14, 3, 12, 28, 28, 28, 40104 },
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
+ 92900, 0x85, 0x00, 5,
+ 4, 20, 3, 13, 29, 29, 29, 53476 },
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5Mb */
+ 102700, 0x86, 0x00, 6,
+ 4, 23, 3, 14, 30, 30, 30, 60156 },
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
+ 112000, 0x87, 0x00, 7,
+ 4, 25, 3, 15, 31, 32, 32, 66840 },
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI,
+ 150000, /* 150Mb */
+ 122000, 0x87, 0x00, 7,
+ 4, 25, 3, 15, 31, 32, 32, 74200 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
+ 25800, 0x88, 0x00, 8,
+ 0, 2, 3, 16, 33, 33, 33, 13360 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
+ 49800, 0x89, 0x00, 9,
+ 2, 4, 3, 17, 34, 34, 34, 26720 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
+ 71900, 0x8a, 0x00, 10,
+ 2, 6, 3, 18, 35, 35, 35, 40080 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
+ 92500, 0x8b, 0x00, 11,
+ 4, 10, 3, 19, 36, 36, 36, 53440 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
+ 130300, 0x8c, 0x00, 12,
+ 4, 14, 3, 20, 37, 37, 37, 80160 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
+ 162800, 0x8d, 0x00, 13,
+ 4, 20, 3, 21, 38, 38, 38, 106880 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
+ 178200, 0x8e, 0x00, 14,
+ 4, 23, 3, 22, 39, 39, 39, 120240 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
+ 192100, 0x8f, 0x00, 15,
+ 4, 25, 3, 23, 40, 41, 41, 133600 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI,
+ 300000, /* 300 Mb */
+ 207000, 0x8f, 0x00, 15,
+ 4, 25, 3, 23, 40, 41, 41, 148400 },
+ },
+ 50, /* probe interval */
+ 50, /* rssi reduce interval */
+ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
+};
+
+/*
+ * 4ms frame limit not used for NG mode. The values filled
+ * for HT are the 64K max aggregate limit
+ */
+
+static struct ath_rate_table ar5416_11ng_ratetable = {
+ 46,
+ {0},
+ {
+ { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+ 900, 0x1b, 0x00, 2,
+ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+ 1900, 0x1a, 0x04, 4,
+ 1, 1, 1, 1, 1, 1, 1, 0 },
+ { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+ 4900, 0x19, 0x04, 11,
+ 2, 2, 2, 2, 2, 2, 2, 0 },
+ { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+ 8100, 0x18, 0x04, 22,
+ 3, 3, 2, 3, 3, 3, 3, 0 },
+ { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+ 5400, 0x0b, 0x00, 12,
+ 4, 2, 1, 4, 4, 4, 4, 0 },
+ { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+ 7800, 0x0f, 0x00, 18,
+ 4, 3, 1, 5, 5, 5, 5, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+ 10100, 0x0a, 0x00, 24,
+ 6, 4, 1, 6, 6, 6, 6, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+ 14100, 0x0e, 0x00, 36,
+ 6, 6, 2, 7, 7, 7, 7, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+ 17700, 0x09, 0x00, 48,
+ 8, 10, 3, 8, 8, 8, 8, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+ 23700, 0x0d, 0x00, 72,
+ 8, 14, 3, 9, 9, 9, 9, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+ 27400, 0x08, 0x00, 96,
+ 8, 20, 3, 10, 10, 10, 10, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+ 30900, 0x0c, 0x00, 108,
+ 8, 23, 3, 11, 11, 11, 11, 0 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
+ 6400, 0x80, 0x00, 0,
+ 4, 2, 3, 12, 28, 12, 28, 3216 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
+ 12700, 0x81, 0x00, 1,
+ 6, 4, 3, 13, 29, 13, 29, 6434 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
+ 18800, 0x82, 0x00, 2,
+ 6, 6, 3, 14, 30, 14, 30, 9650 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
+ 25000, 0x83, 0x00, 3,
+ 8, 10, 3, 15, 31, 15, 31, 12868 },
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
+ 36700, 0x84, 0x00, 4,
+ 8, 14, 3, 16, 32, 16, 32, 19304 },
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
+ 48100, 0x85, 0x00, 5,
+ 8, 20, 3, 17, 33, 17, 33, 25740 },
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
+ 53500, 0x86, 0x00, 6,
+ 8, 23, 3, 18, 34, 18, 34, 28956 },
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
+ 59000, 0x87, 0x00, 7,
+ 8, 25, 3, 19, 35, 19, 36, 32180 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
+ 12700, 0x88, 0x00, 8,
+ 4, 2, 3, 20, 37, 20, 37, 6430 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
+ 24800, 0x89, 0x00, 9,
+ 6, 4, 3, 21, 38, 21, 38, 12860 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
+ 36600, 0x8a, 0x00, 10,
+ 6, 6, 3, 22, 39, 22, 39, 19300 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
+ 48100, 0x8b, 0x00, 11,
+ 8, 10, 3, 23, 40, 23, 40, 25736 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
+ 69500, 0x8c, 0x00, 12,
+ 8, 14, 3, 24, 41, 24, 41, 38600 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
+ 89500, 0x8d, 0x00, 13,
+ 8, 20, 3, 25, 42, 25, 42, 51472 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
+ 98900, 0x8e, 0x00, 14,
+ 8, 23, 3, 26, 43, 26, 44, 57890 },
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
+ 108300, 0x8f, 0x00, 15,
+ 8, 25, 3, 27, 44, 27, 45, 64320 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
+ 13200, 0x80, 0x00, 0,
+ 8, 2, 3, 12, 28, 28, 28, 6684 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
+ 25900, 0x81, 0x00, 1,
+ 8, 4, 3, 13, 29, 29, 29, 13368 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
+ 38600, 0x82, 0x00, 2,
+ 8, 6, 3, 14, 30, 30, 30, 20052 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
+ 49800, 0x83, 0x00, 3,
+ 8, 10, 3, 15, 31, 31, 31, 26738 },
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
+ 72200, 0x84, 0x00, 4,
+ 8, 14, 3, 16, 32, 32, 32, 40104 },
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
+ 92900, 0x85, 0x00, 5,
+ 8, 20, 3, 17, 33, 33, 33, 53476 },
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS,
+ 121500, /* 121.5 Mb */
+ 102700, 0x86, 0x00, 6,
+ 8, 23, 3, 18, 34, 34, 34, 60156 },
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
+ 112000, 0x87, 0x00, 7,
+ 8, 23, 3, 19, 35, 36, 36, 66840 },
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI,
+ 150000, /* 150 Mb */
+ 122000, 0x87, 0x00, 7,
+ 8, 25, 3, 19, 35, 36, 36, 74200 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
+ 25800, 0x88, 0x00, 8,
+ 8, 2, 3, 20, 37, 37, 37, 13360 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
+ 49800, 0x89, 0x00, 9,
+ 8, 4, 3, 21, 38, 38, 38, 26720 },
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
+ 71900, 0x8a, 0x00, 10,
+ 8, 6, 3, 22, 39, 39, 39, 40080 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
+ 92500, 0x8b, 0x00, 11,
+ 8, 10, 3, 23, 40, 40, 40, 53440 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
+ 130300, 0x8c, 0x00, 12,
+ 8, 14, 3, 24, 41, 41, 41, 80160 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
+ 162800, 0x8d, 0x00, 13,
+ 8, 20, 3, 25, 42, 42, 42, 106880 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
+ 178200, 0x8e, 0x00, 14,
+ 8, 23, 3, 26, 43, 43, 43, 120240 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
+ 192100, 0x8f, 0x00, 15,
+ 8, 23, 3, 27, 44, 45, 45, 133600 },
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI,
+ 300000, /* 300 Mb */
+ 207000, 0x8f, 0x00, 15,
+ 8, 25, 3, 27, 44, 45, 45, 148400 },
+ },
+ 50, /* probe interval */
+ 50, /* rssi reduce interval */
+ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
+};
+
+static struct ath_rate_table ar5416_11a_ratetable = {
+ 8,
+ {0},
+ {
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+ 5400, 0x0b, 0x00, (0x80|12),
+ 0, 2, 1, 0, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+ 7800, 0x0f, 0x00, 18,
+ 0, 3, 1, 1, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+ 10000, 0x0a, 0x00, (0x80|24),
+ 2, 4, 2, 2, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+ 13900, 0x0e, 0x00, 36,
+ 2, 6, 2, 3, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+ 17300, 0x09, 0x00, (0x80|48),
+ 4, 10, 3, 4, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+ 23000, 0x0d, 0x00, 72,
+ 4, 14, 3, 5, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+ 27400, 0x08, 0x00, 96,
+ 4, 19, 3, 6, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+ 29300, 0x0c, 0x00, 108,
+ 4, 23, 3, 7, 0 },
+ },
+ 50, /* probe interval */
+ 50, /* rssi reduce interval */
+ 0, /* Phy rates allowed initially */
+};
+
+static struct ath_rate_table ar5416_11g_ratetable = {
+ 12,
+ {0},
+ {
+ { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+ 900, 0x1b, 0x00, 2,
+ 0, 0, 1, 0, 0 },
+ { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+ 1900, 0x1a, 0x04, 4,
+ 1, 1, 1, 1, 0 },
+ { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+ 4900, 0x19, 0x04, 11,
+ 2, 2, 2, 2, 0 },
+ { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+ 8100, 0x18, 0x04, 22,
+ 3, 3, 2, 3, 0 },
+ { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+ 5400, 0x0b, 0x00, 12,
+ 4, 2, 1, 4, 0 },
+ { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+ 7800, 0x0f, 0x00, 18,
+ 4, 3, 1, 5, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+ 10000, 0x0a, 0x00, 24,
+ 6, 4, 1, 6, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+ 13900, 0x0e, 0x00, 36,
+ 6, 6, 2, 7, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+ 17300, 0x09, 0x00, 48,
+ 8, 10, 3, 8, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+ 23000, 0x0d, 0x00, 72,
+ 8, 14, 3, 9, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+ 27400, 0x08, 0x00, 96,
+ 8, 19, 3, 10, 0 },
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+ 29300, 0x0c, 0x00, 108,
+ 8, 23, 3, 11, 0 },
+ },
+ 50, /* probe interval */
+ 50, /* rssi reduce interval */
+ 0, /* Phy rates allowed initially */
+};
+
+static struct ath_rate_table ar5416_11b_ratetable = {
+ 4,
+ {0},
+ {
+ { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+ 900, 0x1b, 0x00, (0x80|2),
+ 0, 0, 1, 0, 0 },
+ { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+ 1800, 0x1a, 0x04, (0x80|4),
+ 1, 1, 1, 1, 0 },
+ { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+ 4300, 0x19, 0x04, (0x80|11),
+ 1, 2, 2, 2, 0 },
+ { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+ 7100, 0x18, 0x04, (0x80|22),
+ 1, 4, 100, 3, 0 },
+ },
+ 100, /* probe interval */
+ 100, /* rssi reduce interval */
+ 0, /* Phy rates allowed initially */
+};
+
+static void
+arn_setup_rate_table(struct arn_softc *sc,
+ struct ath_rate_table *rate_table)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ rate_table->rateCodeToIndex[i] = (uint8_t)-1;
+
+ for (i = 0; i < rate_table->rate_cnt; i++) {
+ uint8_t code = rate_table->info[i].ratecode;
+ uint8_t cix = rate_table->info[i].ctrl_rate;
+ uint8_t sh = rate_table->info[i].short_preamble;
+
+ rate_table->rateCodeToIndex[code] = (int)i;
+ rate_table->rateCodeToIndex[code | sh] = (int)i;
+
+ rate_table->info[i].lpAckDuration =
+ ath9k_hw_computetxtime(sc->sc_ah, rate_table,
+ WLAN_CTRL_FRAME_SIZE,
+ cix,
+ B_FALSE);
+ rate_table->info[i].spAckDuration =
+ ath9k_hw_computetxtime(sc->sc_ah, rate_table,
+ WLAN_CTRL_FRAME_SIZE,
+ cix,
+ B_TRUE);
+ }
+}
+
+void
+arn_rate_attach(struct arn_softc *sc)
+{
+ sc->hw_rate_table[ATH9K_MODE_11B] =
+ &ar5416_11b_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11A] =
+ &ar5416_11a_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11G] =
+ &ar5416_11g_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
+ &ar5416_11na_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
+ &ar5416_11ng_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
+ &ar5416_11na_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
+ &ar5416_11na_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
+ &ar5416_11ng_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
+ &ar5416_11ng_ratetable;
+
+ arn_setup_rate_table(sc, &ar5416_11b_ratetable);
+ arn_setup_rate_table(sc, &ar5416_11a_ratetable);
+ arn_setup_rate_table(sc, &ar5416_11g_ratetable);
+ arn_setup_rate_table(sc, &ar5416_11na_ratetable);
+ arn_setup_rate_table(sc, &ar5416_11ng_ratetable);
+}
+
+void
+arn_rate_update(struct arn_softc *sc, struct ieee80211_node *in, int32_t rate)
+{
+ struct ath_node *an = ATH_NODE(in);
+ const struct ath_rate_table *rt = sc->sc_currates;
+ uint8_t rix;
+
+ ASSERT(rt != NULL);
+
+ in->in_txrate = rate;
+
+ /* management/control frames always go at the lowest speed */
+ an->an_tx_mgtrate = rt->info[0].ratecode;
+ an->an_tx_mgtratesp = an->an_tx_mgtrate | rt->info[0].short_preamble;
+
+ ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_update(): "
+ "mgtrate=%d mgtratesp=%d\n",
+ an->an_tx_mgtrate, an->an_tx_mgtratesp));
+
+ /*
+ * Before associating a node has no rate set setup
+ * so we can't calculate any transmit codes to use.
+ * This is ok since we should never be sending anything
+ * but management frames and those always go at the
+ * lowest hardware rate.
+ */
+ if (in->in_rates.ir_nrates == 0)
+ goto done;
+ an->an_tx_rix0 = sc->asc_rixmap[
+ in->in_rates.ir_rates[rate] & IEEE80211_RATE_VAL];
+ an->an_tx_rate0 = rt->info[an->an_tx_rix0].ratecode;
+ an->an_tx_rate0sp = an->an_tx_rate0 |
+ rt->info[an->an_tx_rix0].short_preamble;
+ if (sc->sc_mrretry) {
+ /*
+ * Hardware supports multi-rate retry; setup two
+ * step-down retry rates and make the lowest rate
+ * be the ``last chance''. We use 4, 2, 2, 2 tries
+ * respectively (4 is set here, the rest are fixed
+ * in the xmit routine).
+ */
+ an->an_tx_try0 = 1 + 3; /* 4 tries at rate 0 */
+ if (--rate >= 0) {
+ rix = sc->asc_rixmap[
+ in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL];
+ an->an_tx_rate1 = rt->info[rix].ratecode;
+ an->an_tx_rate1sp = an->an_tx_rate1 |
+ rt->info[rix].short_preamble;
+ } else {
+ an->an_tx_rate1 = an->an_tx_rate1sp = 0;
+ }
+ if (--rate >= 0) {
+ rix = sc->asc_rixmap[
+ in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL];
+ an->an_tx_rate2 = rt->info[rix].ratecode;
+ an->an_tx_rate2sp = an->an_tx_rate2 |
+ rt->info[rix].short_preamble;
+ } else {
+ an->an_tx_rate2 = an->an_tx_rate2sp = 0;
+ }
+ if (rate > 0) {
+ an->an_tx_rate3 = rt->info[0].ratecode;
+ an->an_tx_rate3sp =
+ an->an_tx_mgtrate | rt->info[0].short_preamble;
+ } else {
+ an->an_tx_rate3 = an->an_tx_rate3sp = 0;
+ }
+ } else {
+ an->an_tx_try0 = ATH_TXMAXTRY; /* max tries at rate 0 */
+ an->an_tx_rate1 = an->an_tx_rate1sp = 0;
+ an->an_tx_rate2 = an->an_tx_rate2sp = 0;
+ an->an_tx_rate3 = an->an_tx_rate3sp = 0;
+ }
+done:
+ an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0;
+}
+
+/*
+ * Set the starting transmit rate for a node.
+ */
+void
+arn_rate_ctl_start(struct arn_softc *sc, struct ieee80211_node *in)
+{
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ int32_t srate;
+
+ if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
+ /*
+ * No fixed rate is requested. For 11b start with
+ * the highest negotiated rate; otherwise, for 11g
+ * and 11a, we start "in the middle" at 24Mb or 36Mb.
+ */
+ srate = in->in_rates.ir_nrates - 1;
+ if (sc->sc_curmode != IEEE80211_MODE_11B) {
+ /*
+ * Scan the negotiated rate set to find the
+ * closest rate.
+ */
+ /* NB: the rate set is assumed sorted */
+ for (; srate >= 0 && IEEE80211_RATE(srate) > 72;
+ srate--) {}
+ }
+ } else {
+ /*
+ * A fixed rate is to be used; We know the rate is
+ * there because the rate set is checked when the
+ * station associates.
+ */
+ /* NB: the rate set is assumed sorted */
+ srate = in->in_rates.ir_nrates - 1;
+ for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate;
+ srate--) {}
+ }
+
+ ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_ctl_start(): "
+ "srate=%d rate=%d\n", srate, IEEE80211_RATE(srate)));
+
+ arn_rate_update(sc, in, srate);
+}
+
+void
+arn_rate_cb(void *arg, struct ieee80211_node *in)
+{
+ arn_rate_update((struct arn_softc *)arg, in, 0);
+}
+
+/*
+ * Reset the rate control state for each 802.11 state transition.
+ */
+void
+arn_rate_ctl_reset(struct arn_softc *sc, enum ieee80211_state state)
+{
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ieee80211_node *in;
+
+ if (ic->ic_opmode == IEEE80211_M_STA) {
+ /*
+ * Reset local xmit state; this is really only
+ * meaningful when operating in station mode.
+ */
+ in = (struct ieee80211_node *)ic->ic_bss;
+ if (state == IEEE80211_S_RUN) {
+ arn_rate_ctl_start(sc, in);
+ } else {
+ arn_rate_update(sc, in, 0);
+ }
+ } else {
+ /*
+ * When operating as a station the node table holds
+ * the AP's that were discovered during scanning.
+ * For any other operating mode we want to reset the
+ * tx rate state of each node.
+ */
+ ieee80211_iterate_nodes(&ic->ic_sta, arn_rate_cb, sc);
+ arn_rate_update(sc, ic->ic_bss, 0);
+ }
+}
+
+/*
+ * Examine and potentially adjust the transmit rate.
+ */
+void
+arn_rate_ctl(void *arg, struct ieee80211_node *in)
+{
+ struct arn_softc *sc = arg;
+ struct ath_node *an = ATH_NODE(in);
+ struct ieee80211_rateset *rs = &in->in_rates;
+ int32_t mod = 0, nrate, enough;
+
+ /*
+ * Rate control(very primitive version).
+ */
+ sc->sc_stats.ast_rate_calls++;
+
+ enough = (an->an_tx_ok + an->an_tx_err >= 10);
+
+ /* no packet reached -> down */
+ if (an->an_tx_err > 0 && an->an_tx_ok == 0)
+ mod = -1;
+
+ /* all packets needs retry in average -> down */
+ if (enough && an->an_tx_ok < an->an_tx_retr)
+ mod = -1;
+
+ /* no error and less than 10% of packets needs retry -> up */
+ if (enough && an->an_tx_err == 0 && an->an_tx_ok > an->an_tx_retr * 10)
+ mod = 1;
+
+ nrate = in->in_txrate;
+ switch (mod) {
+ case 0:
+ if (enough && an->an_tx_upper > 0)
+ an->an_tx_upper--;
+ break;
+ case -1:
+ if (nrate > 0) {
+ nrate--;
+ sc->sc_stats.ast_rate_drop++;
+ }
+ an->an_tx_upper = 0;
+ break;
+ case 1:
+ if (++an->an_tx_upper < 10)
+ break;
+ an->an_tx_upper = 0;
+ if (nrate + 1 < rs->ir_nrates) {
+ nrate++;
+ sc->sc_stats.ast_rate_raise++;
+ }
+ break;
+ }
+
+ if (nrate != in->in_txrate) {
+ ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_ctl(): %dM -> %dM "
+ "(%d ok, %d err, %d retr)\n",
+ (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2,
+ (rs->ir_rates[nrate] & IEEE80211_RATE_VAL) / 2,
+ an->an_tx_ok, an->an_tx_err, an->an_tx_retr));
+ arn_rate_update(sc, in, nrate);
+ } else if (enough)
+ an->an_tx_ok = an->an_tx_err = an->an_tx_retr = 0;
+}
diff --git a/usr/src/uts/common/io/arn/arn_rc.h b/usr/src/uts/common/io/arn/arn_rc.h
new file mode 100644
index 0000000000..04fbb6110c
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_rc.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2004 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * 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.
+ */
+
+#ifndef _ARN_RC_H
+#define _ARN_RC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "arn_ath9k.h"
+
+struct arn_softc;
+
+#define ATH_RATE_MAX 30
+#define RATE_TABLE_SIZE 64
+#define MAX_TX_RATE_PHY 48
+
+/*
+ * VALID_ALL - valid for 20/40/Legacy,
+ * VALID - Legacy only,
+ * VALID_20 - HT 20 only,
+ * VALID_40 - HT 40 only
+ */
+
+#define INVALID 0x0
+#define VALID 0x1
+#define VALID_20 0x2
+#define VALID_40 0x4
+#define VALID_2040 (VALID_20|VALID_40)
+#define VALID_ALL (VALID_2040|VALID)
+
+#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) || \
+ (_phy == WLAN_RC_PHY_HT_40_DS) || \
+ (_phy == WLAN_RC_PHY_HT_20_DS_HGI) || \
+ (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) || \
+ (_phy == WLAN_RC_PHY_HT_40_DS) || \
+ (_phy == WLAN_RC_PHY_HT_40_SS_HGI) || \
+ (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) || \
+ (_phy == WLAN_RC_PHY_HT_20_DS_HGI) || \
+ (_phy == WLAN_RC_PHY_HT_40_SS_HGI) || \
+ (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+
+#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS)
+
+#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \
+ (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID))
+
+/*
+ * Return TRUE if flag supports HT20 && client supports HT20 or
+ * return TRUE if flag supports HT40 && client supports HT40.
+ * This is used becos some rates overlap between HT20/HT40.
+ */
+#define WLAN_RC_PHY_HT_VALID(flag, capflag) \
+ (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \
+ ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG)))
+
+#define WLAN_RC_DS_FLAG (0x01)
+#define WLAN_RC_40_FLAG (0x02)
+#define WLAN_RC_SGI_FLAG (0x04)
+#define WLAN_RC_HT_FLAG (0x08)
+
+/*
+ * struct ath_rate_table - Rate Control table
+ * @valid: valid for use in rate control
+ * @valid_single_stream: valid for use in rate control for
+ * single stream operation
+ * @phy: CCK/OFDM
+ * @ratekbps: rate in Kbits per second
+ * @user_ratekbps: user rate in Kbits per second
+ * @ratecode: rate that goes into HW descriptors
+ * @short_preamble: Mask for enabling short preamble in ratecode for CCK
+ * @dot11rate: value that goes into supported
+ * rates info element of MLME
+ * @ctrl_rate: Index of next lower basic rate, used for duration computation
+ * @max_4ms_framelen: maximum frame length(bytes) for tx duration
+ * @probe_interval: interval for rate control to probe for other rates
+ * @rssi_reduce_interval: interval for rate control to reduce rssi
+ * @initial_ratemax: initial ratemax value
+ */
+struct ath_rate_table {
+ int rate_cnt;
+ uint8_t rateCodeToIndex[256];
+ struct {
+ int valid;
+ int valid_single_stream;
+ uint8_t phy;
+ uint32_t ratekbps;
+ uint32_t user_ratekbps;
+ uint8_t ratecode;
+ uint8_t short_preamble;
+ uint8_t dot11rate;
+ uint8_t ctrl_rate;
+ int8_t rssi_ack_validmin;
+ int8_t rssi_ack_deltamin;
+ uint8_t base_index;
+ uint8_t cw40index;
+ uint8_t sgi_index;
+ uint8_t ht_index;
+ uint32_t max_4ms_framelen;
+ uint16_t lpAckDuration;
+ uint16_t spAckDuration;
+ } info[RATE_TABLE_SIZE];
+ uint32_t probe_interval;
+ uint32_t rssi_reduce_interval;
+ uint8_t initial_ratemax;
+};
+
+struct ath_tx_ratectrl_state {
+ int8_t rssi_thres; /* required rssi for this rate (dB) */
+ uint8_t per; /* recent estimate of packet error rate (%) */
+};
+
+struct ath_rateset {
+ uint8_t rs_nrates;
+ uint8_t rs_rates[ATH_RATE_MAX];
+};
+
+/*
+ * struct ath_rate_priv - Rate Control priv data
+ * @state: RC state
+ * @rssi_last: last ACK rssi
+ * @rssi_last_lookup: last ACK rssi used for lookup
+ * @rssi_last_prev: previous last ACK rssi
+ * @rssi_last_prev2: 2nd previous last ACK rssi
+ * @rssi_sum_cnt: count of rssi_sum for averaging
+ * @rssi_sum_rate: rate that we are averaging
+ * @rssi_sum: running sum of rssi for averaging
+ * @probe_rate: rate we are probing at
+ * @rssi_time: msec timestamp for last ack rssi
+ * @rssi_down_time: msec timestamp for last down step
+ * @probe_time: msec timestamp for last probe
+ * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
+ * @max_valid_rate: maximum number of valid rate
+ * @per_down_time: msec timestamp for last PER down step
+ * @valid_phy_ratecnt: valid rate count
+ * @rate_max_phy: phy index for the max rate
+ * @probe_interval: interval for ratectrl to probe for other rates
+ * @prev_data_rix: rate idx of last data frame
+ * @ht_cap: HT capabilities
+ * @single_stream: When TRUE, only single TX stream possible
+ * @neg_rates: Negotatied rates
+ * @neg_ht_rates: Negotiated HT rates
+ */
+struct ath_rate_priv {
+ int8_t rssi_last;
+ int8_t rssi_last_lookup;
+ int8_t rssi_last_prev;
+ int8_t rssi_last_prev2;
+ int32_t rssi_sum_cnt;
+ int32_t rssi_sum_rate;
+ int32_t rssi_sum;
+ uint8_t rate_table_size;
+ uint8_t probe_rate;
+ uint8_t hw_maxretry_pktcnt;
+ uint8_t max_valid_rate;
+ uint8_t valid_rate_index[RATE_TABLE_SIZE];
+ uint8_t ht_cap;
+ uint8_t single_stream;
+ uint8_t valid_phy_ratecnt[WLAN_RC_PHY_MAX];
+ uint8_t valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
+ uint8_t rc_phy_mode;
+ uint8_t rate_max_phy;
+ uint32_t rssi_time;
+ uint32_t rssi_down_time;
+ uint32_t probe_time;
+ uint32_t per_down_time;
+ uint32_t probe_interval;
+ uint32_t prev_data_rix;
+ uint32_t tx_triglevel_max;
+ struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE];
+ struct ath_rateset neg_rates;
+ struct ath_rateset neg_ht_rates;
+};
+
+struct ath_tx_info_priv {
+ struct ath_tx_status tx;
+ int n_frames;
+ int n_bad_frames;
+ boolean_t update_rc;
+};
+
+#define ATH_TX_INFO_PRIV(tx_info) \
+ ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0]))
+
+/* RATE */
+void arn_rate_attach(struct arn_softc *sc);
+void arn_rate_update(struct arn_softc *sc, struct ieee80211_node *in,
+ int32_t rate);
+void arn_rate_ctl_start(struct arn_softc *sc, struct ieee80211_node *in);
+void arn_rate_cb(void *arg, struct ieee80211_node *in);
+void arn_rate_ctl_reset(struct arn_softc *sc, enum ieee80211_state state);
+void arn_rate_ctl(void *arg, struct ieee80211_node *in);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARN_RC_H */
diff --git a/usr/src/uts/common/io/arn/arn_recv.c b/usr/src/uts/common/io/arn/arn_recv.c
new file mode 100644
index 0000000000..8f925a876d
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_recv.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include <sys/byteorder.h>
+
+#include "arn_core.h"
+
+void
+arn_setdefantenna(struct arn_softc *sc, uint32_t antenna)
+{
+ /* XXX block beacon interrupts */
+ ath9k_hw_setantenna(sc->sc_ah, antenna);
+ sc->sc_defant = (uint8_t)antenna; /* LINT */
+ sc->sc_rxotherant = 0;
+}
+
+/*
+ * Extend 15-bit time stamp from rx descriptor to
+ * a full 64-bit TSF using the current h/w TSF.
+ */
+
+static uint64_t
+arn_extend_tsf(struct arn_softc *sc, uint32_t rstamp)
+{
+ uint64_t tsf;
+
+ tsf = ath9k_hw_gettsf64(sc->sc_ah);
+ if ((tsf & 0x7fff) < rstamp)
+ tsf -= 0x8000;
+ return ((tsf & ~0x7fff) | rstamp);
+}
+
+static void
+arn_opmode_init(struct arn_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ uint32_t rfilt;
+ uint32_t mfilt[2];
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+
+ /* configure rx filter */
+ rfilt = arn_calcrxfilter(sc);
+ ath9k_hw_setrxfilter(ah, rfilt);
+
+ /* configure bssid mask */
+ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
+ (void) ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
+
+ /* configure operational mode */
+ ath9k_hw_setopmode(ah);
+
+ /* Handle any link-level address change. */
+ (void) ath9k_hw_setmac(ah, sc->sc_myaddr);
+
+ /* calculate and install multicast filter */
+ mfilt[0] = ~((uint32_t)0); /* LINT */
+ mfilt[1] = ~((uint32_t)0); /* LINT */
+
+ ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
+
+ ARN_DBG((ARN_DBG_RECV, "arn: arn_opmode_init(): "
+ "mode = %d RX filter 0x%x, MC filter %08x:%08x\n",
+ ic->ic_opmode, rfilt, mfilt[0], mfilt[1]));
+}
+
+/*
+ * Calculate the receive filter according to the
+ * operating mode and state:
+ *
+ * o always accept unicast, broadcast, and multicast traffic
+ * o maintain current state of phy error reception (the hal
+ * may enable phy error frames for noise immunity work)
+ * o probe request frames are accepted only when operating in
+ * hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ * - when operating in adhoc mode so the 802.11 layer creates
+ * node table entries for peers,
+ * - when operating in station mode for collecting rssi data when
+ * the station is otherwise quiet, or
+ * - when operating as a repeater so we see repeater-sta beacons
+ * - when scanning
+ */
+
+uint32_t
+arn_calcrxfilter(struct arn_softc *sc)
+{
+#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | \
+ ATH9K_RX_FILTER_PHYRADAR)
+
+ uint32_t rfilt;
+
+ rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) |
+ ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
+ ATH9K_RX_FILTER_MCAST;
+
+ /* If not a STA, enable processing of Probe Requests */
+ if (sc->sc_ah->ah_opmode != ATH9K_M_STA)
+ rfilt |= ATH9K_RX_FILTER_PROBEREQ;
+
+ /* Can't set HOSTAP into promiscous mode */
+ if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) &&
+ (sc->sc_promisc)) ||
+ (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) {
+ rfilt |= ATH9K_RX_FILTER_PROM;
+ /* ??? To prevent from sending ACK */
+ rfilt &= ~ATH9K_RX_FILTER_UCAST;
+ }
+
+ if (sc->sc_ah->ah_opmode == ATH9K_M_STA ||
+ sc->sc_ah->ah_opmode == ATH9K_M_IBSS)
+ rfilt |= ATH9K_RX_FILTER_BEACON;
+
+ /*
+ * If in HOSTAP mode, want to enable reception of PSPOLL
+ * frames & beacon frames
+ */
+ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP)
+ rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL);
+
+ return (rfilt);
+
+#undef RX_FILTER_PRESERVE
+}
+
+int
+arn_startrecv(struct arn_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_buf *bf;
+
+ /* clean up rx link firstly */
+ sc->sc_rxlink = NULL;
+
+ /* rx descriptor link set up */
+ bf = list_head(&sc->sc_rxbuf_list);
+ while (bf != NULL) {
+ arn_rx_buf_link(sc, bf);
+ bf = list_next(&sc->sc_rxbuf_list, bf);
+ }
+
+ bf = list_head(&sc->sc_rxbuf_list);
+
+ ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+ ath9k_hw_rxena(ah);
+
+ arn_opmode_init(sc);
+ ath9k_hw_startpcureceive(ah);
+
+ return (0);
+}
+
+boolean_t
+arn_stoprecv(struct arn_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ boolean_t stopped;
+
+ ath9k_hw_stoppcurecv(ah);
+ ath9k_hw_setrxfilter(ah, 0);
+ stopped = ath9k_hw_stopdmarecv(ah);
+
+ /* 3ms is long enough for 1 frame ??? */
+ drv_usecwait(3000);
+
+ sc->sc_rxlink = NULL;
+
+ return (stopped);
+}
+
+/*
+ * Intercept management frames to collect beacon rssi data
+ * and to do ibss merges.
+ */
+
+void
+arn_recv_mgmt(struct ieee80211com *ic, mblk_t *mp, struct ieee80211_node *in,
+ int subtype, int rssi, uint32_t rstamp)
+{
+ struct arn_softc *sc = (struct arn_softc *)ic;
+
+ /*
+ * Call up first so subsequent work can use information
+ * potentially stored in the node (e.g. for ibss merge).
+ */
+ sc->sc_recv_mgmt(ic, mp, in, subtype, rssi, rstamp);
+
+ ARN_LOCK(sc);
+ switch (subtype) {
+ case IEEE80211_FC0_SUBTYPE_BEACON:
+ /* update rssi statistics */
+ if (sc->sc_bsync && in == ic->ic_bss &&
+ ic->ic_state == IEEE80211_S_RUN) {
+ /*
+ * Resync beacon timers using the tsf of the beacon
+ * frame we just received.
+ */
+ arn_beacon_config(sc);
+ }
+ /* FALLTHRU */
+ case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+ if (ic->ic_opmode == IEEE80211_M_IBSS &&
+ ic->ic_state == IEEE80211_S_RUN &&
+ (in->in_capinfo & IEEE80211_CAPINFO_IBSS)) {
+ uint64_t tsf = arn_extend_tsf(sc, rstamp);
+ /*
+ * Handle ibss merge as needed; check the tsf on the
+ * frame before attempting the merge. The 802.11 spec
+ * says the station should change it's bssid to match
+ * the oldest station with the same ssid, where oldest
+ * is determined by the tsf. Note that hardware
+ * reconfiguration happens through callback to
+ * ath_newstate as the state machine will go from
+ * RUN -> RUN when this happens.
+ */
+ if (LE_64(in->in_tstamp.tsf) >= tsf) {
+ ARN_DBG((ARN_DBG_BEACON, "arn: arn_recv_mgmt:"
+ "ibss merge, rstamp %u tsf %lu "
+ "tstamp %lu\n", rstamp, tsf,
+ in->in_tstamp.tsf));
+ ARN_UNLOCK(sc);
+ ARN_DBG((ARN_DBG_BEACON, "arn_recv_mgmt():"
+ "ibss_merge: rstamp=%d in_tstamp=%02x %02x"
+ " %02x %02x %02x %02x %02x %02x\n",
+ rstamp, in->in_tstamp.data[0],
+ in->in_tstamp.data[1],
+ in->in_tstamp.data[2],
+ in->in_tstamp.data[3],
+ in->in_tstamp.data[4],
+ in->in_tstamp.data[5],
+ in->in_tstamp.data[6],
+ in->in_tstamp.data[7]));
+ (void) ieee80211_ibss_merge(in);
+ return;
+ }
+ }
+ break;
+ }
+ ARN_UNLOCK(sc);
+}
+
+static void
+arn_printrxbuf(struct ath_buf *bf, int32_t done)
+{
+ struct ath_desc *ds = bf->bf_desc;
+ const struct ath_rx_status *rs = &ds->ds_rxstat;
+
+ ARN_DBG((ARN_DBG_RECV, "arn: R (%p %p) %08x %08x %08x "
+ "%08x %08x %08x %c\n",
+ ds, bf->bf_daddr,
+ ds->ds_link, ds->ds_data,
+ ds->ds_ctl0, ds->ds_ctl1,
+ ds->ds_hw[0], ds->ds_hw[1],
+ !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'));
+}
+
+static void
+arn_rx_handler(struct arn_softc *sc)
+{
+#define PA2DESC(_sc, _pa) \
+ ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
+ ((_pa) - (_sc)->sc_desc_dma.cookie.dmac_address)))
+
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ath_buf *bf;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_desc *ds;
+ struct ath_rx_status *rs;
+ mblk_t *rx_mp;
+ struct ieee80211_frame *wh;
+ int32_t len, ngood, loop = 1;
+ uint8_t phyerr;
+ int status;
+ struct ieee80211_node *in;
+
+ ngood = 0;
+ do {
+ mutex_enter(&sc->sc_rxbuflock);
+ bf = list_head(&sc->sc_rxbuf_list);
+ if (bf == NULL) {
+ ARN_DBG((ARN_DBG_RECV, "arn: arn_rx_handler(): "
+ "no buffer\n"));
+ mutex_exit(&sc->sc_rxbuflock);
+ break;
+ }
+ ASSERT(bf->bf_dma.cookie.dmac_address != NULL);
+ ds = bf->bf_desc;
+ if (ds->ds_link == bf->bf_daddr) {
+ /*
+ * Never process the self-linked entry at the end,
+ * this may be met at heavy load.
+ */
+ mutex_exit(&sc->sc_rxbuflock);
+ break;
+ }
+
+ /*
+ * Must provide the virtual address of the current
+ * descriptor, the physical address, and the virtual
+ * address of the next descriptor in the h/w chain.
+ * This allows the HAL to look ahead to see if the
+ * hardware is done with a descriptor by checking the
+ * done bit in the following descriptor and the address
+ * of the current descriptor the DMA engine is working
+ * on. All this is necessary because of our use of
+ * a self-linked list to avoid rx overruns.
+ */
+ status = ath9k_hw_rxprocdesc(ah, ds,
+ bf->bf_daddr,
+ PA2DESC(sc, ds->ds_link), 0);
+ if (status == EINPROGRESS) {
+ mutex_exit(&sc->sc_rxbuflock);
+ break;
+ }
+ list_remove(&sc->sc_rxbuf_list, bf);
+ mutex_exit(&sc->sc_rxbuflock);
+
+ rs = &ds->ds_rxstat;
+ if (rs->rs_status != 0) {
+ if (rs->rs_status & ATH9K_RXERR_CRC) {
+ sc->sc_stats.ast_rx_crcerr++;
+ }
+ if (rs->rs_status & ATH9K_RXERR_FIFO) {
+ sc->sc_stats.ast_rx_fifoerr++;
+ }
+ if (rs->rs_status & ATH9K_RXERR_DECRYPT) {
+ sc->sc_stats.ast_rx_badcrypt++;
+ }
+ if (rs->rs_status & ATH9K_RXERR_PHY) {
+ sc->sc_stats.ast_rx_phyerr++;
+ phyerr = rs->rs_phyerr & 0x1f;
+ sc->sc_stats.ast_rx_phy[phyerr]++;
+ }
+ goto rx_next;
+ }
+ len = rs->rs_datalen;
+
+ /* less than sizeof(struct ieee80211_frame) */
+ if (len < 20) {
+ sc->sc_stats.ast_rx_tooshort++;
+ goto rx_next;
+ }
+
+ if ((rx_mp = allocb(sc->sc_dmabuf_size, BPRI_MED)) == NULL) {
+ arn_problem("arn: arn_rx_handler(): "
+ "allocing mblk buffer failed.\n");
+ return;
+ }
+
+ ARN_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORCPU);
+ bcopy(bf->bf_dma.mem_va, rx_mp->b_rptr, len);
+
+ rx_mp->b_wptr += len;
+ wh = (struct ieee80211_frame *)rx_mp->b_rptr;
+
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
+ IEEE80211_FC0_TYPE_CTL) {
+ /*
+ * Ignore control frame received in promisc mode.
+ */
+ freemsg(rx_mp);
+ goto rx_next;
+ }
+ /* Remove the CRC at the end of IEEE80211 frame */
+ rx_mp->b_wptr -= IEEE80211_CRC_LEN;
+
+#ifdef DEBUG
+ arn_printrxbuf(bf, status == 0);
+#endif
+
+ /*
+ * Locate the node for sender, track state, and then
+ * pass the (referenced) node up to the 802.11 layer
+ * for its use.
+ */
+ in = ieee80211_find_rxnode(ic, wh);
+
+ /*
+ * Send the frame to net80211 for processing
+ */
+ (void) ieee80211_input(ic, rx_mp, in,
+ rs->rs_rssi, rs->rs_tstamp);
+
+ /* release node */
+ ieee80211_free_node(in);
+
+ /*
+ * Arrange to update the last rx timestamp only for
+ * frames from our ap when operating in station mode.
+ * This assumes the rx key is always setup when associated.
+ */
+ if (ic->ic_opmode == IEEE80211_M_STA &&
+ rs->rs_keyix != ATH9K_RXKEYIX_INVALID) {
+ ngood++;
+ }
+
+ /*
+ * change the default rx antenna if rx diversity chooses the
+ * other antenna 3 times in a row.
+ */
+ if (sc->sc_defant != ds->ds_rxstat.rs_antenna) {
+ if (++sc->sc_rxotherant >= 3) {
+ ath9k_hw_setantenna(sc->sc_ah,
+ ds->ds_rxstat.rs_antenna);
+ sc->sc_defant = ds->ds_rxstat.rs_antenna;
+ sc->sc_rxotherant = 0;
+ }
+ } else {
+ sc->sc_rxotherant = 0;
+ }
+
+rx_next:
+ mutex_enter(&sc->sc_rxbuflock);
+ list_insert_tail(&sc->sc_rxbuf_list, bf);
+ mutex_exit(&sc->sc_rxbuflock);
+ arn_rx_buf_link(sc, bf);
+ } while (loop);
+
+ if (ngood)
+ sc->sc_lastrx = ath9k_hw_gettsf64(ah);
+
+#undef PA2DESC
+}
+
+uint_t
+arn_softint_handler(caddr_t data)
+{
+ struct arn_softc *sc = (struct arn_softc *)data;
+
+ ARN_LOCK(sc);
+
+ if (sc->sc_rx_pend) {
+ /* Soft interrupt for this driver */
+ sc->sc_rx_pend = 0;
+ ARN_UNLOCK(sc);
+ arn_rx_handler(sc);
+ return (DDI_INTR_CLAIMED);
+ }
+
+ ARN_UNLOCK(sc);
+
+ return (DDI_INTR_UNCLAIMED);
+}
diff --git a/usr/src/uts/common/io/arn/arn_reg.h b/usr/src/uts/common/io/arn/arn_reg.h
new file mode 100644
index 0000000000..bc924284a6
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_reg.h
@@ -0,0 +1,1485 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARN_REG_H
+#define _ARN_REG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AR_CR 0x0008
+#define AR_CR_RXE 0x00000004
+#define AR_CR_RXD 0x00000020
+#define AR_CR_SWI 0x00000040
+
+#define AR_RXDP 0x000C
+
+#define AR_CFG 0x0014
+#define AR_CFG_SWTD 0x00000001
+#define AR_CFG_SWTB 0x00000002
+#define AR_CFG_SWRD 0x00000004
+#define AR_CFG_SWRB 0x00000008
+#define AR_CFG_SWRG 0x00000010
+#define AR_CFG_AP_ADHOC_INDICATION 0x00000020
+#define AR_CFG_PHOK 0x00000100
+#define AR_CFG_CLK_GATE_DIS 0x00000400
+#define AR_CFG_EEBS 0x00000200
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17
+
+#define AR_MIRT 0x0020
+#define AR_MIRT_VAL 0x0000ffff
+#define AR_MIRT_VAL_S 16
+
+#define AR_IER 0x0024
+#define AR_IER_ENABLE 0x00000001
+#define AR_IER_DISABLE 0x00000000
+
+#define AR_TIMT 0x0028
+#define AR_TIMT_LAST 0x0000ffff
+#define AR_TIMT_LAST_S 0
+#define AR_TIMT_FIRST 0xffff0000
+#define AR_TIMT_FIRST_S 16
+
+#define AR_RIMT 0x002C
+#define AR_RIMT_LAST 0x0000ffff
+#define AR_RIMT_LAST_S 0
+#define AR_RIMT_FIRST 0xffff0000
+#define AR_RIMT_FIRST_S 16
+
+#define AR_DMASIZE_4B 0x00000000
+#define AR_DMASIZE_8B 0x00000001
+#define AR_DMASIZE_16B 0x00000002
+#define AR_DMASIZE_32B 0x00000003
+#define AR_DMASIZE_64B 0x00000004
+#define AR_DMASIZE_128B 0x00000005
+#define AR_DMASIZE_256B 0x00000006
+#define AR_DMASIZE_512B 0x00000007
+
+#define AR_TXCFG 0x0030
+#define AR_TXCFG_DMASZ_MASK 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_FTRIG 0x000003F0
+#define AR_FTRIG_S 4
+#define AR_FTRIG_IMMED 0x00000000
+#define AR_FTRIG_64B 0x00000010
+#define AR_FTRIG_128B 0x00000020
+#define AR_FTRIG_192B 0x00000030
+#define AR_FTRIG_256B 0x00000040
+#define AR_FTRIG_512B 0x00000080
+#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800
+
+#define AR_RXCFG 0x0034
+#define AR_RXCFG_CHIRP 0x00000008
+#define AR_RXCFG_ZLFDMA 0x00000010
+#define AR_RXCFG_DMASZ_MASK 0x00000007
+#define AR_RXCFG_DMASZ_4B 0
+#define AR_RXCFG_DMASZ_8B 1
+#define AR_RXCFG_DMASZ_16B 2
+#define AR_RXCFG_DMASZ_32B 3
+#define AR_RXCFG_DMASZ_64B 4
+#define AR_RXCFG_DMASZ_128B 5
+#define AR_RXCFG_DMASZ_256B 6
+#define AR_RXCFG_DMASZ_512B 7
+
+#define AR_MIBC 0x0040
+#define AR_MIBC_COW 0x00000001
+#define AR_MIBC_FMC 0x00000002
+#define AR_MIBC_CMC 0x00000004
+#define AR_MIBC_MCS 0x00000008
+
+#define AR_TOPS 0x0044
+#define AR_TOPS_MASK 0x0000FFFF
+
+#define AR_RXNPTO 0x0048
+#define AR_RXNPTO_MASK 0x000003FF
+
+#define AR_TXNPTO 0x004C
+#define AR_TXNPTO_MASK 0x000003FF
+#define AR_TXNPTO_QCU_MASK 0x000FFC00
+
+#define AR_RPGTO 0x0050
+#define AR_RPGTO_MASK 0x000003FF
+
+#define AR_RPCNT 0x0054
+#define AR_RPCNT_MASK 0x0000001F
+
+#define AR_MACMISC 0x0058
+#define AR_MACMISC_PCI_EXT_FORCE 0x00000010
+#define AR_MACMISC_DMA_OBS 0x000001E0
+#define AR_MACMISC_DMA_OBS_S 5
+#define AR_MACMISC_DMA_OBS_LINE_0 0
+#define AR_MACMISC_DMA_OBS_LINE_1 1
+#define AR_MACMISC_DMA_OBS_LINE_2 2
+#define AR_MACMISC_DMA_OBS_LINE_3 3
+#define AR_MACMISC_DMA_OBS_LINE_4 4
+#define AR_MACMISC_DMA_OBS_LINE_5 5
+#define AR_MACMISC_DMA_OBS_LINE_6 6
+#define AR_MACMISC_DMA_OBS_LINE_7 7
+#define AR_MACMISC_DMA_OBS_LINE_8 8
+#define AR_MACMISC_MISC_OBS 0x00000E00
+#define AR_MACMISC_MISC_OBS_S 9
+#define AR_MACMISC_MISC_OBS_BUS_LSB 0x00007000
+#define AR_MACMISC_MISC_OBS_BUS_LSB_S 12
+#define AR_MACMISC_MISC_OBS_BUS_MSB 0x00038000
+#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15
+#define AR_MACMISC_MISC_OBS_BUS_1 1
+
+#define AR_GTXTO 0x0064
+#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF
+#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000
+#define AR_GTXTO_TIMEOUT_LIMIT_S 16
+
+#define AR_GTTM 0x0068
+#define AR_GTTM_USEC 0x00000001
+#define AR_GTTM_IGNORE_IDLE 0x00000002
+#define AR_GTTM_RESET_IDLE 0x00000004
+#define AR_GTTM_CST_USEC 0x00000008
+
+#define AR_CST 0x006C
+#define AR_CST_TIMEOUT_COUNTER 0x0000FFFF
+#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000
+#define AR_CST_TIMEOUT_LIMIT_S 16
+
+#define AR_SREV_VERSION_9100 0x014
+
+#define AR_SREV_5416_V20_OR_LATER(_ah) \
+ (AR_SREV_9100((_ah)) || AR_SREV_5416_20_OR_LATER(_ah))
+#define AR_SREV_5416_V22_OR_LATER(_ah) \
+ (AR_SREV_9100((_ah)) || AR_SREV_5416_22_OR_LATER(_ah))
+
+#define AR_ISR 0x0080
+#define AR_ISR_RXOK 0x00000001
+#define AR_ISR_RXDESC 0x00000002
+#define AR_ISR_RXERR 0x00000004
+#define AR_ISR_RXNOPKT 0x00000008
+#define AR_ISR_RXEOL 0x00000010
+#define AR_ISR_RXORN 0x00000020
+#define AR_ISR_TXOK 0x00000040
+#define AR_ISR_TXDESC 0x00000080
+#define AR_ISR_TXERR 0x00000100
+#define AR_ISR_TXNOPKT 0x00000200
+#define AR_ISR_TXEOL 0x00000400
+#define AR_ISR_TXURN 0x00000800
+#define AR_ISR_MIB 0x00001000
+#define AR_ISR_SWI 0x00002000
+#define AR_ISR_RXPHY 0x00004000
+#define AR_ISR_RXKCM 0x00008000
+#define AR_ISR_SWBA 0x00010000
+#define AR_ISR_BRSSI 0x00020000
+#define AR_ISR_BMISS 0x00040000
+#define AR_ISR_BNR 0x00100000
+#define AR_ISR_RXCHIRP 0x00200000
+#define AR_ISR_BCNMISC 0x00800000
+#define AR_ISR_TIM 0x00800000
+#define AR_ISR_QCBROVF 0x02000000
+#define AR_ISR_QCBRURN 0x04000000
+#define AR_ISR_QTRIG 0x08000000
+#define AR_ISR_GENTMR 0x10000000
+
+#define AR_ISR_TXMINTR 0x00080000
+#define AR_ISR_RXMINTR 0x01000000
+#define AR_ISR_TXINTM 0x40000000
+#define AR_ISR_RXINTM 0x80000000
+
+#define AR_ISR_S0 0x0084
+#define AR_ISR_S0_QCU_TXOK 0x000003FF
+#define AR_ISR_S0_QCU_TXOK_S 0
+#define AR_ISR_S0_QCU_TXDESC 0x03FF0000
+#define AR_ISR_S0_QCU_TXDESC_S 16
+
+#define AR_ISR_S1 0x0088
+#define AR_ISR_S1_QCU_TXERR 0x000003FF
+#define AR_ISR_S1_QCU_TXERR_S 0
+#define AR_ISR_S1_QCU_TXEOL 0x03FF0000
+#define AR_ISR_S1_QCU_TXEOL_S 16
+
+#define AR_ISR_S2 0x008c
+#define AR_ISR_S2_QCU_TXURN 0x000003FF
+#define AR_ISR_S2_CST 0x00400000
+#define AR_ISR_S2_GTT 0x00800000
+#define AR_ISR_S2_TIM 0x01000000
+#define AR_ISR_S2_CABEND 0x02000000
+#define AR_ISR_S2_DTIMSYNC 0x04000000
+#define AR_ISR_S2_BCNTO 0x08000000
+#define AR_ISR_S2_CABTO 0x10000000
+#define AR_ISR_S2_DTIM 0x20000000
+#define AR_ISR_S2_TSFOOR 0x40000000
+#define AR_ISR_S2_TBTT_TIME 0x80000000
+
+#define AR_ISR_S3 0x0090
+#define AR_ISR_S3_QCU_QCBROVF 0x000003FF
+#define AR_ISR_S3_QCU_QCBRURN 0x03FF0000
+
+#define AR_ISR_S4 0x0094
+#define AR_ISR_S4_QCU_QTRIG 0x000003FF
+#define AR_ISR_S4_RESV0 0xFFFFFC00
+
+#define AR_ISR_S5 0x0098
+#define AR_ISR_S5_TIMER_TRIG 0x000000FF
+#define AR_ISR_S5_TIMER_THRESH 0x0007FE00
+#define AR_ISR_S5_TIM_TIMER 0x00000010
+#define AR_ISR_S5_DTIM_TIMER 0x00000020
+#define AR_ISR_S5_S 0x00d8
+#define AR_IMR_S5 0x00b8
+#define AR_IMR_S5_TIM_TIMER 0x00000010
+#define AR_IMR_S5_DTIM_TIMER 0x00000020
+
+
+#define AR_IMR 0x00a0
+#define AR_IMR_RXOK 0x00000001
+#define AR_IMR_RXDESC 0x00000002
+#define AR_IMR_RXERR 0x00000004
+#define AR_IMR_RXNOPKT 0x00000008
+#define AR_IMR_RXEOL 0x00000010
+#define AR_IMR_RXORN 0x00000020
+#define AR_IMR_TXOK 0x00000040
+#define AR_IMR_TXDESC 0x00000080
+#define AR_IMR_TXERR 0x00000100
+#define AR_IMR_TXNOPKT 0x00000200
+#define AR_IMR_TXEOL 0x00000400
+#define AR_IMR_TXURN 0x00000800
+#define AR_IMR_MIB 0x00001000
+#define AR_IMR_SWI 0x00002000
+#define AR_IMR_RXPHY 0x00004000
+#define AR_IMR_RXKCM 0x00008000
+#define AR_IMR_SWBA 0x00010000
+#define AR_IMR_BRSSI 0x00020000
+#define AR_IMR_BMISS 0x00040000
+#define AR_IMR_BNR 0x00100000
+#define AR_IMR_RXCHIRP 0x00200000
+#define AR_IMR_BCNMISC 0x00800000
+#define AR_IMR_TIM 0x00800000
+#define AR_IMR_QCBROVF 0x02000000
+#define AR_IMR_QCBRURN 0x04000000
+#define AR_IMR_QTRIG 0x08000000
+#define AR_IMR_GENTMR 0x10000000
+
+#define AR_IMR_TXMINTR 0x00080000
+#define AR_IMR_RXMINTR 0x01000000
+#define AR_IMR_TXINTM 0x40000000
+#define AR_IMR_RXINTM 0x80000000
+
+#define AR_IMR_S0 0x00a4
+#define AR_IMR_S0_QCU_TXOK 0x000003FF
+#define AR_IMR_S0_QCU_TXOK_S 0
+#define AR_IMR_S0_QCU_TXDESC 0x03FF0000
+#define AR_IMR_S0_QCU_TXDESC_S 16
+
+#define AR_IMR_S1 0x00a8
+#define AR_IMR_S1_QCU_TXERR 0x000003FF
+#define AR_IMR_S1_QCU_TXERR_S 0
+#define AR_IMR_S1_QCU_TXEOL 0x03FF0000
+#define AR_IMR_S1_QCU_TXEOL_S 16
+
+#define AR_IMR_S2 0x00ac
+#define AR_IMR_S2_QCU_TXURN 0x000003FF
+#define AR_IMR_S2_QCU_TXURN_S 0
+#define AR_IMR_S2_CST 0x00400000
+#define AR_IMR_S2_GTT 0x00800000
+#define AR_IMR_S2_TIM 0x01000000
+#define AR_IMR_S2_CABEND 0x02000000
+#define AR_IMR_S2_DTIMSYNC 0x04000000
+#define AR_IMR_S2_BCNTO 0x08000000
+#define AR_IMR_S2_CABTO 0x10000000
+#define AR_IMR_S2_DTIM 0x20000000
+#define AR_IMR_S2_TSFOOR 0x40000000
+
+#define AR_IMR_S3 0x00b0
+#define AR_IMR_S3_QCU_QCBROVF 0x000003FF
+#define AR_IMR_S3_QCU_QCBRURN 0x03FF0000
+#define AR_IMR_S3_QCU_QCBRURN_S 16
+
+#define AR_IMR_S4 0x00b4
+#define AR_IMR_S4_QCU_QTRIG 0x000003FF
+#define AR_IMR_S4_RESV0 0xFFFFFC00
+
+#define AR_IMR_S5 0x00b8
+#define AR_IMR_S5_TIMER_TRIG 0x000000FF
+#define AR_IMR_S5_TIMER_THRESH 0x0000FF00
+
+
+#define AR_ISR_RAC 0x00c0
+#define AR_ISR_S0_S 0x00c4
+#define AR_ISR_S0_QCU_TXOK 0x000003FF
+#define AR_ISR_S0_QCU_TXOK_S 0
+#define AR_ISR_S0_QCU_TXDESC 0x03FF0000
+#define AR_ISR_S0_QCU_TXDESC_S 16
+
+#define AR_ISR_S1_S 0x00c8
+#define AR_ISR_S1_QCU_TXERR 0x000003FF
+#define AR_ISR_S1_QCU_TXERR_S 0
+#define AR_ISR_S1_QCU_TXEOL 0x03FF0000
+#define AR_ISR_S1_QCU_TXEOL_S 16
+
+#define AR_ISR_S2_S 0x00cc
+#define AR_ISR_S3_S 0x00d0
+#define AR_ISR_S4_S 0x00d4
+#define AR_ISR_S5_S 0x00d8
+#define AR_DMADBG_0 0x00e0
+#define AR_DMADBG_1 0x00e4
+#define AR_DMADBG_2 0x00e8
+#define AR_DMADBG_3 0x00ec
+#define AR_DMADBG_4 0x00f0
+#define AR_DMADBG_5 0x00f4
+#define AR_DMADBG_6 0x00f8
+#define AR_DMADBG_7 0x00fc
+
+#define AR_NUM_QCU 10
+#define AR_QCU_0 0x0001
+#define AR_QCU_1 0x0002
+#define AR_QCU_2 0x0004
+#define AR_QCU_3 0x0008
+#define AR_QCU_4 0x0010
+#define AR_QCU_5 0x0020
+#define AR_QCU_6 0x0040
+#define AR_QCU_7 0x0080
+#define AR_QCU_8 0x0100
+#define AR_QCU_9 0x0200
+
+#define AR_Q0_TXDP 0x0800
+#define AR_Q1_TXDP 0x0804
+#define AR_Q2_TXDP 0x0808
+#define AR_Q3_TXDP 0x080c
+#define AR_Q4_TXDP 0x0810
+#define AR_Q5_TXDP 0x0814
+#define AR_Q6_TXDP 0x0818
+#define AR_Q7_TXDP 0x081c
+#define AR_Q8_TXDP 0x0820
+#define AR_Q9_TXDP 0x0824
+#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2))
+
+#define AR_Q_TXE 0x0840
+#define AR_Q_TXE_M 0x000003FF
+
+#define AR_Q_TXD 0x0880
+#define AR_Q_TXD_M 0x000003FF
+
+#define AR_Q0_CBRCFG 0x08c0
+#define AR_Q1_CBRCFG 0x08c4
+#define AR_Q2_CBRCFG 0x08c8
+#define AR_Q3_CBRCFG 0x08cc
+#define AR_Q4_CBRCFG 0x08d0
+#define AR_Q5_CBRCFG 0x08d4
+#define AR_Q6_CBRCFG 0x08d8
+#define AR_Q7_CBRCFG 0x08dc
+#define AR_Q8_CBRCFG 0x08e0
+#define AR_Q9_CBRCFG 0x08e4
+#define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2))
+#define AR_Q_CBRCFG_INTERVAL 0x00FFFFFF
+#define AR_Q_CBRCFG_INTERVAL_S 0
+#define AR_Q_CBRCFG_OVF_THRESH 0xFF000000
+#define AR_Q_CBRCFG_OVF_THRESH_S 24
+
+#define AR_Q0_RDYTIMECFG 0x0900
+#define AR_Q1_RDYTIMECFG 0x0904
+#define AR_Q2_RDYTIMECFG 0x0908
+#define AR_Q3_RDYTIMECFG 0x090c
+#define AR_Q4_RDYTIMECFG 0x0910
+#define AR_Q5_RDYTIMECFG 0x0914
+#define AR_Q6_RDYTIMECFG 0x0918
+#define AR_Q7_RDYTIMECFG 0x091c
+#define AR_Q8_RDYTIMECFG 0x0920
+#define AR_Q9_RDYTIMECFG 0x0924
+#define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2))
+#define AR_Q_RDYTIMECFG_DURATION 0x00FFFFFF
+#define AR_Q_RDYTIMECFG_DURATION_S 0
+#define AR_Q_RDYTIMECFG_EN 0x01000000
+
+#define AR_Q_ONESHOTARM_SC 0x0940
+#define AR_Q_ONESHOTARM_SC_M 0x000003FF
+#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00
+
+#define AR_Q_ONESHOTARM_CC 0x0980
+#define AR_Q_ONESHOTARM_CC_M 0x000003FF
+#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00
+
+#define AR_Q0_MISC 0x09c0
+#define AR_Q1_MISC 0x09c4
+#define AR_Q2_MISC 0x09c8
+#define AR_Q3_MISC 0x09cc
+#define AR_Q4_MISC 0x09d0
+#define AR_Q5_MISC 0x09d4
+#define AR_Q6_MISC 0x09d8
+#define AR_Q7_MISC 0x09dc
+#define AR_Q8_MISC 0x09e0
+#define AR_Q9_MISC 0x09e4
+#define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2))
+#define AR_Q_MISC_FSP 0x0000000F
+#define AR_Q_MISC_FSP_ASAP 0
+#define AR_Q_MISC_FSP_CBR 1
+#define AR_Q_MISC_FSP_DBA_GATED 2
+#define AR_Q_MISC_FSP_TIM_GATED 3
+#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4
+#define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5
+#define AR_Q_MISC_ONE_SHOT_EN 0x00000010
+#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020
+#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040
+#define AR_Q_MISC_BEACON_USE 0x00000080
+#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100
+#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200
+#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400
+#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800
+#define AR_Q_MISC_RESV0 0xFFFFF000
+
+#define AR_Q0_STS 0x0a00
+#define AR_Q1_STS 0x0a04
+#define AR_Q2_STS 0x0a08
+#define AR_Q3_STS 0x0a0c
+#define AR_Q4_STS 0x0a10
+#define AR_Q5_STS 0x0a14
+#define AR_Q6_STS 0x0a18
+#define AR_Q7_STS 0x0a1c
+#define AR_Q8_STS 0x0a20
+#define AR_Q9_STS 0x0a24
+#define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2))
+#define AR_Q_STS_PEND_FR_CNT 0x00000003
+#define AR_Q_STS_RESV0 0x000000FC
+#define AR_Q_STS_CBR_EXP_CNT 0x0000FF00
+#define AR_Q_STS_RESV1 0xFFFF0000
+
+#define AR_Q_RDYTIMESHDN 0x0a40
+#define AR_Q_RDYTIMESHDN_M 0x000003FF
+
+
+#define AR_NUM_DCU 10
+#define AR_DCU_0 0x0001
+#define AR_DCU_1 0x0002
+#define AR_DCU_2 0x0004
+#define AR_DCU_3 0x0008
+#define AR_DCU_4 0x0010
+#define AR_DCU_5 0x0020
+#define AR_DCU_6 0x0040
+#define AR_DCU_7 0x0080
+#define AR_DCU_8 0x0100
+#define AR_DCU_9 0x0200
+
+#define AR_D0_QCUMASK 0x1000
+#define AR_D1_QCUMASK 0x1004
+#define AR_D2_QCUMASK 0x1008
+#define AR_D3_QCUMASK 0x100c
+#define AR_D4_QCUMASK 0x1010
+#define AR_D5_QCUMASK 0x1014
+#define AR_D6_QCUMASK 0x1018
+#define AR_D7_QCUMASK 0x101c
+#define AR_D8_QCUMASK 0x1020
+#define AR_D9_QCUMASK 0x1024
+#define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2))
+#define AR_D_QCUMASK 0x000003FF
+#define AR_D_QCUMASK_RESV0 0xFFFFFC00
+
+#define AR_D_TXBLK_CMD 0x1038
+#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i))
+
+#define AR_D0_LCL_IFS 0x1040
+#define AR_D1_LCL_IFS 0x1044
+#define AR_D2_LCL_IFS 0x1048
+#define AR_D3_LCL_IFS 0x104c
+#define AR_D4_LCL_IFS 0x1050
+#define AR_D5_LCL_IFS 0x1054
+#define AR_D6_LCL_IFS 0x1058
+#define AR_D7_LCL_IFS 0x105c
+#define AR_D8_LCL_IFS 0x1060
+#define AR_D9_LCL_IFS 0x1064
+#define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2))
+#define AR_D_LCL_IFS_CWMIN 0x000003FF
+#define AR_D_LCL_IFS_CWMIN_S 0
+#define AR_D_LCL_IFS_CWMAX 0x000FFC00
+#define AR_D_LCL_IFS_CWMAX_S 10
+#define AR_D_LCL_IFS_AIFS 0x0FF00000
+#define AR_D_LCL_IFS_AIFS_S 20
+
+#define AR_D_LCL_IFS_RESV0 0xF0000000
+
+#define AR_D0_RETRY_LIMIT 0x1080
+#define AR_D1_RETRY_LIMIT 0x1084
+#define AR_D2_RETRY_LIMIT 0x1088
+#define AR_D3_RETRY_LIMIT 0x108c
+#define AR_D4_RETRY_LIMIT 0x1090
+#define AR_D5_RETRY_LIMIT 0x1094
+#define AR_D6_RETRY_LIMIT 0x1098
+#define AR_D7_RETRY_LIMIT 0x109c
+#define AR_D8_RETRY_LIMIT 0x10a0
+#define AR_D9_RETRY_LIMIT 0x10a4
+#define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2))
+#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F
+#define AR_D_RETRY_LIMIT_FR_SH_S 0
+#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00
+#define AR_D_RETRY_LIMIT_STA_SH_S 8
+#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000
+#define AR_D_RETRY_LIMIT_STA_LG_S 14
+#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000
+
+#define AR_D0_CHNTIME 0x10c0
+#define AR_D1_CHNTIME 0x10c4
+#define AR_D2_CHNTIME 0x10c8
+#define AR_D3_CHNTIME 0x10cc
+#define AR_D4_CHNTIME 0x10d0
+#define AR_D5_CHNTIME 0x10d4
+#define AR_D6_CHNTIME 0x10d8
+#define AR_D7_CHNTIME 0x10dc
+#define AR_D8_CHNTIME 0x10e0
+#define AR_D9_CHNTIME 0x10e4
+#define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2))
+#define AR_D_CHNTIME_DUR 0x000FFFFF
+#define AR_D_CHNTIME_DUR_S 0
+#define AR_D_CHNTIME_EN 0x00100000
+#define AR_D_CHNTIME_RESV0 0xFFE00000
+
+#define AR_D0_MISC 0x1100
+#define AR_D1_MISC 0x1104
+#define AR_D2_MISC 0x1108
+#define AR_D3_MISC 0x110c
+#define AR_D4_MISC 0x1110
+#define AR_D5_MISC 0x1114
+#define AR_D6_MISC 0x1118
+#define AR_D7_MISC 0x111c
+#define AR_D8_MISC 0x1120
+#define AR_D9_MISC 0x1124
+#define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2))
+#define AR_D_MISC_BKOFF_THRESH 0x0000003F
+#define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040
+#define AR_D_MISC_CW_RESET_EN 0x00000080
+#define AR_D_MISC_FRAG_WAIT_EN 0x00000100
+#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200
+#define AR_D_MISC_CW_BKOFF_EN 0x00001000
+#define AR_D_MISC_VIR_COL_HANDLING 0x0000C000
+#define AR_D_MISC_VIR_COL_HANDLING_S 14
+#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0
+#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1
+#define AR_D_MISC_BEACON_USE 0x00010000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2
+#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000
+#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000
+#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000
+#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000
+#define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000
+#define AR_D_MISC_RESV0 0xFF000000
+
+#define AR_D_SEQNUM 0x1140
+
+#define AR_D_GBL_IFS_SIFS 0x1030
+#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF
+#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF
+
+#define AR_D_TXBLK_BASE 0x1038
+#define AR_D_TXBLK_WRITE_BITMASK 0x0000FFFF
+#define AR_D_TXBLK_WRITE_BITMASK_S 0
+#define AR_D_TXBLK_WRITE_SLICE 0x000F0000
+#define AR_D_TXBLK_WRITE_SLICE_S 16
+#define AR_D_TXBLK_WRITE_DCU 0x00F00000
+#define AR_D_TXBLK_WRITE_DCU_S 20
+#define AR_D_TXBLK_WRITE_COMMAND 0x0F000000
+#define AR_D_TXBLK_WRITE_COMMAND_S 24
+
+#define AR_D_GBL_IFS_SLOT 0x1070
+#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF
+#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000
+
+#define AR_D_GBL_IFS_EIFS 0x10b0
+#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF
+#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000
+
+#define AR_D_GBL_IFS_MISC 0x10f0
+#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
+#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008
+#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00
+#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000
+#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000
+#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000
+#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000
+#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000
+
+#define AR_D_FPCTL 0x1230
+#define AR_D_FPCTL_DCU 0x0000000F
+#define AR_D_FPCTL_DCU_S 0
+#define AR_D_FPCTL_PREFETCH_EN 0x00000010
+#define AR_D_FPCTL_BURST_PREFETCH 0x00007FE0
+#define AR_D_FPCTL_BURST_PREFETCH_S 5
+
+#define AR_D_TXPSE 0x1270
+#define AR_D_TXPSE_CTRL 0x000003FF
+#define AR_D_TXPSE_RESV0 0x0000FC00
+#define AR_D_TXPSE_STATUS 0x00010000
+#define AR_D_TXPSE_RESV1 0xFFFE0000
+
+#define AR_D_TXSLOTMASK 0x12f0
+#define AR_D_TXSLOTMASK_NUM 0x0000000F
+
+#define AR_CFG_LED 0x1f04
+#define AR_CFG_SCLK_RATE_IND 0x00000003
+#define AR_CFG_SCLK_RATE_IND_S 0
+#define AR_CFG_SCLK_32MHZ 0x00000000
+#define AR_CFG_SCLK_4MHZ 0x00000001
+#define AR_CFG_SCLK_1MHZ 0x00000002
+#define AR_CFG_SCLK_32KHZ 0x00000003
+#define AR_CFG_LED_BLINK_SLOW 0x00000008
+#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070
+#define AR_CFG_LED_MODE_SEL 0x00000380
+#define AR_CFG_LED_MODE_SEL_S 7
+#define AR_CFG_LED_POWER 0x00000280
+#define AR_CFG_LED_POWER_S 7
+#define AR_CFG_LED_NETWORK 0x00000300
+#define AR_CFG_LED_NETWORK_S 7
+#define AR_CFG_LED_MODE_PROP 0x0
+#define AR_CFG_LED_MODE_RPROP 0x1
+#define AR_CFG_LED_MODE_SPLIT 0x2
+#define AR_CFG_LED_MODE_RAND 0x3
+#define AR_CFG_LED_MODE_POWER_OFF 0x4
+#define AR_CFG_LED_MODE_POWER_ON 0x5
+#define AR_CFG_LED_MODE_NETWORK_OFF 0x4
+#define AR_CFG_LED_MODE_NETWORK_ON 0x6
+#define AR_CFG_LED_ASSOC_CTL 0x00000c00
+#define AR_CFG_LED_ASSOC_CTL_S 10
+#define AR_CFG_LED_ASSOC_NONE 0x0
+#define AR_CFG_LED_ASSOC_ACTIVE 0x1
+#define AR_CFG_LED_ASSOC_PENDING 0x2
+
+#define AR_CFG_LED_BLINK_SLOW 0x00000008
+#define AR_CFG_LED_BLINK_SLOW_S 3
+
+#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070
+#define AR_CFG_LED_BLINK_THRESH_SEL_S 4
+
+#define AR_MAC_SLEEP 0x1f00
+#define AR_MAC_SLEEP_MAC_AWAKE 0x00000000
+#define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001
+
+#define AR_RC 0x4000
+#define AR_RC_AHB 0x00000001
+#define AR_RC_APB 0x00000002
+#define AR_RC_HOSTIF 0x00000100
+
+#define AR_WA 0x4004
+#define AR9285_WA_DEFAULT 0x004a05cb
+#define AR9280_WA_DEFAULT 0x0040073f
+#define AR_WA_DEFAULT 0x0000073f
+
+#define AR_PM_STATE 0x4008
+#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
+
+#define AR_HOST_TIMEOUT 0x4018
+#define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF
+#define AR_HOST_TIMEOUT_APB_CNTR_S 0
+#define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000
+#define AR_HOST_TIMEOUT_LCL_CNTR_S 16
+
+#define AR_EEPROM 0x401c
+#define AR_EEPROM_ABSENT 0x00000100
+#define AR_EEPROM_CORRUPT 0x00000200
+#define AR_EEPROM_PROT_MASK 0x03FFFC00
+#define AR_EEPROM_PROT_MASK_S 10
+
+#define EEPROM_PROTECT_RP_0_31 0x0001
+#define EEPROM_PROTECT_WP_0_31 0x0002
+#define EEPROM_PROTECT_RP_32_63 0x0004
+#define EEPROM_PROTECT_WP_32_63 0x0008
+#define EEPROM_PROTECT_RP_64_127 0x0010
+#define EEPROM_PROTECT_WP_64_127 0x0020
+#define EEPROM_PROTECT_RP_128_191 0x0040
+#define EEPROM_PROTECT_WP_128_191 0x0080
+#define EEPROM_PROTECT_RP_192_255 0x0100
+#define EEPROM_PROTECT_WP_192_255 0x0200
+#define EEPROM_PROTECT_RP_256_511 0x0400
+#define EEPROM_PROTECT_WP_256_511 0x0800
+#define EEPROM_PROTECT_RP_512_1023 0x1000
+#define EEPROM_PROTECT_WP_512_1023 0x2000
+#define EEPROM_PROTECT_RP_1024_2047 0x4000
+#define EEPROM_PROTECT_WP_1024_2047 0x8000
+
+#define AR_SREV \
+ ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020)
+
+#define AR_SREV_ID \
+ ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF)
+#define AR_SREV_VERSION 0x000000F0
+#define AR_SREV_VERSION_S 4
+#define AR_SREV_REVISION 0x00000007
+
+#define AR_SREV_ID2 0xFFFFFFFF
+#define AR_SREV_VERSION2 0xFFFC0000
+#define AR_SREV_VERSION2_S 18
+#define AR_SREV_TYPE2 0x0003F000
+#define AR_SREV_TYPE2_S 12
+#define AR_SREV_TYPE2_CHAIN 0x00001000
+#define AR_SREV_TYPE2_HOST_MODE 0x00002000
+#define AR_SREV_REVISION2 0x00000F00
+#define AR_SREV_REVISION2_S 8
+
+#define AR_SREV_VERSION_5416_PCI 0xD
+#define AR_SREV_VERSION_5416_PCIE 0xC
+#define AR_SREV_REVISION_5416_10 0
+#define AR_SREV_REVISION_5416_20 1
+#define AR_SREV_REVISION_5416_22 2
+#define AR_SREV_VERSION_9160 0x40
+#define AR_SREV_REVISION_9160_10 0
+#define AR_SREV_REVISION_9160_11 1
+#define AR_SREV_VERSION_9280 0x80
+#define AR_SREV_REVISION_9280_10 0
+#define AR_SREV_REVISION_9280_20 1
+#define AR_SREV_REVISION_9280_21 2
+#define AR_SREV_VERSION_9285 0xC0
+#define AR_SREV_REVISION_9285_10 0
+#define AR_SREV_REVISION_9285_11 1
+#define AR_SREV_REVISION_9285_12 2
+
+#define AR_SREV_9100_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion >= AR_SREV_VERSION_5416_PCIE))
+#define AR_SREV_5416_20_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion >= AR_SREV_VERSION_9160) || \
+ ((_ah)->ah_macRev >= AR_SREV_REVISION_5416_20))
+#define AR_SREV_5416_22_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion >= AR_SREV_VERSION_9160) || \
+ ((_ah)->ah_macRev >= AR_SREV_REVISION_5416_22))
+#define AR_SREV_9160(_ah) \
+ (((_ah)->ah_macVersion == AR_SREV_VERSION_9160))
+#define AR_SREV_9160_10_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion >= AR_SREV_VERSION_9160))
+#define AR_SREV_9160_11(_ah) \
+ (AR_SREV_9160(_ah) && ((_ah)->ah_macRev == AR_SREV_REVISION_9160_11))
+#define AR_SREV_9280(_ah) \
+ (((_ah)->ah_macVersion == AR_SREV_VERSION_9280))
+#define AR_SREV_9280_10_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion >= AR_SREV_VERSION_9280))
+#define AR_SREV_9280_20(_ah) \
+ (((_ah)->ah_macVersion == AR_SREV_VERSION_9280) && \
+ ((_ah)->ah_macRev >= AR_SREV_REVISION_9280_20))
+#define AR_SREV_9280_20_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion > AR_SREV_VERSION_9280) || \
+ (((_ah)->ah_macVersion == AR_SREV_VERSION_9280) && \
+ ((_ah)->ah_macRev >= AR_SREV_REVISION_9280_20)))
+
+#define AR_SREV_9285(_ah) (((_ah)->ah_macVersion == AR_SREV_VERSION_9285))
+#define AR_SREV_9285_10_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion >= AR_SREV_VERSION_9285))
+#define AR_SREV_9285_11(_ah) \
+ (AR_SREV_9280(ah) && ((_ah)->ah_macRev == AR_SREV_REVISION_9285_11))
+#define AR_SREV_9285_11_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion > AR_SREV_VERSION_9285) || \
+ (AR_SREV_9285(ah) && ((_ah)->ah_macRev >= AR_SREV_REVISION_9285_11)))
+#define AR_SREV_9285_12(_ah) \
+ (AR_SREV_9280(ah) && ((_ah)->ah_macRev == AR_SREV_REVISION_9285_12))
+#define AR_SREV_9285_12_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion > AR_SREV_VERSION_9285) || \
+ (AR_SREV_9285(ah) && ((_ah)->ah_macRev >= AR_SREV_REVISION_9285_12)))
+
+#define AR_RADIO_SREV_MAJOR 0xf0
+#define AR_RAD5133_SREV_MAJOR 0xc0
+#define AR_RAD2133_SREV_MAJOR 0xd0
+#define AR_RAD5122_SREV_MAJOR 0xe0
+#define AR_RAD2122_SREV_MAJOR 0xf0
+
+#define AR_AHB_MODE 0x4024
+#define AR_AHB_EXACT_WR_EN 0x00000000
+#define AR_AHB_BUF_WR_EN 0x00000001
+#define AR_AHB_EXACT_RD_EN 0x00000000
+#define AR_AHB_CACHELINE_RD_EN 0x00000002
+#define AR_AHB_PREFETCH_RD_EN 0x00000004
+#define AR_AHB_PAGE_SIZE_1K 0x00000000
+#define AR_AHB_PAGE_SIZE_2K 0x00000008
+#define AR_AHB_PAGE_SIZE_4K 0x00000010
+
+#define AR_INTR_RTC_IRQ 0x00000001
+#define AR_INTR_MAC_IRQ 0x00000002
+#define AR_INTR_EEP_PROT_ACCESS 0x00000004
+#define AR_INTR_MAC_AWAKE 0x00020000
+#define AR_INTR_MAC_ASLEEP 0x00040000
+#define AR_INTR_SPURIOUS 0xFFFFFFFF
+
+
+#define AR_INTR_SYNC_CAUSE_CLR 0x4028
+
+#define AR_INTR_SYNC_CAUSE 0x4028
+
+#define AR_INTR_SYNC_ENABLE 0x402c
+#define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000
+#define AR_INTR_SYNC_ENABLE_GPIO_S 18
+
+enum {
+ AR_INTR_SYNC_RTC_IRQ = 0x00000001,
+ AR_INTR_SYNC_MAC_IRQ = 0x00000002,
+ AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004,
+ AR_INTR_SYNC_APB_TIMEOUT = 0x00000008,
+ AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010,
+ AR_INTR_SYNC_HOST1_FATAL = 0x00000020,
+ AR_INTR_SYNC_HOST1_PERR = 0x00000040,
+ AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080,
+ AR_INTR_SYNC_RADM_CPL_EP = 0x00000100,
+ AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200,
+ AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400,
+ AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800,
+ AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000,
+ AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000,
+ AR_INTR_SYNC_PM_ACCESS = 0x00004000,
+ AR_INTR_SYNC_MAC_AWAKE = 0x00008000,
+ AR_INTR_SYNC_MAC_ASLEEP = 0x00010000,
+ AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000,
+ AR_INTR_SYNC_ALL = 0x0003FFFF,
+
+
+ AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL |
+ AR_INTR_SYNC_HOST1_PERR |
+ AR_INTR_SYNC_RADM_CPL_EP |
+ AR_INTR_SYNC_RADM_CPL_DLLP_ABORT |
+ AR_INTR_SYNC_RADM_CPL_TLP_ABORT |
+ AR_INTR_SYNC_RADM_CPL_ECRC_ERR |
+ AR_INTR_SYNC_RADM_CPL_TIMEOUT |
+ AR_INTR_SYNC_LOCAL_TIMEOUT |
+ AR_INTR_SYNC_MAC_SLEEP_ACCESS),
+
+ /* AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF, */
+ AR_INTR_SYNC_SPURIOUS = -1,
+
+};
+
+#define AR_INTR_ASYNC_MASK 0x4030
+#define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000
+#define AR_INTR_ASYNC_MASK_GPIO_S 18
+
+#define AR_INTR_SYNC_MASK 0x4034
+#define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000
+#define AR_INTR_SYNC_MASK_GPIO_S 18
+
+#define AR_INTR_ASYNC_CAUSE_CLR 0x4038
+#define AR_INTR_ASYNC_CAUSE 0x4038
+
+#define AR_INTR_ASYNC_ENABLE 0x403c
+#define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000
+#define AR_INTR_ASYNC_ENABLE_GPIO_S 18
+
+#define AR_PCIE_SERDES 0x4040
+#define AR_PCIE_SERDES2 0x4044
+#define AR_PCIE_PM_CTRL 0x4014
+#define AR_PCIE_PM_CTRL_ENA 0x00080000
+
+#define AR_NUM_GPIO 14
+#define AR928X_NUM_GPIO 10
+
+#define AR_GPIO_IN_OUT 0x4048
+#define AR_GPIO_IN_VAL 0x0FFFC000
+#define AR_GPIO_IN_VAL_S 14
+#define AR928X_GPIO_IN_VAL 0x000FFC00
+#define AR928X_GPIO_IN_VAL_S 10
+
+#define AR_GPIO_OE_OUT 0x404c
+#define AR_GPIO_OE_OUT_DRV 0x3
+#define AR_GPIO_OE_OUT_DRV_NO 0x0
+#define AR_GPIO_OE_OUT_DRV_LOW 0x1
+#define AR_GPIO_OE_OUT_DRV_HI 0x2
+#define AR_GPIO_OE_OUT_DRV_ALL 0x3
+
+#define AR_GPIO_INTR_POL 0x4050
+#define AR_GPIO_INTR_POL_VAL 0x00001FFF
+#define AR_GPIO_INTR_POL_VAL_S 0
+
+#define AR_GPIO_INPUT_EN_VAL 0x4054
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15
+#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000
+#define AR_GPIO_JTAG_DISABLE 0x00020000
+
+#define AR_GPIO_INPUT_MUX1 0x4058
+
+#define AR_GPIO_INPUT_MUX2 0x405c
+#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f
+#define AR_GPIO_INPUT_MUX2_CLK25_S 0
+#define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0
+#define AR_GPIO_INPUT_MUX2_RFSILENT_S 4
+#define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00
+#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8
+
+#define AR_GPIO_OUTPUT_MUX1 0x4060
+#define AR_GPIO_OUTPUT_MUX2 0x4064
+#define AR_GPIO_OUTPUT_MUX3 0x4068
+
+#define AR_INPUT_STATE 0x406c
+
+#define AR_EEPROM_STATUS_DATA 0x407c
+#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff
+#define AR_EEPROM_STATUS_DATA_VAL_S 0
+#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000
+#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000
+#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000
+#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000
+
+#define AR_OBS 0x4080
+
+#define AR_PCIE_MSI 0x4094
+#define AR_PCIE_MSI_ENABLE 0x00000001
+
+
+#define AR_RTC_9160_PLL_DIV 0x000003ff
+#define AR_RTC_9160_PLL_DIV_S 0
+#define AR_RTC_9160_PLL_REFDIV 0x00003C00
+#define AR_RTC_9160_PLL_REFDIV_S 10
+#define AR_RTC_9160_PLL_CLKSEL 0x0000C000
+#define AR_RTC_9160_PLL_CLKSEL_S 14
+
+#define AR_RTC_BASE 0x00020000
+#define AR_RTC_RC \
+ (AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000
+#define AR_RTC_RC_M 0x00000003
+#define AR_RTC_RC_MAC_WARM 0x00000001
+#define AR_RTC_RC_MAC_COLD 0x00000002
+#define AR_RTC_RC_COLD_RESET 0x00000004
+#define AR_RTC_RC_WARM_RESET 0x00000008
+
+#define AR_RTC_PLL_CONTROL \
+ (AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014
+
+#define AR_RTC_PLL_DIV 0x0000001f
+#define AR_RTC_PLL_DIV_S 0
+#define AR_RTC_PLL_DIV2 0x00000020
+#define AR_RTC_PLL_REFDIV_5 0x000000c0
+#define AR_RTC_PLL_CLKSEL 0x00000300
+#define AR_RTC_PLL_CLKSEL_S 8
+
+
+
+#define AR_RTC_RESET \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
+#define AR_RTC_RESET_EN (0x00000001)
+
+#define AR_RTC_STATUS \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044)
+
+#define AR_RTC_STATUS_M \
+ ((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f)
+
+#define AR_RTC_PM_STATUS_M 0x0000000f
+
+#define AR_RTC_STATUS_SHUTDOWN 0x00000001
+#define AR_RTC_STATUS_ON 0x00000002
+#define AR_RTC_STATUS_SLEEP 0x00000004
+#define AR_RTC_STATUS_WAKEUP 0x00000008
+
+#define AR_RTC_SLEEP_CLK \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048)
+#define AR_RTC_FORCE_DERIVED_CLK 0x2
+
+#define AR_RTC_FORCE_WAKE \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c)
+#define AR_RTC_FORCE_WAKE_EN 0x00000001
+#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002
+
+
+#define AR_RTC_INTR_CAUSE \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050)
+
+#define AR_RTC_INTR_ENABLE \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054)
+
+#define AR_RTC_INTR_MASK \
+ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058)
+
+#define AR_SEQ_MASK 0x8060
+
+#define AR_AN_RF2G1_CH0 0x7810
+#define AR_AN_RF2G1_CH0_OB 0x03800000
+#define AR_AN_RF2G1_CH0_OB_S 23
+#define AR_AN_RF2G1_CH0_DB 0x1C000000
+#define AR_AN_RF2G1_CH0_DB_S 26
+
+#define AR_AN_RF5G1_CH0 0x7818
+#define AR_AN_RF5G1_CH0_OB5 0x00070000
+#define AR_AN_RF5G1_CH0_OB5_S 16
+#define AR_AN_RF5G1_CH0_DB5 0x00380000
+#define AR_AN_RF5G1_CH0_DB5_S 19
+
+#define AR_AN_RF2G1_CH1 0x7834
+#define AR_AN_RF2G1_CH1_OB 0x03800000
+#define AR_AN_RF2G1_CH1_OB_S 23
+#define AR_AN_RF2G1_CH1_DB 0x1C000000
+#define AR_AN_RF2G1_CH1_DB_S 26
+
+#define AR_AN_RF5G1_CH1 0x783C
+#define AR_AN_RF5G1_CH1_OB5 0x00070000
+#define AR_AN_RF5G1_CH1_OB5_S 16
+#define AR_AN_RF5G1_CH1_DB5 0x00380000
+#define AR_AN_RF5G1_CH1_DB5_S 19
+
+#define AR_AN_TOP2 0x7894
+#define AR_AN_TOP2_XPABIAS_LVL 0xC0000000
+#define AR_AN_TOP2_XPABIAS_LVL_S 30
+#define AR_AN_TOP2_LOCALBIAS 0x00200000
+#define AR_AN_TOP2_LOCALBIAS_S 21
+#define AR_AN_TOP2_PWDCLKIND 0x00400000
+#define AR_AN_TOP2_PWDCLKIND_S 22
+
+#define AR_AN_SYNTH9 0x7868
+#define AR_AN_SYNTH9_REFDIVA 0xf8000000
+#define AR_AN_SYNTH9_REFDIVA_S 27
+
+#define AR9285_AN_RF2G1 0x7820
+#define AR9285_AN_RF2G1_ENPACAL 0x00000800
+#define AR9285_AN_RF2G1_ENPACAL_S 11
+#define AR9285_AN_RF2G1_PDPADRV1 0x02000000
+#define AR9285_AN_RF2G1_PDPADRV1_S 25
+#define AR9285_AN_RF2G1_PDPADRV2 0x01000000
+#define AR9285_AN_RF2G1_PDPADRV2_S 24
+#define AR9285_AN_RF2G1_PDPAOUT 0x00800000
+#define AR9285_AN_RF2G1_PDPAOUT_S 23
+#define AR9285_AN_RF2G2 0x7824
+#define AR9285_AN_RF2G2_OFFCAL 0x00001000
+#define AR9285_AN_RF2G2_OFFCAL_S 12
+#define AR9285_AN_RF2G3 0x7828
+#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000
+#define AR9285_AN_RF2G3_PDVCCOMP_S 25
+#define AR9285_AN_RF2G3_OB_0 0x00E00000
+#define AR9285_AN_RF2G3_OB_0_S 21
+#define AR9285_AN_RF2G3_OB_1 0x001C0000
+#define AR9285_AN_RF2G3_OB_1_S 18
+#define AR9285_AN_RF2G3_OB_2 0x00038000
+#define AR9285_AN_RF2G3_OB_2_S 15
+#define AR9285_AN_RF2G3_OB_3 0x00007000
+#define AR9285_AN_RF2G3_OB_3_S 12
+#define AR9285_AN_RF2G3_OB_4 0x00000E00
+#define AR9285_AN_RF2G3_OB_4_S 9
+#define AR9285_AN_RF2G3_DB1_0 0x000001C0
+#define AR9285_AN_RF2G3_DB1_0_S 6
+#define AR9285_AN_RF2G3_DB1_1 0x00000038
+#define AR9285_AN_RF2G3_DB1_1_S 3
+#define AR9285_AN_RF2G3_DB1_2 0x00000007
+#define AR9285_AN_RF2G3_DB1_2_S 0
+#define AR9285_AN_RF2G4 0x782C
+#define AR9285_AN_RF2G4_DB1_3 0xE0000000
+#define AR9285_AN_RF2G4_DB1_3_S 29
+#define AR9285_AN_RF2G4_DB1_4 0x1C000000
+#define AR9285_AN_RF2G4_DB1_4_S 26
+#define AR9285_AN_RF2G4_DB2_0 0x03800000
+#define AR9285_AN_RF2G4_DB2_0_S 23
+#define AR9285_AN_RF2G4_DB2_1 0x00700000
+#define AR9285_AN_RF2G4_DB2_1_S 20
+#define AR9285_AN_RF2G4_DB2_2 0x000E0000
+#define AR9285_AN_RF2G4_DB2_2_S 17
+#define AR9285_AN_RF2G4_DB2_3 0x0001C000
+#define AR9285_AN_RF2G4_DB2_3_S 14
+#define AR9285_AN_RF2G4_DB2_4 0x00003800
+#define AR9285_AN_RF2G4_DB2_4_S 11
+#define AR9285_AN_RF2G6 0x7834
+#define AR9285_AN_RF2G6_CCOMP 0x00007800
+#define AR9285_AN_RF2G6_CCOMP_S 11
+#define AR9285_AN_RF2G6_OFFS 0x03f00000
+#define AR9285_AN_RF2G6_OFFS_S 20
+#define AR9285_AN_RF2G7 0x7838
+#define AR9285_AN_RF2G7_PWDDB 0x00000002
+#define AR9285_AN_RF2G7_PWDDB_S 1
+#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000
+#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29
+#define AR9285_AN_RF2G8 0x783C
+#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000
+#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14
+#define AR9285_AN_RF2G9 0x7840
+#define AR9285_AN_RXTXBB1 0x7854
+#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020
+#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5
+#define AR9285_AN_RXTXBB1_PDV2I 0x00000080
+#define AR9285_AN_RXTXBB1_PDV2I_S 7
+#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100
+#define AR9285_AN_RXTXBB1_PDDACIF_S 8
+#define AR9285_AN_RXTXBB1_SPARE9 0x00000001
+#define AR9285_AN_RXTXBB1_SPARE9_S 0
+#define AR9285_AN_TOP2 0x7868
+#define AR9285_AN_TOP3 0x786c
+#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C
+#define AR9285_AN_TOP3_XPABIAS_LVL_S 2
+#define AR9285_AN_TOP3_PWDDAC 0x00800000
+#define AR9285_AN_TOP3_PWDDAC_S 23
+#define AR9285_AN_TOP4 0x7870
+#define AR9285_AN_TOP4_DEFAULT 0x10142c00
+#define AR_STA_ID0 0x8000
+#define AR_STA_ID1 0x8004
+#define AR_STA_ID1_SADH_MASK 0x0000FFFF
+#define AR_STA_ID1_STA_AP 0x00010000
+#define AR_STA_ID1_ADHOC 0x00020000
+#define AR_STA_ID1_PWR_SAV 0x00040000
+#define AR_STA_ID1_KSRCHDIS 0x00080000
+#define AR_STA_ID1_PCF 0x00100000
+#define AR_STA_ID1_USE_DEFANT 0x00200000
+#define AR_STA_ID1_DEFANT_UPDATE 0x00400000
+#define AR_STA_ID1_RTS_USE_DEF 0x00800000
+#define AR_STA_ID1_ACKCTS_6MB 0x01000000
+#define AR_STA_ID1_BASE_RATE_11B 0x02000000
+#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000
+#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000
+#define AR_STA_ID1_KSRCH_MODE 0x10000000
+#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000
+#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000
+#define AR_STA_ID1_MCAST_KSRCH 0x80000000
+
+#define AR_BSS_ID0 0x8008
+#define AR_BSS_ID1 0x800C
+#define AR_BSS_ID1_U16 0x0000FFFF
+#define AR_BSS_ID1_AID 0x07FF0000
+#define AR_BSS_ID1_AID_S 16
+
+#define AR_BCN_RSSI_AVE 0x8010
+#define AR_BCN_RSSI_AVE_MASK 0x00000FFF
+
+#define AR_TIME_OUT 0x8014
+#define AR_TIME_OUT_ACK 0x00003FFF
+#define AR_TIME_OUT_ACK_S 0
+#define AR_TIME_OUT_CTS 0x3FFF0000
+#define AR_TIME_OUT_CTS_S 16
+
+#define AR_RSSI_THR 0x8018
+#define AR_RSSI_THR_MASK 0x000000FF
+#define AR_RSSI_THR_BM_THR 0x0000FF00
+#define AR_RSSI_THR_BM_THR_S 8
+#define AR_RSSI_BCN_WEIGHT 0x1F000000
+#define AR_RSSI_BCN_WEIGHT_S 24
+#define AR_RSSI_BCN_RSSI_RST 0x20000000
+
+#define AR_USEC 0x801c
+#define AR_USEC_USEC 0x0000007F
+#define AR_USEC_TX_LAT 0x007FC000
+#define AR_USEC_TX_LAT_S 14
+#define AR_USEC_RX_LAT 0x1F800000
+#define AR_USEC_RX_LAT_S 23
+
+#define AR_RESET_TSF 0x8020
+#define AR_RESET_TSF_ONCE 0x01000000
+
+#define AR_MAX_CFP_DUR 0x8038
+#define AR_CFP_VAL 0x0000FFFF
+
+#define AR_RX_FILTER 0x803C
+#define AR_RX_FILTER_ALL 0x00000000
+#define AR_RX_UCAST 0x00000001
+#define AR_RX_MCAST 0x00000002
+#define AR_RX_BCAST 0x00000004
+#define AR_RX_CONTROL 0x00000008
+#define AR_RX_BEACON 0x00000010
+#define AR_RX_PROM 0x00000020
+#define AR_RX_PROBE_REQ 0x00000080
+#define AR_RX_MY_BEACON 0x00000200
+#define AR_RX_COMPR_BAR 0x00000400
+#define AR_RX_COMPR_BA 0x00000800
+#define AR_RX_UNCOM_BA_BAR 0x00001000
+
+#define AR_MCAST_FIL0 0x8040
+#define AR_MCAST_FIL1 0x8044
+
+#define AR_DIAG_SW 0x8048
+#define AR_DIAG_CACHE_ACK 0x00000001
+#define AR_DIAG_ACK_DIS 0x00000002
+#define AR_DIAG_CTS_DIS 0x00000004
+#define AR_DIAG_ENCRYPT_DIS 0x00000008
+#define AR_DIAG_DECRYPT_DIS 0x00000010
+#define AR_DIAG_RX_DIS 0x00000020
+#define AR_DIAG_LOOP_BACK 0x00000040
+#define AR_DIAG_CORR_FCS 0x00000080
+#define AR_DIAG_CHAN_INFO 0x00000100
+#define AR_DIAG_SCRAM_SEED 0x0001FE00
+#define AR_DIAG_SCRAM_SEED_S 8
+#define AR_DIAG_FRAME_NV0 0x00020000
+#define AR_DIAG_OBS_PT_SEL1 0x000C0000
+#define AR_DIAG_OBS_PT_SEL1_S 18
+#define AR_DIAG_FORCE_RX_CLEAR 0x00100000
+#define AR_DIAG_IGNORE_VIRT_CS 0x00200000
+#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000
+#define AR_DIAG_EIFS_CTRL_ENA 0x00800000
+#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000
+#define AR_DIAG_RX_ABORT 0x02000000
+#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000
+#define AR_DIAG_OBS_PT_SEL2 0x08000000
+#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000
+#define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000
+
+#define AR_TSF_L32 0x804c
+#define AR_TSF_U32 0x8050
+
+#define AR_TST_ADDAC 0x8054
+#define AR_DEF_ANTENNA 0x8058
+
+#define AR_AES_MUTE_MASK0 0x805c
+#define AR_AES_MUTE_MASK0_FC 0x0000FFFF
+#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000
+#define AR_AES_MUTE_MASK0_QOS_S 16
+
+#define AR_AES_MUTE_MASK1 0x8060
+#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF
+
+#define AR_GATED_CLKS 0x8064
+#define AR_GATED_CLKS_TX 0x00000002
+#define AR_GATED_CLKS_RX 0x00000004
+#define AR_GATED_CLKS_REG 0x00000008
+
+#define AR_OBS_BUS_CTRL 0x8068
+#define AR_OBS_BUS_SEL_1 0x00040000
+#define AR_OBS_BUS_SEL_2 0x00080000
+#define AR_OBS_BUS_SEL_3 0x000C0000
+#define AR_OBS_BUS_SEL_4 0x08040000
+#define AR_OBS_BUS_SEL_5 0x08080000
+
+#define AR_OBS_BUS_1 0x806c
+#define AR_OBS_BUS_1_PCU 0x00000001
+#define AR_OBS_BUS_1_RX_END 0x00000002
+#define AR_OBS_BUS_1_RX_WEP 0x00000004
+#define AR_OBS_BUS_1_RX_BEACON 0x00000008
+#define AR_OBS_BUS_1_RX_FILTER 0x00000010
+#define AR_OBS_BUS_1_TX_HCF 0x00000020
+#define AR_OBS_BUS_1_QUIET_TIME 0x00000040
+#define AR_OBS_BUS_1_CHAN_IDLE 0x00000080
+#define AR_OBS_BUS_1_TX_HOLD 0x00000100
+#define AR_OBS_BUS_1_TX_FRAME 0x00000200
+#define AR_OBS_BUS_1_RX_FRAME 0x00000400
+#define AR_OBS_BUS_1_RX_CLEAR 0x00000800
+#define AR_OBS_BUS_1_WEP_STATE 0x0003F000
+#define AR_OBS_BUS_1_WEP_STATE_S 12
+#define AR_OBS_BUS_1_RX_STATE 0x01F00000
+#define AR_OBS_BUS_1_RX_STATE_S 20
+#define AR_OBS_BUS_1_TX_STATE 0x7E000000
+#define AR_OBS_BUS_1_TX_STATE_S 25
+
+#define AR_LAST_TSTP 0x8080
+#define AR_NAV 0x8084
+#define AR_RTS_OK 0x8088
+#define AR_RTS_FAIL 0x808c
+#define AR_ACK_FAIL 0x8090
+#define AR_FCS_FAIL 0x8094
+#define AR_BEACON_CNT 0x8098
+
+#define AR_SLEEP1 0x80d4
+#define AR_SLEEP1_ASSUME_DTIM 0x00080000
+#define AR_SLEEP1_CAB_TIMEOUT 0xFFE00000
+#define AR_SLEEP1_CAB_TIMEOUT_S 21
+
+#define AR_SLEEP2 0x80d8
+#define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000
+#define AR_SLEEP2_BEACON_TIMEOUT_S 21
+
+#define AR_BSSMSKL 0x80e0
+#define AR_BSSMSKU 0x80e4
+
+#define AR_TPC 0x80e8
+#define AR_TPC_ACK 0x0000003f
+#define AR_TPC_ACK_S 0x00
+#define AR_TPC_CTS 0x00003f00
+#define AR_TPC_CTS_S 0x08
+#define AR_TPC_CHIRP 0x003f0000
+#define AR_TPC_CHIRP_S 0x16
+
+#define AR_TFCNT 0x80ec
+#define AR_RFCNT 0x80f0
+#define AR_RCCNT 0x80f4
+#define AR_CCCNT 0x80f8
+
+#define AR_QUIET1 0x80fc
+#define AR_QUIET1_NEXT_QUIET_S 0
+#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
+#define AR_QUIET1_QUIET_ENABLE 0x00010000
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
+#define AR_QUIET2 0x8100
+#define AR_QUIET2_QUIET_PERIOD_S 0
+#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff
+#define AR_QUIET2_QUIET_DUR_S 16
+#define AR_QUIET2_QUIET_DUR 0xffff0000
+
+#define AR_TSF_PARM 0x8104
+#define AR_TSF_INCREMENT_M 0x000000ff
+#define AR_TSF_INCREMENT_S 0x00
+
+#define AR_QOS_NO_ACK 0x8108
+#define AR_QOS_NO_ACK_TWO_BIT 0x0000000f
+#define AR_QOS_NO_ACK_TWO_BIT_S 0
+#define AR_QOS_NO_ACK_BIT_OFF 0x00000070
+#define AR_QOS_NO_ACK_BIT_OFF_S 4
+#define AR_QOS_NO_ACK_BYTE_OFF 0x00000180
+#define AR_QOS_NO_ACK_BYTE_OFF_S 7
+
+#define AR_PHY_ERR 0x810c
+
+#define AR_PHY_ERR_DCHIRP 0x00000008
+#define AR_PHY_ERR_RADAR 0x00000020
+#define AR_PHY_ERR_OFDM_TIMING 0x00020000
+#define AR_PHY_ERR_CCK_TIMING 0x02000000
+
+#define AR_RXFIFO_CFG 0x8114
+
+
+#define AR_MIC_QOS_CONTROL 0x8118
+#define AR_MIC_QOS_SELECT 0x811c
+
+#define AR_PCU_MISC 0x8120
+#define AR_PCU_FORCE_BSSID_MATCH 0x00000001
+#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004
+#define AR_PCU_TX_ADD_TSF 0x00000008
+#define AR_PCU_CCK_SIFS_MODE 0x00000010
+#define AR_PCU_RX_ANT_UPDT 0x00000800
+#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000
+#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000
+#define AR_PCU_BUG_12306_FIX_ENA 0x00020000
+#define AR_PCU_FORCE_QUIET_COLL 0x00040000
+#define AR_PCU_TBTT_PROTECT 0x00200000
+#define AR_PCU_CLEAR_VMF 0x01000000
+#define AR_PCU_CLEAR_BA_VALID 0x04000000
+
+
+#define AR_FILT_OFDM 0x8124
+#define AR_FILT_OFDM_COUNT 0x00FFFFFF
+
+#define AR_FILT_CCK 0x8128
+#define AR_FILT_CCK_COUNT 0x00FFFFFF
+
+#define AR_PHY_ERR_1 0x812c
+#define AR_PHY_ERR_1_COUNT 0x00FFFFFF
+#define AR_PHY_ERR_MASK_1 0x8130
+
+#define AR_PHY_ERR_2 0x8134
+#define AR_PHY_ERR_2_COUNT 0x00FFFFFF
+#define AR_PHY_ERR_MASK_2 0x8138
+
+#define AR_PHY_COUNTMAX (3 << 22)
+#define AR_MIBCNT_INTRMASK (3 << 22)
+
+#define AR_TSF_THRESHOLD 0x813c
+#define AR_TSF_THRESHOLD_VAL 0x0000FFFF
+
+#define AR_PHY_ERR_EIFS_MASK 8144
+
+#define AR_PHY_ERR_3 0x8168
+#define AR_PHY_ERR_3_COUNT 0x00FFFFFF
+#define AR_PHY_ERR_MASK_3 0x816c
+
+#define AR_TXSIFS 0x81d0
+#define AR_TXSIFS_TIME 0x000000FF
+#define AR_TXSIFS_TX_LATENCY 0x00000F00
+#define AR_TXSIFS_TX_LATENCY_S 8
+#define AR_TXSIFS_ACK_SHIFT 0x00007000
+#define AR_TXSIFS_ACK_SHIFT_S 12
+
+#define AR_TXOP_X 0x81ec
+#define AR_TXOP_X_VAL 0x000000FF
+
+
+#define AR_TXOP_0_3 0x81f0
+#define AR_TXOP_4_7 0x81f4
+#define AR_TXOP_8_11 0x81f8
+#define AR_TXOP_12_15 0x81fc
+
+
+#define AR_NEXT_TBTT_TIMER 0x8200
+#define AR_NEXT_DMA_BEACON_ALERT 0x8204
+#define AR_NEXT_SWBA 0x8208
+#define AR_NEXT_CFP 0x8208
+#define AR_NEXT_HCF 0x820C
+#define AR_NEXT_TIM 0x8210
+#define AR_NEXT_DTIM 0x8214
+#define AR_NEXT_QUIET_TIMER 0x8218
+#define AR_NEXT_NDP_TIMER 0x821C
+
+#define AR_BEACON_PERIOD 0x8220
+#define AR_DMA_BEACON_PERIOD 0x8224
+#define AR_SWBA_PERIOD 0x8228
+#define AR_HCF_PERIOD 0x822C
+#define AR_TIM_PERIOD 0x8230
+#define AR_DTIM_PERIOD 0x8234
+#define AR_QUIET_PERIOD 0x8238
+#define AR_NDP_PERIOD 0x823C
+
+#define AR_TIMER_MODE 0x8240
+#define AR_TBTT_TIMER_EN 0x00000001
+#define AR_DBA_TIMER_EN 0x00000002
+#define AR_SWBA_TIMER_EN 0x00000004
+#define AR_HCF_TIMER_EN 0x00000008
+#define AR_TIM_TIMER_EN 0x00000010
+#define AR_DTIM_TIMER_EN 0x00000020
+#define AR_QUIET_TIMER_EN 0x00000040
+#define AR_NDP_TIMER_EN 0x00000080
+#define AR_TIMER_OVERFLOW_INDEX 0x00000700
+#define AR_TIMER_OVERFLOW_INDEX_S 8
+#define AR_TIMER_THRESH 0xFFFFF000
+#define AR_TIMER_THRESH_S 12
+
+#define AR_SLP32_MODE 0x8244
+#define AR_SLP32_HALF_CLK_LATENCY 0x000FFFFF
+#define AR_SLP32_ENA 0x00100000
+#define AR_SLP32_TSF_WRITE_STATUS 0x00200000
+
+#define AR_SLP32_WAKE 0x8248
+#define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF
+
+#define AR_SLP32_INC 0x824c
+#define AR_SLP32_TST_INC 0x000FFFFF
+
+#define AR_SLP_CNT 0x8250
+#define AR_SLP_CYCLE_CNT 0x8254
+
+#define AR_SLP_MIB_CTRL 0x8258
+#define AR_SLP_MIB_CLEAR 0x00000001
+#define AR_SLP_MIB_PENDING 0x00000002
+
+#define AR_2040_MODE 0x8318
+#define AR_2040_JOINED_RX_CLEAR 0x00000001
+
+
+#define AR_EXTRCCNT 0x8328
+
+#define AR_SELFGEN_MASK 0x832c
+
+#define AR_PCU_TXBUF_CTRL 0x8340
+#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF
+#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700
+#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380
+
+#define AR_KEYTABLE_0 0x8800
+#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
+#define AR_KEY_CACHE_SIZE 128
+#define AR_RSVD_KEYTABLE_ENTRIES 4
+#define AR_KEY_TYPE 0x00000007
+#define AR_KEYTABLE_TYPE_40 0x00000000
+#define AR_KEYTABLE_TYPE_104 0x00000001
+#define AR_KEYTABLE_TYPE_128 0x00000003
+#define AR_KEYTABLE_TYPE_TKIP 0x00000004
+#define AR_KEYTABLE_TYPE_AES 0x00000005
+#define AR_KEYTABLE_TYPE_CCM 0x00000006
+#define AR_KEYTABLE_TYPE_CLR 0x00000007
+#define AR_KEYTABLE_ANT 0x00000008
+#define AR_KEYTABLE_VALID 0x00008000
+#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0)
+#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4)
+#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8)
+#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12)
+#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16)
+#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20)
+#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
+#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARN_REG_H */
diff --git a/usr/src/uts/common/io/arn/arn_regd.c b/usr/src/uts/common/io/arn/arn_regd.c
new file mode 100644
index 0000000000..5a35afaea4
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_regd.c
@@ -0,0 +1,1046 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#include "arn_core.h"
+#include "arn_hw.h"
+#include "arn_regd.h"
+#include "arn_regd_common.h"
+
+static int
+ath9k_regd_chansort(const void *a, const void *b)
+{
+ const struct ath9k_channel *ca = a;
+ const struct ath9k_channel *cb = b;
+
+ return (ca->channel == cb->channel) ?
+ (ca->channelFlags & CHAN_FLAGS) -
+ (cb->channelFlags & CHAN_FLAGS) : ca->channel - cb->channel;
+}
+
+static void
+ath9k_regd_sort(void *a, uint32_t n, uint32_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);
+ }
+}
+
+static uint16_t
+ath9k_regd_get_eepromRD(struct ath_hal *ah)
+{
+ return (ah->ah_currentRD & ~WORLDWIDE_ROAMING_FLAG);
+}
+
+static boolean_t
+ath9k_regd_is_chan_bm_zero(uint64_t *bitmask)
+{
+ int i;
+
+ for (i = 0; i < BMLEN; i++) {
+ if (bitmask[i] != 0)
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
+static boolean_t
+ath9k_regd_is_eeprom_valid(struct ath_hal *ah)
+{
+ uint16_t rd = ath9k_regd_get_eepromRD(ah);
+ int i;
+
+ if (rd & COUNTRY_ERD_FLAG) {
+ uint16_t cc = rd & ~COUNTRY_ERD_FLAG;
+ for (i = 0; i < ARRAY_SIZE(allCountries); i++)
+ if (allCountries[i].countryCode == cc)
+ return (B_TRUE);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
+ if (regDomainPairs[i].regDmnEnum == rd)
+ return (B_TRUE);
+ }
+
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: invalid regulatory domain/country code 0x%x\n",
+ __func__, rd));
+
+ return (B_FALSE);
+}
+
+static boolean_t
+ath9k_regd_is_fcc_midband_supported(struct ath_hal *ah)
+{
+ uint32_t regcap;
+
+ regcap = ah->ah_caps.reg_cap;
+
+ if (regcap & AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND)
+ return (B_TRUE);
+ else
+ return (B_FALSE);
+}
+
+static boolean_t
+ath9k_regd_is_ccode_valid(struct ath_hal *ah, uint16_t cc)
+{
+ uint16_t rd;
+ int i;
+
+ if (cc == CTRY_DEFAULT)
+ return (B_TRUE);
+ if (cc == CTRY_DEBUG)
+ return (B_TRUE);
+
+ rd = ath9k_regd_get_eepromRD(ah);
+
+ ARN_DBG((ARN_DBG_REGULATORY, "%s: EEPROM regdomain 0x%x\n",
+ __func__, rd));
+
+ if (rd & COUNTRY_ERD_FLAG) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: EEPROM setting is country code %u\n",
+ __func__, rd & ~COUNTRY_ERD_FLAG));
+ return (cc == (rd & ~COUNTRY_ERD_FLAG));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+ if (cc == allCountries[i].countryCode) {
+#ifdef ARN_SUPPORT_11D
+ if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)
+ return (B_TRUE);
+#endif
+ if (allCountries[i].regDmnEnum == rd ||
+ rd == DEBUG_REG_DMN || rd == NO_ENUMRD)
+ return (B_TRUE);
+ }
+ }
+ return (B_FALSE);
+}
+
+static void
+ath9k_regd_get_wmodes_nreg(struct ath_hal *ah,
+ struct country_code_to_enum_rd *country,
+ struct regDomain *rd5GHz,
+ uint8_t *modes_allowed)
+
+{
+ bcopy(ah->ah_caps.wireless_modes, modes_allowed,
+ sizeof (ah->ah_caps.wireless_modes));
+
+ if (is_set(ATH9K_MODE_11G, ah->ah_caps.wireless_modes) &&
+ (!country->allow11g))
+ clr_bit(ATH9K_MODE_11G, modes_allowed);
+
+ if (is_set(ATH9K_MODE_11A, ah->ah_caps.wireless_modes) &&
+ (ath9k_regd_is_chan_bm_zero(rd5GHz->chan11a)))
+ clr_bit(ATH9K_MODE_11A, modes_allowed);
+
+ if (is_set(ATH9K_MODE_11NG_HT20, ah->ah_caps.wireless_modes) &&
+ (!country->allow11ng20))
+ clr_bit(ATH9K_MODE_11NG_HT20, modes_allowed);
+
+ if (is_set(ATH9K_MODE_11NA_HT20, ah->ah_caps.wireless_modes) &&
+ (!country->allow11na20))
+ clr_bit(ATH9K_MODE_11NA_HT20, modes_allowed);
+
+ if (is_set(ATH9K_MODE_11NG_HT40PLUS, ah->ah_caps.wireless_modes) &&
+ (!country->allow11ng40))
+ clr_bit(ATH9K_MODE_11NG_HT40PLUS, modes_allowed);
+
+ if (is_set(ATH9K_MODE_11NG_HT40MINUS, ah->ah_caps.wireless_modes) &&
+ (!country->allow11ng40))
+ clr_bit(ATH9K_MODE_11NG_HT40MINUS, modes_allowed);
+
+ if (is_set(ATH9K_MODE_11NA_HT40PLUS, ah->ah_caps.wireless_modes) &&
+ (!country->allow11na40))
+ clr_bit(ATH9K_MODE_11NA_HT40PLUS, modes_allowed);
+
+ if (is_set(ATH9K_MODE_11NA_HT40MINUS, ah->ah_caps.wireless_modes) &&
+ (!country->allow11na40))
+ clr_bit(ATH9K_MODE_11NA_HT40MINUS, modes_allowed);
+}
+
+boolean_t
+ath9k_regd_is_public_safety_sku(struct ath_hal *ah)
+{
+ uint16_t rd;
+
+ rd = ath9k_regd_get_eepromRD(ah);
+
+ switch (rd) {
+ case FCC4_FCCA:
+ case (CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG):
+ return (B_TRUE);
+ case DEBUG_REG_DMN:
+ case NO_ENUMRD:
+ if (ah->ah_countryCode == CTRY_UNITED_STATES_FCC49)
+ return (B_TRUE);
+ break;
+ }
+ return (B_FALSE);
+}
+
+static struct country_code_to_enum_rd *
+ath9k_regd_find_country(uint16_t countryCode)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+ if (allCountries[i].countryCode == countryCode)
+ return (&allCountries[i]);
+ }
+ return (NULL);
+}
+
+static uint16_t
+ath9k_regd_get_default_country(struct ath_hal *ah)
+{
+ uint16_t rd;
+ int i;
+
+ rd = ath9k_regd_get_eepromRD(ah);
+ if (rd & COUNTRY_ERD_FLAG) {
+ struct country_code_to_enum_rd *country = NULL;
+ uint16_t cc = rd & ~COUNTRY_ERD_FLAG;
+
+ country = ath9k_regd_find_country(cc);
+ if (country != NULL)
+ return (cc);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
+ if (regDomainPairs[i].regDmnEnum == rd) {
+ if (regDomainPairs[i].singleCC != 0)
+ return (regDomainPairs[i].singleCC);
+ else
+ i = ARRAY_SIZE(regDomainPairs);
+ }
+ return (CTRY_DEFAULT);
+}
+
+static boolean_t
+ath9k_regd_is_valid_reg_domain(int regDmn, struct regDomain *rd)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(regDomains); i++) {
+ if (regDomains[i].regDmnEnum == regDmn) {
+ if (rd != NULL) {
+ (void) memcpy(rd, &regDomains[i],
+ sizeof (struct regDomain));
+ }
+ return (B_TRUE);
+ }
+ }
+ return (B_FALSE);
+}
+
+static boolean_t
+ath9k_regd_is_valid_reg_domainPair(int regDmnPair)
+{
+ int i;
+
+ if (regDmnPair == NO_ENUMRD)
+ return (B_FALSE);
+ for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
+ if (regDomainPairs[i].regDmnEnum == regDmnPair)
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
+static boolean_t
+ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn,
+ uint16_t channelFlag, struct regDomain *rd)
+{
+ int i, found;
+ uint64_t flags = NO_REQ;
+ struct reg_dmn_pair_mapping *regPair = NULL;
+ int regOrg;
+
+ regOrg = regDmn;
+ if (regDmn == CTRY_DEFAULT) {
+ uint16_t rdnum;
+ rdnum = ath9k_regd_get_eepromRD(ah);
+
+ if (!(rdnum & COUNTRY_ERD_FLAG)) {
+ if (ath9k_regd_is_valid_reg_domain(rdnum, NULL) ||
+ ath9k_regd_is_valid_reg_domainPair(rdnum)) {
+ regDmn = rdnum;
+ }
+ }
+ }
+
+ if ((regDmn & MULTI_DOMAIN_MASK) == 0) {
+ for (i = 0, found = 0;
+ (i < ARRAY_SIZE(regDomainPairs)) && (!found); i++) {
+ if (regDomainPairs[i].regDmnEnum == regDmn) {
+ regPair = &regDomainPairs[i];
+ found = 1;
+ }
+ }
+ if (!found) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: Failed to find reg domain pair %u\n",
+ __func__, regDmn));
+ return (B_FALSE);
+ }
+ if (!(channelFlag & CHANNEL_2GHZ)) {
+ regDmn = regPair->regDmn5GHz;
+ flags = regPair->flags5GHz;
+ }
+ if (channelFlag & CHANNEL_2GHZ) {
+ regDmn = regPair->regDmn2GHz;
+ flags = regPair->flags2GHz;
+ }
+ }
+
+ found = ath9k_regd_is_valid_reg_domain(regDmn, rd);
+ if (!found) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: Failed to find unitary reg domain %u\n",
+ __func__, regDmn));
+ return (B_FALSE);
+ } else {
+ rd->pscan &= regPair->pscanMask;
+ if (((regOrg & MULTI_DOMAIN_MASK) == 0) &&
+ (flags != NO_REQ)) {
+ rd->flags = (uint32_t)flags; /* LINT */
+ }
+
+ rd->flags &= (channelFlag & CHANNEL_2GHZ) ?
+ REG_DOMAIN_2GHZ_MASK : REG_DOMAIN_5GHZ_MASK;
+ return (B_TRUE);
+ }
+}
+
+static boolean_t
+ath9k_regd_is_bit_set(int bit, uint64_t *bitmask)
+{
+ int byteOffset, bitnum;
+ uint64_t val;
+
+ byteOffset = bit / 64;
+ bitnum = bit - byteOffset * 64;
+ val = ((uint64_t)1) << bitnum;
+ if (bitmask[byteOffset] & val)
+ return (B_TRUE);
+ else
+ return (B_FALSE);
+}
+
+static void
+ath9k_regd_add_reg_classid(uint8_t *regclassids, uint32_t maxregids,
+ uint32_t *nregids, uint8_t regclassid)
+{
+ int i;
+
+ if (regclassid == 0)
+ return;
+
+ for (i = 0; i < maxregids; i++) {
+ if (regclassids[i] == regclassid)
+ return;
+ if (regclassids[i] == 0)
+ break;
+ }
+
+ if (i == maxregids)
+ return;
+ else {
+ regclassids[i] = regclassid;
+ *nregids += 1;
+ }
+}
+
+static boolean_t
+ath9k_regd_get_eeprom_reg_ext_bits(struct ath_hal *ah,
+ enum reg_ext_bitmap bit)
+{
+ return ((ah->ah_currentRDExt & (1 << bit)) ? B_TRUE : B_FALSE);
+}
+
+#ifdef ARN_NF_PER_CHAN
+
+static void
+ath9k_regd_init_rf_buffer(struct ath9k_channel *ichans, int nchans)
+{
+ int i, j, next;
+
+ for (next = 0; next < nchans; next++) {
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ ichans[next].nfCalHist[i].currIndex = 0;
+ ichans[next].nfCalHist[i].privNF =
+ AR_PHY_CCA_MAX_GOOD_VALUE;
+ ichans[next].nfCalHist[i].invalidNFcount =
+ AR_PHY_CCA_FILTERWINDOW_LENGTH;
+ for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
+ ichans[next].nfCalHist[i].nfCalBuffer[j] =
+ AR_PHY_CCA_MAX_GOOD_VALUE;
+ }
+ }
+ }
+}
+#endif
+
+static int
+ath9k_regd_is_chan_present(struct ath_hal *ah, uint16_t c)
+{
+ int i;
+
+ for (i = 0; i < 150; i++) {
+ if (!ah->ah_channels[i].channel)
+ return (-1);
+ else if (ah->ah_channels[i].channel == c)
+ return (i);
+ }
+
+ return (-1);
+}
+
+/* ARGSUSED */
+static boolean_t
+ath9k_regd_add_channel(
+ struct ath_hal *ah,
+ uint16_t c,
+ uint16_t c_lo,
+ uint16_t c_hi,
+ uint16_t maxChan,
+ uint8_t ctl,
+ int pos,
+ struct regDomain rd5GHz,
+ struct RegDmnFreqBand *fband,
+ struct regDomain *rd,
+ const struct cmode *cm,
+ struct ath9k_channel *ichans,
+ boolean_t enableExtendedChannels)
+{
+ struct ath9k_channel *chan;
+ int ret;
+ uint32_t channelFlags = 0;
+ uint8_t privFlags = 0;
+
+ if (!(c_lo <= c && c <= c_hi)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: c %u out of range [%u..%u]\n",
+ __func__, c, c_lo, c_hi));
+ return (B_FALSE);
+ }
+ if ((fband->channelBW == CHANNEL_HALF_BW) &&
+ !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_HALFRATE)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: Skipping %u half rate channel\n",
+ __func__, c));
+ return (B_FALSE);
+ }
+
+ if ((fband->channelBW == CHANNEL_QUARTER_BW) &&
+ !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_QUARTERRATE)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: Skipping %u quarter rate channel\n",
+ __func__, c));
+ return (B_FALSE);
+ }
+
+ if (((c + fband->channelSep) / 2) > (maxChan + HALF_MAXCHANBW)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: c %u > maxChan %u\n",
+ __func__, c, maxChan));
+ return (B_FALSE);
+ }
+
+ if ((fband->usePassScan & IS_ECM_CHAN) && !enableExtendedChannels) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "Skipping ecm channel\n"));
+ return (B_FALSE);
+ }
+
+ if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == ATH9K_M_HOSTAP)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "Skipping HOSTAP channel\n"));
+ return (B_FALSE);
+ }
+
+ if (IS_HT40_MODE(cm->mode) &&
+ !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_FCC_DFS_HT40)) &&
+ (fband->useDfs) &&
+ (rd->conformanceTestLimit != MKK)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "Skipping HT40 channel (en_fcc_dfs_ht40 = 0)\n"));
+ return (B_FALSE);
+ }
+
+ if (IS_HT40_MODE(cm->mode) &&
+ !(ath9k_regd_get_eeprom_reg_ext_bits(ah,
+ REG_EXT_JAPAN_NONDFS_HT40)) &&
+ !(fband->useDfs) && (rd->conformanceTestLimit == MKK)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "Skipping HT40 channel (en_jap_ht40 = 0)\n"));
+ return (B_FALSE);
+ }
+
+ if (IS_HT40_MODE(cm->mode) &&
+ !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_JAPAN_DFS_HT40)) &&
+ (fband->useDfs) &&
+ (rd->conformanceTestLimit == MKK)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "Skipping HT40 channel (en_jap_dfs_ht40 = 0)\n"));
+ return (B_FALSE);
+ }
+
+ /* Calculate channel flags */
+
+ channelFlags = cm->flags;
+
+ switch (fband->channelBW) {
+ case CHANNEL_HALF_BW:
+ channelFlags |= CHANNEL_HALF;
+ break;
+ case CHANNEL_QUARTER_BW:
+ channelFlags |= CHANNEL_QUARTER;
+ break;
+ }
+
+ if (fband->usePassScan & rd->pscan)
+ channelFlags |= CHANNEL_PASSIVE;
+ else
+ channelFlags &= ~CHANNEL_PASSIVE;
+ if (fband->useDfs & rd->dfsMask)
+ privFlags = CHANNEL_DFS;
+ else
+ privFlags = 0;
+ if (rd->flags & LIMIT_FRAME_4MS)
+ privFlags |= CHANNEL_4MS_LIMIT;
+ if (privFlags & CHANNEL_DFS)
+ privFlags |= CHANNEL_DISALLOW_ADHOC;
+ if (rd->flags & ADHOC_PER_11D)
+ privFlags |= CHANNEL_PER_11D_ADHOC;
+
+ if (channelFlags & CHANNEL_PASSIVE) {
+ if ((c < 2412) || (c > 2462)) {
+ if (rd5GHz.regDmnEnum == MKK1 ||
+ rd5GHz.regDmnEnum == MKK2) {
+ uint32_t regcap = ah->ah_caps.reg_cap;
+ if (!(regcap &
+ (AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
+ AR_EEPROM_EEREGCAP_EN_KK_U2 |
+ AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) &&
+ isUNII1OddChan(c)) {
+ channelFlags &= ~CHANNEL_PASSIVE;
+ } else {
+ privFlags |= CHANNEL_DISALLOW_ADHOC;
+ }
+ } else {
+ privFlags |= CHANNEL_DISALLOW_ADHOC;
+ }
+ }
+ }
+
+ if ((cm->mode == ATH9K_MODE_11A) ||
+ (cm->mode == ATH9K_MODE_11NA_HT20) ||
+ (cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
+ (cm->mode == ATH9K_MODE_11NA_HT40MINUS)) {
+ if (rd->flags & (ADHOC_NO_11A | DISALLOW_ADHOC_11A))
+ privFlags |= CHANNEL_DISALLOW_ADHOC;
+ }
+
+ /* Fill in channel details */
+
+ ret = ath9k_regd_is_chan_present(ah, c);
+ if (ret == -1) {
+ chan = &ah->ah_channels[pos];
+ chan->channel = c;
+ chan->maxRegTxPower = fband->powerDfs;
+ chan->antennaMax = fband->antennaMax;
+ chan->regDmnFlags = rd->flags;
+ chan->maxTxPower = AR5416_MAX_RATE_POWER;
+ chan->minTxPower = AR5416_MAX_RATE_POWER;
+ chan->channelFlags = channelFlags;
+ chan->privFlags = privFlags;
+ } else {
+ chan = &ah->ah_channels[ret];
+ chan->channelFlags |= channelFlags;
+ chan->privFlags |= privFlags;
+ }
+
+ /* Set CTLs */
+
+ if ((cm->flags & CHANNEL_ALL) == CHANNEL_A)
+ chan->conformanceTestLimit[0] = ctl;
+ else if ((cm->flags & CHANNEL_ALL) == CHANNEL_B)
+ chan->conformanceTestLimit[1] = ctl;
+ else if ((cm->flags & CHANNEL_ALL) == CHANNEL_G)
+ chan->conformanceTestLimit[2] = ctl;
+
+ return ((ret == -1) ? B_TRUE : B_FALSE);
+}
+
+static boolean_t
+ath9k_regd_japan_check(struct ath_hal *ah, int b, struct regDomain *rd5GHz)
+{
+ boolean_t skipband = B_FALSE;
+ int i;
+ uint32_t regcap;
+
+ for (i = 0; i < ARRAY_SIZE(j_bandcheck); i++) {
+ if (j_bandcheck[i].freqbandbit == b) {
+ regcap = ah->ah_caps.reg_cap;
+ if ((j_bandcheck[i].eepromflagtocheck & regcap) == 0) {
+ skipband = B_TRUE;
+ } else if ((regcap & AR_EEPROM_EEREGCAP_EN_KK_U2) ||
+ (regcap & AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) {
+ rd5GHz->dfsMask |= DFS_MKK4;
+ rd5GHz->pscan |= PSCAN_MKK3;
+ }
+ break;
+ }
+ }
+
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: Skipping %d freq band\n",
+ __func__, j_bandcheck[i].freqbandbit));
+
+ return (skipband);
+}
+
+boolean_t
+ath9k_regd_init_channels(
+ struct ath_hal *ah,
+ uint32_t maxchans,
+ uint32_t *nchans,
+ uint8_t *regclassids,
+ uint32_t maxregids,
+ uint32_t *nregids,
+ uint16_t cc,
+ boolean_t enableOutdoor,
+ boolean_t enableExtendedChannels)
+{
+ uint16_t maxChan = 7000;
+ struct country_code_to_enum_rd *country = NULL;
+ struct regDomain rd5GHz, rd2GHz;
+ const struct cmode *cm;
+ struct ath9k_channel *ichans = &ah->ah_channels[0];
+ int next = 0, b;
+ uint8_t ctl;
+ int regdmn;
+ uint16_t chanSep;
+ uint8_t *modes_avail;
+ uint8_t modes_allowed[4];
+
+ (void) memset(modes_allowed, 0, sizeof (modes_allowed));
+ ARN_DBG((ARN_DBG_REGULATORY, "arn: ath9k_regd_init_channels(): "
+ "cc %u %s %s\n",
+ cc,
+ enableOutdoor ? "Enable outdoor" : "",
+ enableExtendedChannels ? "Enable ecm" : ""));
+
+ if (!ath9k_regd_is_ccode_valid(ah, cc)) {
+ ARN_DBG((ARN_DBG_XMIT, "arn: ath9k_regd_init_channels(): "
+ "invalid country code %d\n", cc));
+ return (B_FALSE);
+ }
+
+ if (!ath9k_regd_is_eeprom_valid(ah)) {
+ ARN_DBG((ARN_DBG_ANY, "arn: ath9k_regd_init_channels(): "
+ "invalid EEPROM contents\n"));
+ return (B_FALSE);
+ }
+
+ ah->ah_countryCode = ath9k_regd_get_default_country(ah);
+
+ if (ah->ah_countryCode == CTRY_DEFAULT) {
+ ah->ah_countryCode = cc & COUNTRY_CODE_MASK;
+ if ((ah->ah_countryCode == CTRY_DEFAULT) &&
+ (ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT)) {
+ ah->ah_countryCode = CTRY_UNITED_STATES;
+ }
+ }
+
+#ifdef ARN_SUPPORT_11D
+ if (ah->ah_countryCode == CTRY_DEFAULT) {
+ regdmn = ath9k_regd_get_eepromRD(ah);
+ country = NULL;
+ } else {
+#endif
+ country = ath9k_regd_find_country(ah->ah_countryCode);
+ if (country == NULL) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "arn: ath9k_regd_init_channels(): "
+ "Country is NULL!!!!, cc= %d\n",
+ ah->ah_countryCode));
+
+ return (B_FALSE);
+ } else {
+ regdmn = country->regDmnEnum;
+#ifdef ARN_SUPPORT_11D
+ if (((ath9k_regd_get_eepromRD(ah) &
+ WORLD_SKU_MASK) == WORLD_SKU_PREFIX) &&
+ (cc == CTRY_UNITED_STATES)) {
+ if (!isWwrSKU_NoMidband(ah) &&
+ ath9k_regd_is_fcc_midband_supported(ah))
+ regdmn = FCC3_FCCA;
+ else
+ regdmn = FCC1_FCCA;
+ }
+#endif
+ }
+#ifdef ARN_SUPPORT_11D
+ }
+#endif
+ if (!ath9k_regd_get_wmode_regdomain(ah, regdmn,
+ ~CHANNEL_2GHZ, &rd5GHz)) {
+ ARN_DBG((ARN_DBG_REGULATORY, "arn: ath9k_regd_init_channels(): "
+ "couldn't find unitary "
+ "5GHz reg domain for country %u\n",
+ ah->ah_countryCode));
+ return (B_FALSE);
+ }
+ if (!ath9k_regd_get_wmode_regdomain(ah, regdmn,
+ CHANNEL_2GHZ, &rd2GHz)) {
+ ARN_DBG((ARN_DBG_REGULATORY, "arn: ath9k_regd_init_channels(): "
+ "couldn't find unitary 2GHz "
+ "reg domain for country %u\n",
+ ah->ah_countryCode));
+ return (B_FALSE);
+ }
+
+ if (!isWwrSKU(ah) && ((rd5GHz.regDmnEnum == FCC1) ||
+ (rd5GHz.regDmnEnum == FCC2))) {
+ if (ath9k_regd_is_fcc_midband_supported(ah)) {
+ if (!ath9k_regd_get_wmode_regdomain(ah,
+ FCC3_FCCA, ~CHANNEL_2GHZ, &rd5GHz)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "arn: ath9k_regd_init_channels(): "
+ "couldn't find unitary 5GHz "
+ "reg domain for country %u\n",
+ ah->ah_countryCode));
+ return (B_FALSE);
+ }
+ }
+ }
+
+ if (country == NULL) {
+ modes_avail = ah->ah_caps.wireless_modes;
+ } else {
+ ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz, modes_allowed);
+ modes_avail = modes_allowed;
+
+ if (!enableOutdoor)
+ maxChan = country->outdoorChanStart;
+ }
+
+ next = 0;
+
+ if (maxchans > ARRAY_SIZE(ah->ah_channels))
+ maxchans = ARRAY_SIZE(ah->ah_channels);
+
+ for (cm = modes; cm < &modes[ARRAY_SIZE(modes)]; cm++) {
+ uint16_t c, c_hi, c_lo;
+ uint64_t *channelBM = NULL;
+ struct regDomain *rd = NULL;
+ struct RegDmnFreqBand *fband = NULL, *freqs;
+ int8_t low_adj = 0, hi_adj = 0;
+
+ if (!is_set(cm->mode, modes_avail)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "%s: !avail mode %d flags 0x%x\n",
+ __func__, cm->mode, cm->flags));
+ continue;
+ }
+ if (!ath9k_get_channel_edges(ah, cm->flags, &c_lo, &c_hi)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "arn: ath9k_regd_init_channels(): "
+ "channels 0x%x not supported "
+ "by hardware\n", cm->flags));
+ continue;
+ }
+
+ switch (cm->mode) {
+ case ATH9K_MODE_11A:
+ case ATH9K_MODE_11NA_HT20:
+ case ATH9K_MODE_11NA_HT40PLUS:
+ case ATH9K_MODE_11NA_HT40MINUS:
+ rd = &rd5GHz;
+ channelBM = rd->chan11a;
+ freqs = &regDmn5GhzFreq[0];
+ ctl = rd->conformanceTestLimit;
+ break;
+ case ATH9K_MODE_11B:
+ rd = &rd2GHz;
+ channelBM = rd->chan11b;
+ freqs = &regDmn2GhzFreq[0];
+ ctl = rd->conformanceTestLimit | CTL_11B;
+ break;
+ case ATH9K_MODE_11G:
+ case ATH9K_MODE_11NG_HT20:
+ case ATH9K_MODE_11NG_HT40PLUS:
+ case ATH9K_MODE_11NG_HT40MINUS:
+ rd = &rd2GHz;
+ channelBM = rd->chan11g;
+ freqs = &regDmn2Ghz11gFreq[0];
+ ctl = rd->conformanceTestLimit | CTL_11G;
+ break;
+ default:
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "arn: ath9k_regd_init_channels(): "
+ "Unknown HAL mode 0x%x\n", cm->mode));
+ continue;
+ }
+
+ if (ath9k_regd_is_chan_bm_zero(channelBM))
+ continue;
+
+ if ((cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
+ (cm->mode == ATH9K_MODE_11NG_HT40PLUS)) {
+ hi_adj = -20;
+ }
+
+ if ((cm->mode == ATH9K_MODE_11NA_HT40MINUS) ||
+ (cm->mode == ATH9K_MODE_11NG_HT40MINUS)) {
+ low_adj = 20;
+ }
+
+ /* XXX: Add a helper here instead */
+ for (b = 0; b < 64 * BMLEN; b++) {
+ if (ath9k_regd_is_bit_set(b, channelBM)) {
+ fband = &freqs[b];
+ if (rd5GHz.regDmnEnum == MKK1 ||
+ rd5GHz.regDmnEnum == MKK2) {
+ if (ath9k_regd_japan_check(ah,
+ b, &rd5GHz))
+ continue;
+ }
+
+ ath9k_regd_add_reg_classid(regclassids,
+ maxregids,
+ nregids,
+ fband->regClassId);
+
+ if (IS_HT40_MODE(cm->mode) && (rd == &rd5GHz)) {
+ chanSep = 40;
+ if (fband->lowChannel == 5280)
+ low_adj += 20;
+
+ if (fband->lowChannel == 5170)
+ continue;
+ } else
+ chanSep = fband->channelSep;
+
+ for (c = fband->lowChannel + low_adj;
+ ((c <= (fband->highChannel + hi_adj)) &&
+ (c >= (fband->lowChannel + low_adj)));
+ c += chanSep) {
+ if (next >= maxchans) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "too many channels "
+ "for channel table\n"));
+ goto done;
+ }
+ if (ath9k_regd_add_channel(ah,
+ c, c_lo, c_hi,
+ maxChan, ctl,
+ next,
+ rd5GHz,
+ fband, rd, cm,
+ ichans,
+ enableExtendedChannels))
+ next++;
+ }
+ if (IS_HT40_MODE(cm->mode) &&
+ (fband->lowChannel == 5280)) {
+ low_adj -= 20;
+ }
+ }
+ }
+ }
+done:
+ if (next != 0) {
+ int i;
+
+ if (next > ARRAY_SIZE(ah->ah_channels)) {
+ ARN_DBG((ARN_DBG_REGULATORY,
+ "arn: ath9k_regd_init_channels(): "
+ "too many channels %u; truncating to %u\n",
+ next, (int)ARRAY_SIZE(ah->ah_channels)));
+ next = ARRAY_SIZE(ah->ah_channels);
+ }
+#ifdef ARN_NF_PER_CHAN
+ ath9k_regd_init_rf_buffer(ichans, next);
+#endif
+ ath9k_regd_sort(ichans, next, sizeof (struct ath9k_channel),
+ ath9k_regd_chansort);
+
+ ah->ah_nchan = next;
+
+ ARN_DBG((ARN_DBG_REGULATORY, "arn: ath9k_regd_init_channels(): "
+ "Channel list:\n"));
+ for (i = 0; i < next; i++) {
+ ARN_DBG((ARN_DBG_REGULATORY, "arn: "
+ "chan: %d flags: 0x%x\n",
+ ah->ah_channels[i].channel,
+ ah->ah_channels[i].channelFlags));
+ }
+ }
+ *nchans = next;
+
+ ah->ah_countryCode = ah->ah_countryCode;
+
+ ah->ah_currentRDInUse = (uint16_t)regdmn; /* LINT */
+ ah->ah_currentRD5G = rd5GHz.regDmnEnum;
+ ah->ah_currentRD2G = rd2GHz.regDmnEnum;
+ if (country == NULL) {
+ ah->ah_iso[0] = 0;
+ ah->ah_iso[1] = 0;
+ } else {
+ ah->ah_iso[0] = country->isoName[0];
+ ah->ah_iso[1] = country->isoName[1];
+ }
+
+ return (next != 0);
+}
+
+struct ath9k_channel *
+ath9k_regd_check_channel(struct ath_hal *ah, const struct ath9k_channel *c)
+{
+ struct ath9k_channel *base, *cc;
+
+ int flags = c->channelFlags & CHAN_FLAGS;
+ int n, lim;
+
+ ARN_DBG((ARN_DBG_REGULATORY, "arn: "
+ "%s: channel %u/0x%x (0x%x) requested\n", __func__,
+ c->channel, c->channelFlags, flags));
+
+ cc = ah->ah_curchan;
+ if (cc != NULL && cc->channel == c->channel &&
+ (cc->channelFlags & CHAN_FLAGS) == flags) {
+ if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
+ (cc->privFlags & CHANNEL_DFS))
+ return (NULL);
+ else
+ return (cc);
+ }
+
+ base = ah->ah_channels;
+ n = ah->ah_nchan;
+
+ for (lim = n; lim != 0; lim >>= 1) {
+ int d;
+ cc = &base[lim >> 1];
+ d = c->channel - cc->channel;
+ if (d == 0) {
+ if ((cc->channelFlags & CHAN_FLAGS) == flags) {
+ if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
+ (cc->privFlags & CHANNEL_DFS))
+ return (NULL);
+ else
+ return (cc);
+ }
+ d = flags - (cc->channelFlags & CHAN_FLAGS);
+ }
+
+ ARN_DBG((ARN_DBG_REGULATORY, "arn: "
+ "%s: channel %u/0x%x d %d\n", __func__,
+ cc->channel, cc->channelFlags, d));
+
+ if (d > 0) {
+ base = cc + 1;
+ lim--;
+ }
+ }
+
+ ARN_DBG((ARN_DBG_REGULATORY, "arn: "
+ "%s: no match for %u/0x%x\n",
+ __func__, c->channel, c->channelFlags));
+
+ return (NULL);
+}
+
+uint32_t
+ath9k_regd_get_antenna_allowed(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath9k_channel *ichan = NULL;
+
+ ichan = ath9k_regd_check_channel(ah, chan);
+ if (!ichan)
+ return (0);
+
+ return (ichan->antennaMax);
+}
+
+uint32_t
+ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ uint32_t ctl = NO_CTL;
+ struct ath9k_channel *ichan;
+
+ if (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
+ ctl = SD_NO_CTL | CTL_11A;
+ } else {
+ ichan = ath9k_regd_check_channel(ah, chan);
+ if (ichan != NULL) {
+ /* FIXME */
+ if (IS_CHAN_A(ichan))
+ ctl = ichan->conformanceTestLimit[0];
+ else if (IS_CHAN_B(ichan))
+ ctl = ichan->conformanceTestLimit[1];
+ else if (IS_CHAN_G(ichan))
+ ctl = ichan->conformanceTestLimit[2];
+
+ if (IS_CHAN_G(chan) && (ctl & 0xf) == CTL_11B)
+ ctl = (ctl & ~0xf) | CTL_11G;
+ }
+ }
+ return (ctl);
+}
+
+void
+ath9k_regd_get_current_country(struct ath_hal *ah,
+ struct ath9k_country_entry *ctry)
+{
+ uint16_t rd = ath9k_regd_get_eepromRD(ah);
+
+ ctry->isMultidomain = B_FALSE;
+ if (rd == CTRY_DEFAULT)
+ ctry->isMultidomain = B_TRUE;
+ else if (!(rd & COUNTRY_ERD_FLAG))
+ ctry->isMultidomain = isWwrSKU(ah);
+
+ ctry->countryCode = ah->ah_countryCode;
+ ctry->regDmnEnum = ah->ah_currentRD;
+ ctry->regDmn5G = ah->ah_currentRD5G;
+ ctry->regDmn2G = ah->ah_currentRD2G;
+ ctry->iso[0] = ah->ah_iso[0];
+ ctry->iso[1] = ah->ah_iso[1];
+ ctry->iso[2] = ah->ah_iso[2];
+}
diff --git a/usr/src/uts/common/io/arn/arn_regd.h b/usr/src/uts/common/io/arn/arn_regd.h
new file mode 100644
index 0000000000..a54ae0bc1a
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_regd.h
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARN_REGD_H
+#define _ARN_REGD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "arn_ath9k.h"
+
+#define BMLEN 2
+#define BMZERO {(uint64_t)0, (uint64_t)0}
+
+#define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \
+ {((((_fa >= 0) && (_fa < 64)) ? \
+ (((uint64_t)1) << _fa) : (uint64_t)0) | \
+ (((_fb >= 0) && (_fb < 64)) ? \
+ (((uint64_t)1) << _fb) : (uint64_t)0) | \
+ (((_fc >= 0) && (_fc < 64)) ? \
+ (((uint64_t)1) << _fc) : (uint64_t)0) | \
+ (((_fd >= 0) && (_fd < 64)) ? \
+ (((uint64_t)1) << _fd) : (uint64_t)0) | \
+ (((_fe >= 0) && (_fe < 64)) ? \
+ (((uint64_t)1) << _fe) : (uint64_t)0) | \
+ (((_ff >= 0) && (_ff < 64)) ? \
+ (((uint64_t)1) << _ff) : (uint64_t)0) | \
+ (((_fg >= 0) && (_fg < 64)) ? \
+ (((uint64_t)1) << _fg) : (uint64_t)0) | \
+ (((_fh >= 0) && (_fh < 64)) ? \
+ (((uint64_t)1) << _fh) : (uint64_t)0) | \
+ (((_fi >= 0) && (_fi < 64)) ? \
+ (((uint64_t)1) << _fi) : (uint64_t)0) | \
+ (((_fj >= 0) && (_fj < 64)) ? \
+ (((uint64_t)1) << _fj) : (uint64_t)0) | \
+ (((_fk >= 0) && (_fk < 64)) ? \
+ (((uint64_t)1) << _fk) : (uint64_t)0) | \
+ (((_fl >= 0) && (_fl < 64)) ? \
+ (((uint64_t)1) << _fl) : (uint64_t)0) | \
+ ((((_fa > 63) && (_fa < 128)) ? \
+ (((uint64_t)1) << (_fa - 64)) : (uint64_t)0) | \
+ (((_fb > 63) && (_fb < 128)) ? \
+ (((uint64_t)1) << (_fb - 64)) : (uint64_t)0) | \
+ (((_fc > 63) && (_fc < 128)) ? \
+ (((uint64_t)1) << (_fc - 64)) : (uint64_t)0) | \
+ (((_fd > 63) && (_fd < 128)) ? \
+ (((uint64_t)1) << (_fd - 64)) : (uint64_t)0) | \
+ (((_fe > 63) && (_fe < 128)) ? \
+ (((uint64_t)1) << (_fe - 64)) : (uint64_t)0) | \
+ (((_ff > 63) && (_ff < 128)) ? \
+ (((uint64_t)1) << (_ff - 64)) : (uint64_t)0) | \
+ (((_fg > 63) && (_fg < 128)) ? \
+ (((uint64_t)1) << (_fg - 64)) : (uint64_t)0) | \
+ (((_fh > 63) && (_fh < 128)) ? \
+ (((uint64_t)1) << (_fh - 64)) : (uint64_t)0) | \
+ (((_fi > 63) && (_fi < 128)) ? \
+ (((uint64_t)1) << (_fi - 64)) : (uint64_t)0) | \
+ (((_fj > 63) && (_fj < 128)) ? \
+ (((uint64_t)1) << (_fj - 64)) : (uint64_t)0) | \
+ (((_fk > 63) && (_fk < 128)) ? \
+ (((uint64_t)1) << (_fk - 64)) : (uint64_t)0) | \
+ (((_fl > 63) && (_fl < 128)) ? \
+ (((uint64_t)1) << (_fl - 64)) : (uint64_t)0)))}
+
+#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 CF_INTERFERENCE (CHANNEL_CW_INT | CHANNEL_RADAR_INT)
+#define CHANNEL_14 (2484)
+#define IS_11G_CH14(_ch, _cf) \
+ (((_ch) == CHANNEL_14) && ((_cf) == CHANNEL_G))
+
+#define NO_PSCAN 0x0ULL
+#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
+
+#define isWwrSKU(_ah) \
+ (((ath9k_regd_get_eepromRD((_ah)) & WORLD_SKU_MASK) == \
+ WORLD_SKU_PREFIX) || \
+ (ath9k_regd_get_eepromRD(_ah) == WORLD))
+
+#define isWwrSKU_NoMidband(_ah) \
+ ((ath9k_regd_get_eepromRD((_ah)) == WOR3_WORLD) || \
+ (ath9k_regd_get_eepromRD(_ah) == WOR4_WORLD) || \
+ (ath9k_regd_get_eepromRD(_ah) == WOR5_ETSIC))
+
+#define isUNII1OddChan(ch) \
+ ((ch == 5170) || (ch == 5190) || (ch == 5210) || (ch == 5230))
+
+#define IS_HT40_MODE(_mode) \
+ (((_mode == ATH9K_MODE_11NA_HT40PLUS || \
+ _mode == ATH9K_MODE_11NG_HT40PLUS || \
+ _mode == ATH9K_MODE_11NA_HT40MINUS || \
+ _mode == ATH9K_MODE_11NG_HT40MINUS) ? B_TRUE : B_FALSE))
+
+#define CHAN_FLAGS (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)
+
+#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; \
+}
+
+
+#define HALF_MAXCHANBW 10
+
+#define MULTI_DOMAIN_MASK 0xFF00
+
+#define WORLD_SKU_MASK 0x00F0
+#define WORLD_SKU_PREFIX 0x0060
+
+#define CHANNEL_HALF_BW 10
+#define CHANNEL_QUARTER_BW 5
+
+typedef int ath_hal_cmp_t(const void *, const void *);
+
+struct reg_dmn_pair_mapping {
+ uint16_t regDmnEnum;
+ uint16_t regDmn5GHz;
+ uint16_t regDmn2GHz;
+ uint32_t flags5GHz;
+ uint32_t flags2GHz;
+ uint64_t pscanMask;
+ uint16_t singleCC;
+};
+
+struct ccmap {
+ char isoName[3];
+ uint16_t countryCode;
+};
+
+struct country_code_to_enum_rd {
+ uint16_t countryCode;
+ uint16_t regDmnEnum;
+ const char *isoName;
+ const char *name;
+ boolean_t allow11g;
+ boolean_t allow11aTurbo;
+ boolean_t allow11gTurbo;
+ boolean_t allow11ng20;
+ boolean_t allow11ng40;
+ boolean_t allow11na20;
+ boolean_t allow11na40;
+ uint16_t outdoorChanStart;
+};
+
+struct RegDmnFreqBand {
+ uint16_t lowChannel;
+ uint16_t highChannel;
+ uint8_t powerDfs;
+ uint8_t antennaMax;
+ uint8_t channelBW;
+ uint8_t channelSep;
+ uint64_t useDfs;
+ uint64_t usePassScan;
+ uint8_t regClassId;
+};
+
+struct regDomain {
+ uint16_t regDmnEnum;
+ uint8_t conformanceTestLimit;
+ uint64_t dfsMask;
+ uint64_t pscan;
+ uint32_t flags;
+ uint64_t chan11a[BMLEN];
+ uint64_t chan11a_turbo[BMLEN];
+ uint64_t chan11a_dyn_turbo[BMLEN];
+ uint64_t chan11b[BMLEN];
+ uint64_t chan11g[BMLEN];
+ uint64_t chan11g_turbo[BMLEN];
+};
+
+struct cmode {
+ uint32_t mode;
+ uint32_t flags;
+};
+
+#define YES B_TRUE
+#define NO B_FALSE
+
+struct japan_bandcheck {
+ uint16_t freqbandbit;
+ uint32_t eepromflagtocheck;
+};
+
+struct common_mode_power {
+ uint16_t lchan;
+ uint16_t hchan;
+ uint8_t pwrlvl;
+};
+
+enum CountryCode {
+ CTRY_ALBANIA = 8,
+ CTRY_ALGERIA = 12,
+ CTRY_ARGENTINA = 32,
+ CTRY_ARMENIA = 51,
+ CTRY_AUSTRALIA = 36,
+ CTRY_AUSTRIA = 40,
+ CTRY_AZERBAIJAN = 31,
+ CTRY_BAHRAIN = 48,
+ CTRY_BELARUS = 112,
+ CTRY_BELGIUM = 56,
+ CTRY_BELIZE = 84,
+ CTRY_BOLIVIA = 68,
+ CTRY_BOSNIA_HERZ = 70,
+ CTRY_BRAZIL = 76,
+ CTRY_BRUNEI_DARUSSALAM = 96,
+ CTRY_BULGARIA = 100,
+ CTRY_CANADA = 124,
+ CTRY_CHILE = 152,
+ CTRY_CHINA = 156,
+ CTRY_COLOMBIA = 170,
+ CTRY_COSTA_RICA = 188,
+ CTRY_CROATIA = 191,
+ CTRY_CYPRUS = 196,
+ CTRY_CZECH = 203,
+ CTRY_DENMARK = 208,
+ CTRY_DOMINICAN_REPUBLIC = 214,
+ CTRY_ECUADOR = 218,
+ CTRY_EGYPT = 818,
+ CTRY_EL_SALVADOR = 222,
+ CTRY_ESTONIA = 233,
+ CTRY_FAEROE_ISLANDS = 234,
+ CTRY_FINLAND = 246,
+ CTRY_FRANCE = 250,
+ CTRY_GEORGIA = 268,
+ CTRY_GERMANY = 276,
+ CTRY_GREECE = 300,
+ CTRY_GUATEMALA = 320,
+ CTRY_HONDURAS = 340,
+ CTRY_HONG_KONG = 344,
+ CTRY_HUNGARY = 348,
+ CTRY_ICELAND = 352,
+ CTRY_INDIA = 356,
+ CTRY_INDONESIA = 360,
+ CTRY_IRAN = 364,
+ CTRY_IRAQ = 368,
+ CTRY_IRELAND = 372,
+ CTRY_ISRAEL = 376,
+ CTRY_ITALY = 380,
+ CTRY_JAMAICA = 388,
+ CTRY_JAPAN = 392,
+ CTRY_JORDAN = 400,
+ CTRY_KAZAKHSTAN = 398,
+ CTRY_KENYA = 404,
+ CTRY_KOREA_NORTH = 408,
+ CTRY_KOREA_ROC = 410,
+ CTRY_KOREA_ROC2 = 411,
+ CTRY_KOREA_ROC3 = 412,
+ CTRY_KUWAIT = 414,
+ CTRY_LATVIA = 428,
+ CTRY_LEBANON = 422,
+ CTRY_LIBYA = 434,
+ CTRY_LIECHTENSTEIN = 438,
+ CTRY_LITHUANIA = 440,
+ CTRY_LUXEMBOURG = 442,
+ CTRY_MACAU = 446,
+ CTRY_MACEDONIA = 807,
+ CTRY_MALAYSIA = 458,
+ CTRY_MALTA = 470,
+ CTRY_MEXICO = 484,
+ CTRY_MONACO = 492,
+ CTRY_MOROCCO = 504,
+ CTRY_NEPAL = 524,
+ CTRY_NETHERLANDS = 528,
+ CTRY_NETHERLANDS_ANTILLES = 530,
+ CTRY_NEW_ZEALAND = 554,
+ CTRY_NICARAGUA = 558,
+ CTRY_NORWAY = 578,
+ CTRY_OMAN = 512,
+ CTRY_PAKISTAN = 586,
+ CTRY_PANAMA = 591,
+ CTRY_PAPUA_NEW_GUINEA = 598,
+ CTRY_PARAGUAY = 600,
+ CTRY_PERU = 604,
+ CTRY_PHILIPPINES = 608,
+ CTRY_POLAND = 616,
+ CTRY_PORTUGAL = 620,
+ CTRY_PUERTO_RICO = 630,
+ CTRY_QATAR = 634,
+ CTRY_ROMANIA = 642,
+ CTRY_RUSSIA = 643,
+ CTRY_SAUDI_ARABIA = 682,
+ CTRY_SERBIA_MONTENEGRO = 891,
+ CTRY_SINGAPORE = 702,
+ CTRY_SLOVAKIA = 703,
+ CTRY_SLOVENIA = 705,
+ CTRY_SOUTH_AFRICA = 710,
+ CTRY_SPAIN = 724,
+ CTRY_SRI_LANKA = 144,
+ CTRY_SWEDEN = 752,
+ CTRY_SWITZERLAND = 756,
+ CTRY_SYRIA = 760,
+ CTRY_TAIWAN = 158,
+ CTRY_THAILAND = 764,
+ CTRY_TRINIDAD_Y_TOBAGO = 780,
+ CTRY_TUNISIA = 788,
+ CTRY_TURKEY = 792,
+ CTRY_UAE = 784,
+ CTRY_UKRAINE = 804,
+ CTRY_UNITED_KINGDOM = 826,
+ CTRY_UNITED_STATES = 840,
+ CTRY_UNITED_STATES_FCC49 = 842,
+ CTRY_URUGUAY = 858,
+ CTRY_UZBEKISTAN = 860,
+ CTRY_VENEZUELA = 862,
+ CTRY_VIET_NAM = 704,
+ CTRY_YEMEN = 887,
+ CTRY_ZIMBABWE = 716,
+ CTRY_JAPAN1 = 393,
+ CTRY_JAPAN2 = 394,
+ CTRY_JAPAN3 = 395,
+ CTRY_JAPAN4 = 396,
+ CTRY_JAPAN5 = 397,
+ CTRY_JAPAN6 = 4006,
+ CTRY_JAPAN7 = 4007,
+ CTRY_JAPAN8 = 4008,
+ CTRY_JAPAN9 = 4009,
+ CTRY_JAPAN10 = 4010,
+ CTRY_JAPAN11 = 4011,
+ CTRY_JAPAN12 = 4012,
+ CTRY_JAPAN13 = 4013,
+ CTRY_JAPAN14 = 4014,
+ CTRY_JAPAN15 = 4015,
+ CTRY_JAPAN16 = 4016,
+ CTRY_JAPAN17 = 4017,
+ CTRY_JAPAN18 = 4018,
+ CTRY_JAPAN19 = 4019,
+ CTRY_JAPAN20 = 4020,
+ CTRY_JAPAN21 = 4021,
+ CTRY_JAPAN22 = 4022,
+ CTRY_JAPAN23 = 4023,
+ CTRY_JAPAN24 = 4024,
+ CTRY_JAPAN25 = 4025,
+ CTRY_JAPAN26 = 4026,
+ CTRY_JAPAN27 = 4027,
+ CTRY_JAPAN28 = 4028,
+ CTRY_JAPAN29 = 4029,
+ CTRY_JAPAN30 = 4030,
+ CTRY_JAPAN31 = 4031,
+ CTRY_JAPAN32 = 4032,
+ CTRY_JAPAN33 = 4033,
+ CTRY_JAPAN34 = 4034,
+ CTRY_JAPAN35 = 4035,
+ CTRY_JAPAN36 = 4036,
+ CTRY_JAPAN37 = 4037,
+ CTRY_JAPAN38 = 4038,
+ CTRY_JAPAN39 = 4039,
+ CTRY_JAPAN40 = 4040,
+ CTRY_JAPAN41 = 4041,
+ CTRY_JAPAN42 = 4042,
+ CTRY_JAPAN43 = 4043,
+ CTRY_JAPAN44 = 4044,
+ CTRY_JAPAN45 = 4045,
+ CTRY_JAPAN46 = 4046,
+ CTRY_JAPAN47 = 4047,
+ CTRY_JAPAN48 = 4048,
+ CTRY_JAPAN49 = 4049,
+ CTRY_JAPAN50 = 4050,
+ CTRY_JAPAN51 = 4051,
+ CTRY_JAPAN52 = 4052,
+ CTRY_JAPAN53 = 4053,
+ CTRY_JAPAN54 = 4054,
+ CTRY_JAPAN55 = 4055,
+ CTRY_JAPAN56 = 4056,
+ CTRY_JAPAN57 = 4057,
+ CTRY_JAPAN58 = 4058,
+ CTRY_JAPAN59 = 4059,
+ CTRY_AUSTRALIA2 = 5000,
+ CTRY_CANADA2 = 5001,
+ CTRY_BELGIUM2 = 5002
+};
+
+void ath9k_regd_get_current_country(struct ath_hal *ah,
+ struct ath9k_country_entry *ctry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARN_REGD_H */
diff --git a/usr/src/uts/common/io/arn/arn_regd_common.h b/usr/src/uts/common/io/arn/arn_regd_common.h
new file mode 100644
index 0000000000..53ea702b2d
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_regd_common.h
@@ -0,0 +1,2117 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARN_REGD_COMMON_H
+#define _ARN_REGD_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum EnumRd {
+ NO_ENUMRD = 0x00,
+ NULL1_WORLD = 0x03,
+ NULL1_ETSIB = 0x07,
+ NULL1_ETSIC = 0x08,
+ FCC1_FCCA = 0x10,
+ FCC1_WORLD = 0x11,
+ FCC4_FCCA = 0x12,
+ FCC5_FCCA = 0x13,
+ FCC6_FCCA = 0x14,
+
+ FCC2_FCCA = 0x20,
+ FCC2_WORLD = 0x21,
+ FCC2_ETSIC = 0x22,
+ FCC6_WORLD = 0x23,
+ FRANCE_RES = 0x31,
+ FCC3_FCCA = 0x3A,
+ FCC3_WORLD = 0x3B,
+
+ ETSI1_WORLD = 0x37,
+ ETSI3_ETSIA = 0x32,
+ ETSI2_WORLD = 0x35,
+ ETSI3_WORLD = 0x36,
+ ETSI4_WORLD = 0x30,
+ ETSI4_ETSIC = 0x38,
+ ETSI5_WORLD = 0x39,
+ ETSI6_WORLD = 0x34,
+ ETSI_RESERVED = 0x33,
+
+ MKK1_MKKA = 0x40,
+ MKK1_MKKB = 0x41,
+ APL4_WORLD = 0x42,
+ MKK2_MKKA = 0x43,
+ APL_RESERVED = 0x44,
+ APL2_WORLD = 0x45,
+ APL2_APLC = 0x46,
+ APL3_WORLD = 0x47,
+ MKK1_FCCA = 0x48,
+ APL2_APLD = 0x49,
+ MKK1_MKKA1 = 0x4A,
+ MKK1_MKKA2 = 0x4B,
+ MKK1_MKKC = 0x4C,
+
+ APL3_FCCA = 0x50,
+ APL1_WORLD = 0x52,
+ APL1_FCCA = 0x53,
+ APL1_APLA = 0x54,
+ APL1_ETSIC = 0x55,
+ APL2_ETSIC = 0x56,
+ APL5_WORLD = 0x58,
+ APL6_WORLD = 0x5B,
+ APL7_FCCA = 0x5C,
+ APL8_WORLD = 0x5D,
+ APL9_WORLD = 0x5E,
+
+ WOR0_WORLD = 0x60,
+ WOR1_WORLD = 0x61,
+ WOR2_WORLD = 0x62,
+ WOR3_WORLD = 0x63,
+ WOR4_WORLD = 0x64,
+ WOR5_ETSIC = 0x65,
+
+ WOR01_WORLD = 0x66,
+ WOR02_WORLD = 0x67,
+ EU1_WORLD = 0x68,
+
+ WOR9_WORLD = 0x69,
+ WORA_WORLD = 0x6A,
+ WORB_WORLD = 0x6B,
+
+ MKK3_MKKB = 0x80,
+ MKK3_MKKA2 = 0x81,
+ MKK3_MKKC = 0x82,
+
+ MKK4_MKKB = 0x83,
+ MKK4_MKKA2 = 0x84,
+ MKK4_MKKC = 0x85,
+
+ MKK5_MKKB = 0x86,
+ MKK5_MKKA2 = 0x87,
+ MKK5_MKKC = 0x88,
+
+ MKK6_MKKB = 0x89,
+ MKK6_MKKA2 = 0x8A,
+ MKK6_MKKC = 0x8B,
+
+ MKK7_MKKB = 0x8C,
+ MKK7_MKKA2 = 0x8D,
+ MKK7_MKKC = 0x8E,
+
+ MKK8_MKKB = 0x8F,
+ MKK8_MKKA2 = 0x90,
+ MKK8_MKKC = 0x91,
+
+ MKK14_MKKA1 = 0x92,
+ MKK15_MKKA1 = 0x93,
+
+ MKK10_FCCA = 0xD0,
+ MKK10_MKKA1 = 0xD1,
+ MKK10_MKKC = 0xD2,
+ MKK10_MKKA2 = 0xD3,
+
+ MKK11_MKKA = 0xD4,
+ MKK11_FCCA = 0xD5,
+ MKK11_MKKA1 = 0xD6,
+ MKK11_MKKC = 0xD7,
+ MKK11_MKKA2 = 0xD8,
+
+ MKK12_MKKA = 0xD9,
+ MKK12_FCCA = 0xDA,
+ MKK12_MKKA1 = 0xDB,
+ MKK12_MKKC = 0xDC,
+ MKK12_MKKA2 = 0xDD,
+
+ MKK13_MKKB = 0xDE,
+
+ MKK3_MKKA = 0xF0,
+ MKK3_MKKA1 = 0xF1,
+ MKK3_FCCA = 0xF2,
+ MKK4_MKKA = 0xF3,
+ MKK4_MKKA1 = 0xF4,
+ MKK4_FCCA = 0xF5,
+ MKK9_MKKA = 0xF6,
+ MKK10_MKKA = 0xF7,
+ MKK6_MKKA1 = 0xF8,
+ MKK6_FCCA = 0xF9,
+ MKK7_MKKA1 = 0xFA,
+ MKK7_FCCA = 0xFB,
+ MKK9_FCCA = 0xFC,
+ MKK9_MKKA1 = 0xFD,
+ MKK9_MKKC = 0xFE,
+ MKK9_MKKA2 = 0xFF,
+
+ APL1 = 0x0150,
+ APL2 = 0x0250,
+ APL3 = 0x0350,
+ APL4 = 0x0450,
+ APL5 = 0x0550,
+ APL6 = 0x0650,
+ APL7 = 0x0750,
+ APL8 = 0x0850,
+ APL9 = 0x0950,
+ APL10 = 0x1050,
+
+ ETSI1 = 0x0130,
+ ETSI2 = 0x0230,
+ ETSI3 = 0x0330,
+ ETSI4 = 0x0430,
+ ETSI5 = 0x0530,
+ ETSI6 = 0x0630,
+ ETSIA = 0x0A30,
+ ETSIB = 0x0B30,
+ ETSIC = 0x0C30,
+
+ FCC1 = 0x0110,
+ FCC2 = 0x0120,
+ FCC3 = 0x0160,
+ FCC4 = 0x0165,
+ FCC5 = 0x0510,
+ FCC6 = 0x0610,
+ FCCA = 0x0A10,
+
+ APLD = 0x0D50,
+
+ MKK1 = 0x0140,
+ MKK2 = 0x0240,
+ MKK3 = 0x0340,
+ MKK4 = 0x0440,
+ MKK5 = 0x0540,
+ MKK6 = 0x0640,
+ MKK7 = 0x0740,
+ MKK8 = 0x0840,
+ MKK9 = 0x0940,
+ MKK10 = 0x0B40,
+ MKK11 = 0x1140,
+ MKK12 = 0x1240,
+ MKK13 = 0x0C40,
+ MKK14 = 0x1440,
+ MKK15 = 0x1540,
+ MKKA = 0x0A40,
+ MKKC = 0x0A50,
+
+ NULL1 = 0x0198,
+ WORLD = 0x0199,
+ DEBUG_REG_DMN = 0x01ff,
+};
+
+enum {
+ FCC = 0x10,
+ MKK = 0x40,
+ ETSI = 0x30,
+};
+
+enum {
+ NO_REQ = 0x00000000,
+ DISALLOW_ADHOC_11A = 0x00000001,
+ DISALLOW_ADHOC_11A_TURB = 0x00000002,
+ NEED_NFC = 0x00000004,
+
+ ADHOC_PER_11D = 0x00000008,
+ ADHOC_NO_11A = 0x00000010,
+
+ PUBLIC_SAFETY_DOMAIN = 0x00000020,
+ LIMIT_FRAME_4MS = 0x00000040,
+
+ NO_HOSTAP = 0x00000080,
+
+ REQ_MASK = 0x000000FF,
+};
+
+#define REG_DOMAIN_2GHZ_MASK (REQ_MASK & \
+ (~(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB)))
+#define REG_DOMAIN_5GHZ_MASK REQ_MASK
+
+static struct 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_FCCA, FCC5, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
+ {FCC6_FCCA, FCC6, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
+ {FCC6_WORLD, FCC6, WORLD, 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, },
+
+ {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_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_MKKA, MKK3, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKKA, CTRY_JAPAN25},
+ {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, CTRY_JAPAN26},
+ {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, CTRY_JAPAN27},
+
+ {MKK4_MKKA, MKK4, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK3, CTRY_JAPAN36},
+ {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, CTRY_JAPAN28},
+ {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, CTRY_JAPAN29},
+
+ {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_MKKB, MKK6, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16},
+ {MKK6_MKKA1, MKK6, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN30},
+ {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},
+ {MKK6_FCCA, MKK6, FCCA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ NO_PSCAN, CTRY_JAPAN31},
+
+ {MKK7_MKKB, MKK7, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G,
+ CTRY_JAPAN19},
+ {MKK7_MKKA1, MKK7, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN32},
+ {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},
+ {MKK7_FCCA, MKK7, FCCA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN33},
+
+ {MKK8_MKKB, MKK8, MKKA,
+ 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_MKK2 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G,
+ CTRY_JAPAN34},
+ {MKK9_FCCA, MKK9, FCCA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ NO_PSCAN, CTRY_JAPAN37},
+ {MKK9_MKKA1, MKK9, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN38},
+ {MKK9_MKKA2, MKK9, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN40},
+ {MKK9_MKKC, MKK9, MKKC,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ NO_PSCAN, CTRY_JAPAN39},
+
+ {MKK10_MKKA, MKK10, MKKA,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
+ LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKK3, CTRY_JAPAN35},
+ {MKK10_FCCA, MKK10, FCCA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ NO_PSCAN, CTRY_JAPAN41},
+ {MKK10_MKKA1, MKK10, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN42},
+ {MKK10_MKKA2, MKK10, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN44},
+ {MKK10_MKKC, MKK10, MKKC,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ NO_PSCAN, CTRY_JAPAN43},
+
+ {MKK11_MKKA, MKK11, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK3, CTRY_JAPAN45},
+ {MKK11_FCCA, MKK11, FCCA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK3, CTRY_JAPAN46},
+ {MKK11_MKKA1, MKK11, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN47},
+ {MKK11_MKKA2, MKK11, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN49},
+ {MKK11_MKKC, MKK11, MKKC,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK3, CTRY_JAPAN48},
+
+ {MKK12_MKKA, MKK12, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN50},
+ {MKK12_FCCA, MKK12, FCCA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN51},
+ {MKK12_MKKA1, MKK12, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G,
+ CTRY_JAPAN52},
+ {MKK12_MKKA2, MKK12, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G,
+ CTRY_JAPAN54},
+ {MKK12_MKKC, MKK12, MKKC,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN53},
+
+ {MKK13_MKKB, MKK13, 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_JAPAN57},
+
+ {MKK14_MKKA1, MKK14, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN58},
+ {MKK15_MKKA1, MKK15, MKKA,
+ DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
+ PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN59},
+
+ {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},
+ {WORB_WORLD, WORB_WORLD, WORB_WORLD,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
+ 0},
+};
+
+#define NO_INTERSECT_REQ 0xFFFFFFFF
+#define NO_UNION_REQ 0
+
+static struct country_code_to_enum_rd allCountries[] = {
+ {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, YES, NO,
+ NO, NO, 7000},
+ {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, YES, NO,
+ NO, NO, 7000},
+ {CTRY_ARGENTINA, APL3_WORLD, "AR", "ARGENTINA", YES, NO, NO, YES,
+ NO, YES, NO, 7000},
+ {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_AUSTRALIA, FCC2_WORLD, "AU", "AUSTRALIA", YES, YES, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_AUSTRALIA2, FCC6_WORLD, "AU", "AUSTRALIA2", YES, YES, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, YES, YES,
+ YES, NO, 7000},
+ {CTRY_BELARUS, ETSI1_WORLD, "BY", "BELARUS", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_BELGIUM2, ETSI4_WORLD, "BL", "BELGIUM", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLVIA", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA", "BOSNIA_HERZGOWINA", YES, NO,
+ YES, YES, YES, YES, NO, 7000},
+ {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL", YES, NO, NO, YES, NO,
+ YES, NO, 7000},
+ {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN", "BRUNEI DARUSSALAM",
+ YES, YES, YES, YES, YES, YES, YES, 7000},
+ {CTRY_BULGARIA, ETSI6_WORLD, "BG", "BULGARIA", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_CANADA, FCC2_FCCA, "CA", "CANADA", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_CANADA2, FCC6_FCCA, "CA", "CANADA2", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_CHILE, APL6_WORLD, "CL", "CHILE", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_CHINA, APL1_WORLD, "CN", "CHINA", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA", YES, NO, YES, YES,
+ YES, YES, NO, 7000},
+ {CTRY_COSTA_RICA, FCC1_WORLD, "CR", "COSTA RICA", YES, NO, YES,
+ YES, YES, YES, NO, 7000},
+ {CTRY_CROATIA, ETSI3_WORLD, "HR", "CROATIA", YES, NO, YES, YES,
+ YES, YES, NO, 7000},
+ {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_CZECH, ETSI3_WORLD, "CZ", "CZECH REPUBLIC", YES, NO, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO", "DOMINICAN REPUBLIC",
+ YES, YES, YES, YES, YES, YES, YES, 7000},
+ {CTRY_ECUADOR, FCC1_WORLD, "EC", "ECUADOR", YES, NO, NO, YES, YES,
+ YES, NO, 7000},
+ {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT", YES, NO, YES, YES, YES,
+ YES, NO, 7000},
+ {CTRY_EL_SALVADOR, FCC1_WORLD, "SV", "EL SALVADOR", YES, NO, YES,
+ YES, YES, YES, NO, 7000},
+ {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_FRANCE, ETSI1_WORLD, "FR", "FRANCE", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA", YES, YES, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA", YES, YES, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_HONDURAS, NULL1_WORLD, "HN", "HONDURAS", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_HONG_KONG, FCC2_WORLD, "HK", "HONG KONG", YES, YES, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_INDIA, APL6_WORLD, "IN", "INDIA", YES, NO, YES, YES, YES,
+ YES, NO, 7000},
+ {CTRY_INDONESIA, APL1_WORLD, "ID", "INDONESIA", YES, NO, YES, YES,
+ YES, YES, NO, 7000},
+ {CTRY_IRAN, APL1_WORLD, "IR", "IRAN", YES, YES, YES, YES, YES, YES,
+ YES, 7000},
+ {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_ISRAEL, NULL1_WORLD, "IL", "ISRAEL", YES, NO, YES, YES, YES,
+ NO, NO, 7000},
+ {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAMAICA, ETSI1_WORLD, "JM", "JAMAICA", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+
+ {CTRY_JAPAN, MKK1_MKKA, "JP", "JAPAN", YES, NO, NO, YES, YES, YES,
+ YES, 7000},
+ {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JAPAN25, MKK3_MKKA, "JP", "JAPAN25", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN26, MKK3_MKKA1, "JP", "JAPAN26", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN27, MKK3_FCCA, "JP", "JAPAN27", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN28, MKK4_MKKA1, "JP", "JAPAN28", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN29, MKK4_FCCA, "JP", "JAPAN29", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN30, MKK6_MKKA1, "JP", "JAPAN30", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN31, MKK6_FCCA, "JP", "JAPAN31", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN32, MKK7_MKKA1, "JP", "JAPAN32", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN33, MKK7_FCCA, "JP", "JAPAN33", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN34, MKK9_MKKA, "JP", "JAPAN34", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN35, MKK10_MKKA, "JP", "JAPAN35", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN36, MKK4_MKKA, "JP", "JAPAN36", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN37, MKK9_FCCA, "JP", "JAPAN37", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN38, MKK9_MKKA1, "JP", "JAPAN38", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN39, MKK9_MKKC, "JP", "JAPAN39", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN40, MKK9_MKKA2, "JP", "JAPAN40", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN41, MKK10_FCCA, "JP", "JAPAN41", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN42, MKK10_MKKA1, "JP", "JAPAN42", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN43, MKK10_MKKC, "JP", "JAPAN43", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN44, MKK10_MKKA2, "JP", "JAPAN44", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN45, MKK11_MKKA, "JP", "JAPAN45", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN46, MKK11_FCCA, "JP", "JAPAN46", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN47, MKK11_MKKA1, "JP", "JAPAN47", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN48, MKK11_MKKC, "JP", "JAPAN48", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN49, MKK11_MKKA2, "JP", "JAPAN49", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN50, MKK12_MKKA, "JP", "JAPAN50", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN51, MKK12_FCCA, "JP", "JAPAN51", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN52, MKK12_MKKA1, "JP", "JAPAN52", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN53, MKK12_MKKC, "JP", "JAPAN53", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN54, MKK12_MKKA2, "JP", "JAPAN54", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JAPAN57, MKK13_MKKB, "JP", "JAPAN57", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN58, MKK14_MKKA1, "JP", "JAPAN58", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+ {CTRY_JAPAN59, MKK15_MKKA1, "JP", "JAPAN59", YES, NO, NO, YES, YES,
+ YES, YES, 7000},
+
+ {CTRY_JORDAN, ETSI2_WORLD, "JO", "JORDAN", YES, NO, YES, YES, YES,
+ YES, NO, 7000},
+ {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN", YES, NO, YES,
+ YES, YES, NO, NO, 7000},
+ {CTRY_KOREA_NORTH, APL9_WORLD, "KP", "NORTH KOREA", YES, NO, NO,
+ YES, YES, YES, YES, 7000},
+ {CTRY_KOREA_ROC, APL9_WORLD, "KR", "KOREA REPUBLIC", YES, NO, NO,
+ YES, NO, YES, NO, 7000},
+ {CTRY_KOREA_ROC2, APL2_WORLD, "K2", "KOREA REPUBLIC2", YES, NO, NO,
+ YES, NO, YES, NO, 7000},
+ {CTRY_KOREA_ROC3, APL9_WORLD, "K3", "KOREA REPUBLIC3", YES, NO, NO,
+ YES, NO, YES, NO, 7000},
+ {CTRY_KUWAIT, NULL1_WORLD, "KW", "KUWAIT", YES, NO, YES, YES, YES,
+ NO, NO, 7000},
+ {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_LEBANON, NULL1_WORLD, "LB", "LEBANON", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI", "LIECHTENSTEIN", YES, NO,
+ YES, YES, YES, YES, YES, 7000},
+ {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG", YES, NO, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_MACEDONIA, NULL1_WORLD, "MK", "MACEDONIA", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_MALAYSIA, APL8_WORLD, "MY", "MALAYSIA", YES, NO, NO, YES, NO,
+ YES, NO, 7000},
+ {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_MEXICO, FCC1_FCCA, "MX", "MEXICO", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_MOROCCO, NULL1_WORLD, "MA", "MOROCCO", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_NEPAL, APL1_WORLD, "NP", "NEPAL", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS", YES, NO, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN",
+ "NETHERLANDS-ANTILLES", YES, NO, YES, YES, YES, YES, YES, 7000},
+ {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ", "NEW ZEALAND", YES, NO, YES,
+ YES, YES, YES, NO, 7000},
+ {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_OMAN, APL6_WORLD, "OM", "OMAN", YES, NO, YES, YES, YES, YES,
+ NO, 7000},
+ {CTRY_PAKISTAN, NULL1_WORLD, "PK", "PAKISTAN", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG", "PAPUA NEW GUINEA", YES,
+ YES, YES, YES, YES, YES, YES, 7000},
+ {CTRY_PERU, APL1_WORLD, "PE", "PERU", YES, NO, YES, YES, YES, YES,
+ NO, 7000},
+ {CTRY_PHILIPPINES, APL1_WORLD, "PH", "PHILIPPINES", YES, YES, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO", YES, YES, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_QATAR, NULL1_WORLD, "QA", "QATAR", YES, NO, YES, YES, YES,
+ NO, NO, 7000},
+ {CTRY_ROMANIA, NULL1_WORLD, "RO", "ROMANIA", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_RUSSIA, NULL1_WORLD, "RU", "RUSSIA", YES, NO, YES, YES, YES,
+ NO, NO, 7000},
+ {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA", "SAUDI ARABIA", YES, NO,
+ YES, YES, YES, NO, NO, 7000},
+ {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS", "SERBIA & MONTENEGRO",
+ YES, NO, YES, YES, YES, YES, YES, 7000},
+ {CTRY_SINGAPORE, APL6_WORLD, "SG", "SINGAPORE", YES, YES, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAK REPUBLIC", YES, NO, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA", YES, NO, YES, YES,
+ YES, YES, YES, 7000},
+ {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", "SOUTH AFRICA", YES, NO, YES,
+ YES, YES, YES, NO, 7000},
+ {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_SRI_LANKA, FCC3_WORLD, "LK", "SRI LANKA", YES, NO, YES, YES,
+ YES, YES, NO, 7000},
+ {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN", YES, NO, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND", YES, NO, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIA", YES, NO, YES, YES, YES,
+ NO, NO, 7000},
+ {CTRY_TAIWAN, APL3_FCCA, "TW", "TAIWAN", YES, YES, YES, YES, YES,
+ YES, YES, 7000},
+ {CTRY_THAILAND, NULL1_WORLD, "TH", "THAILAND", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT", "TRINIDAD & TOBAGO",
+ YES, NO, YES, YES, YES, YES, NO, 7000},
+ {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA", YES, NO, YES, YES,
+ YES, YES, NO, 7000},
+ {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY", YES, NO, YES, YES, YES,
+ YES, NO, 7000},
+ {CTRY_UKRAINE, NULL1_WORLD, "UA", "UKRAINE", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_UAE, NULL1_WORLD, "AE", "UNITED ARAB EMIRATES", YES, NO, YES,
+ YES, YES, NO, NO, 7000},
+ {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB", "UNITED KINGDOM", YES, NO,
+ YES, YES, YES, YES, YES, 7000},
+ {CTRY_UNITED_STATES, FCC3_FCCA, "US", "UNITED STATES", YES, YES,
+ YES, YES, YES, YES, YES, 5825},
+ {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS",
+ "UNITED STATES (PUBLIC SAFETY)", YES, YES, YES, YES, YES, YES,
+ YES, 7000},
+ {CTRY_URUGUAY, APL2_WORLD, "UY", "URUGUAY", YES, NO, YES, YES, YES,
+ YES, NO, 7000},
+ {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN", YES, YES, YES,
+ YES, YES, YES, YES, 7000},
+ {CTRY_VENEZUELA, APL2_ETSIC, "VE", "VENEZUELA", YES, NO, YES, YES,
+ YES, YES, NO, 7000},
+ {CTRY_VIET_NAM, NULL1_WORLD, "VN", "VIET NAM", YES, NO, YES, YES,
+ YES, NO, NO, 7000},
+ {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, YES, YES,
+ NO, NO, 7000},
+ {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, YES,
+ YES, NO, NO, 7000}
+};
+
+enum {
+ NO_DFS = 0x0000000000000000ULL,
+ DFS_FCC3 = 0x0000000000000001ULL,
+ DFS_ETSI = 0x0000000000000002ULL,
+ DFS_MKK4 = 0x0000000000000004ULL,
+};
+
+enum {
+ F1_4915_4925,
+ F1_4935_4945,
+ F1_4920_4980,
+ F1_4942_4987,
+ F1_4945_4985,
+ F1_4950_4980,
+ F1_5035_5040,
+ F1_5040_5080,
+ F1_5055_5055,
+
+ F1_5120_5240,
+
+ F1_5170_5230,
+ F2_5170_5230,
+
+ F1_5180_5240,
+ F2_5180_5240,
+ F3_5180_5240,
+ F4_5180_5240,
+ F5_5180_5240,
+ F6_5180_5240,
+ F7_5180_5240,
+ F8_5180_5240,
+
+ F1_5180_5320,
+
+ F1_5240_5280,
+
+ F1_5260_5280,
+
+ F1_5260_5320,
+ F2_5260_5320,
+ F3_5260_5320,
+ F4_5260_5320,
+ F5_5260_5320,
+ F6_5260_5320,
+
+ F1_5260_5700,
+
+ F1_5280_5320,
+
+ F1_5500_5580,
+
+ F1_5500_5620,
+
+ F1_5500_5700,
+ F2_5500_5700,
+ F3_5500_5700,
+ F4_5500_5700,
+ F5_5500_5700,
+
+ F1_5660_5700,
+
+ F1_5745_5805,
+ F2_5745_5805,
+ F3_5745_5805,
+
+ F1_5745_5825,
+ F2_5745_5825,
+ F3_5745_5825,
+ F4_5745_5825,
+ F5_5745_5825,
+ F6_5745_5825,
+
+ W1_4920_4980,
+ W1_5040_5080,
+ W1_5170_5230,
+ W1_5180_5240,
+ W1_5260_5320,
+ W1_5745_5825,
+ W1_5500_5700,
+ A_DEMO_ALL_CHANNELS
+};
+
+static struct RegDmnFreqBand regDmn5GhzFreq[] = {
+ {4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16},
+ {4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16},
+ {4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7},
+ {4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC, 0},
+ {4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC, 0},
+ {4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC, 0},
+ {5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12},
+ {5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2},
+ {5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12},
+
+ {5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
+
+ {5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1},
+ {5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1},
+
+ {5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0},
+ {5180, 5240, 17, 6, 20, 20, NO_DFS, NO_PSCAN, 1},
+ {5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0},
+ {5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0},
+ {5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0},
+ {5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0},
+ {5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK3, 0},
+ {5180, 5240, 23, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
+
+ {5180, 5320, 20, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0},
+
+ {5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0},
+
+ {5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI,
+ PSCAN_FCC | PSCAN_ETSI, 0},
+
+ {5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI,
+ PSCAN_FCC | PSCAN_ETSI, 0},
+
+ {5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4,
+ PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3, 0},
+
+
+ {5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI,
+ PSCAN_FCC | PSCAN_ETSI, 2},
+ {5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2},
+ {5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0},
+ {5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
+
+ {5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0},
+
+ {5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0},
+
+ {5500, 5580, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0},
+
+ {5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0},
+
+ {5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4},
+ {5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI,
+ PSCAN_FCC | PSCAN_ETSI, 0},
+ {5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI,
+ PSCAN_FCC | PSCAN_ETSI, 0},
+ {5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4,
+ PSCAN_MKK3 | PSCAN_FCC, 0},
+ {5500, 5700, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0},
+
+ {5660, 5700, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0},
+
+ {5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
+ {5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
+ {5745, 5805, 30, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0},
+ {5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
+ {5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
+ {5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
+ {5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
+ {5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3},
+ {5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
+
+
+ {4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
+ {5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
+ {5170, 5230, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
+ {5180, 5240, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
+ {5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
+ {5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
+ {5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
+ {4920, 6100, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
+};
+
+enum {
+ T1_5130_5650,
+ T1_5150_5670,
+
+ T1_5200_5200,
+ T2_5200_5200,
+ T3_5200_5200,
+ T4_5200_5200,
+ T5_5200_5200,
+ T6_5200_5200,
+ T7_5200_5200,
+ T8_5200_5200,
+
+ T1_5200_5280,
+ T2_5200_5280,
+ T3_5200_5280,
+ T4_5200_5280,
+ T5_5200_5280,
+ T6_5200_5280,
+
+ T1_5200_5240,
+ T1_5210_5210,
+ T2_5210_5210,
+ T3_5210_5210,
+ T4_5210_5210,
+ T5_5210_5210,
+ T6_5210_5210,
+ T7_5210_5210,
+ T8_5210_5210,
+ T9_5210_5210,
+ T10_5210_5210,
+ T1_5240_5240,
+
+ T1_5210_5250,
+ T1_5210_5290,
+ T2_5210_5290,
+ T3_5210_5290,
+
+ T1_5280_5280,
+ T2_5280_5280,
+ T1_5290_5290,
+ T2_5290_5290,
+ T3_5290_5290,
+ T1_5250_5290,
+ T2_5250_5290,
+ T3_5250_5290,
+ T4_5250_5290,
+
+ T1_5540_5660,
+ T2_5540_5660,
+ T3_5540_5660,
+ T1_5760_5800,
+ T2_5760_5800,
+ T3_5760_5800,
+ T4_5760_5800,
+ T5_5760_5800,
+ T6_5760_5800,
+ T7_5760_5800,
+
+ T1_5765_5805,
+ T2_5765_5805,
+ T3_5765_5805,
+ T4_5765_5805,
+ T5_5765_5805,
+ T6_5765_5805,
+ T7_5765_5805,
+ T8_5765_5805,
+ T9_5765_5805,
+
+ WT1_5210_5250,
+ WT1_5290_5290,
+ WT1_5540_5660,
+ WT1_5760_5800,
+};
+
+enum {
+ F1_2312_2372,
+ F2_2312_2372,
+
+ F1_2412_2472,
+ F2_2412_2472,
+ F3_2412_2472,
+
+ F1_2412_2462,
+ F2_2412_2462,
+
+ F1_2432_2442,
+
+ F1_2457_2472,
+
+ F1_2467_2472,
+
+ F1_2484_2484,
+ F2_2484_2484,
+
+ F1_2512_2732,
+
+ W1_2312_2372,
+ W1_2412_2412,
+ W1_2417_2432,
+ W1_2437_2442,
+ W1_2447_2457,
+ W1_2462_2462,
+ W1_2467_2467,
+ W2_2467_2467,
+ W1_2472_2472,
+ W2_2472_2472,
+ W1_2484_2484,
+ W2_2484_2484,
+};
+
+static struct RegDmnFreqBand regDmn2GhzFreq[] = {
+ {2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0},
+ {2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0},
+
+ {2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0},
+
+ {2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2484, 2484, 20, 0, 20, 5, NO_DFS,
+ PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0},
+
+ {2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+ {2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+ {2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+ {2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+ {2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+ {2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+};
+
+enum {
+ G1_2312_2372,
+ G2_2312_2372,
+
+ G1_2412_2472,
+ G2_2412_2472,
+ G3_2412_2472,
+
+ G1_2412_2462,
+ G2_2412_2462,
+
+ G1_2432_2442,
+
+ G1_2457_2472,
+
+ G1_2512_2732,
+
+ G1_2467_2472,
+
+ WG1_2312_2372,
+ WG1_2412_2462,
+ WG1_2467_2472,
+ WG2_2467_2472,
+ G_DEMO_ALL_CHANNELS
+};
+
+static struct RegDmnFreqBand regDmn2Ghz11gFreq[] = {
+ {2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0},
+ {2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0},
+
+ {2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+
+ {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0},
+
+ {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2412, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
+ {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
+ {2467, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
+ {2312, 2732, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
+};
+
+enum {
+ T1_2312_2372,
+ T1_2437_2437,
+ T2_2437_2437,
+ T3_2437_2437,
+ T1_2512_2732
+};
+
+static struct regDomain regDomains[] = {
+
+ {DEBUG_REG_DMN, FCC, DFS_FCC3, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(A_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5130_5650, T1_5150_5670, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5240, T1_5280_5280, T1_5540_5660, T1_5765_5805, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_2312_2372, F1_2412_2472, F1_2484_2484, F1_2512_2732, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_2312_2372, T1_2437_2437, T1_2512_2732, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1)},
+
+ {APL1, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL2, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL3, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5280_5320, F2_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5290_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL4, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F4_5180_5240, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5210_5210, T3_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5200, T3_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL5, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T4_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T4_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL6, ETSI, DFS_ETSI, PSCAN_FCC_T | PSCAN_FCC, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F4_5180_5240, F2_5260_5320, F3_5745_5825, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_5210_5210, T1_5250_5290, T1_5760_5800, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5280, T5_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL7, ETSI, DFS_ETSI, PSCAN_ETSI, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5280_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL8, ETSI, NO_DFS, NO_PSCAN,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F6_5260_5320, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_5290_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL9, ETSI, DFS_ETSI, PSCAN_ETSI,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5180_5320, F1_5500_5620, F3_5745_5805, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {APL10, ETSI, DFS_ETSI, PSCAN_ETSI,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5180_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F4_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {ETSI2, ETSI, DFS_ETSI, PSCAN_ETSI,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F3_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {ETSI3, ETSI, DFS_ETSI, PSCAN_ETSI,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {ETSI4, ETSI, DFS_ETSI, PSCAN_ETSI,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F3_5180_5240, F1_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {ETSI5, ETSI, DFS_ETSI, PSCAN_ETSI,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T4_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {ETSI6, ETSI, DFS_ETSI, PSCAN_ETSI,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F5_5180_5240, F1_5260_5280, F3_5500_5700, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5210_5250, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T4_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {FCC1, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_5180_5240, F4_5260_5320, F5_5745_5825, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T6_5210_5210, T2_5250_5290, T6_5760_5800, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5240, T2_5280_5280, T7_5765_5805, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {FCC2, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F6_5180_5240, F5_5260_5320, F6_5745_5825, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {FCC3, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_5180_5240, F3_5260_5320, F1_5500_5700, F5_5745_5825, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T4_5200_5200, T8_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {FCC4, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_4942_4987, F1_4945_4985, F1_4950_4980, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T8_5210_5210, T4_5250_5290, T7_5760_5800, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5240, T1_5280_5280, T9_5765_5805, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {FCC5, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_5180_5240, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T8_5200_5200, T7_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {FCC6, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F8_5180_5240, F5_5260_5320, F1_5500_5580, F1_5660_5700,
+ F6_5745_5825, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {MKK1, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {MKK2, MKK, NO_DFS, PSCAN_MKK2, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
+ F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240,
+ F2_5260_5320, F4_5500_5700, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK3, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK4, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T10_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK5, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK6, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_5170_5230, F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK7, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3,
+ DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T5_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK8, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3,
+ DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK9, MKK, NO_DFS, PSCAN_MKK2 | PSCAN_MKK3,
+ DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
+ F1_5055_5055, F1_5040_5080, F4_5180_5240, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK10, MKK, DFS_MKK4, PSCAN_MKK2 | PSCAN_MKK3,
+ DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
+ F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK11, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
+ F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320,
+ F4_5500_5700, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK12, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3,
+ DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
+ F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240,
+ F2_5260_5320, F4_5500_5700, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK13, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_5170_5230, F7_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK14, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
+ F1_5040_5080, F1_5055_5055, F1_5170_5230, F4_5180_5240, -1, -1,
+ -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {MKK15, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
+ F1_5040_5080, F1_5055_5055, F1_5170_5230, F4_5180_5240,
+ F2_5260_5320, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+
+ {APLD, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_2312_2372, F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G2_2312_2372, G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ BMZERO},
+
+ {ETSIA, NO_CTL, NO_DFS, PSCAN_ETSIA,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {ETSIB, ETSI, NO_DFS, PSCAN_ETSIB,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {ETSIC, ETSI, NO_DFS, PSCAN_ETSIC,
+ DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {FCCA, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {MKKA, MKK, NO_DFS,
+ PSCAN_MKKA | PSCAN_MKKA_G | PSCAN_MKKA1 | PSCAN_MKKA1_G |
+ PSCAN_MKKA2 | PSCAN_MKKA2_G, DISALLOW_ADHOC_11A_TURB,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_2412_2462, F1_2467_2472, F2_2484_2484, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G2_2412_2462, G1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {MKKC, MKK, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WORLD, ETSI, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR0_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
+ W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1),
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
+ W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR01_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR,
+ ADHOC_PER_11D,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
+ W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1),
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432,
+ W1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR02_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR,
+ ADHOC_PER_11D,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
+ W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1),
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
+ W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {EU1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
+ W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1),
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W2_2472_2472,
+ W1_2417_2432, W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG2_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
+ W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
+ W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR2_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
+ W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1),
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
+ W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR3_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1),
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
+ W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG2_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR4_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1),
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432,
+ W1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR5_ETSIC, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
+ W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WOR9_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1),
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432,
+ W1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WORA_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1,
+ -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
+ W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {WORB_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_5260_5320, W1_5180_5240, W1_5500_5700, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
+ W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1),
+ /* LINTED E_FALSE_LOGICAL_EXPR */
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO}
+};
+
+static const struct cmode modes[] = {
+ {ATH9K_MODE_11A, CHANNEL_A},
+ {ATH9K_MODE_11B, CHANNEL_B},
+ {ATH9K_MODE_11G, CHANNEL_G},
+ {ATH9K_MODE_11NG_HT20, CHANNEL_G_HT20},
+ {ATH9K_MODE_11NG_HT40PLUS, CHANNEL_G_HT40PLUS},
+ {ATH9K_MODE_11NG_HT40MINUS, CHANNEL_G_HT40MINUS},
+ {ATH9K_MODE_11NA_HT20, CHANNEL_A_HT20},
+ {ATH9K_MODE_11NA_HT40PLUS, CHANNEL_A_HT40PLUS},
+ {ATH9K_MODE_11NA_HT40MINUS, CHANNEL_A_HT40MINUS},
+};
+
+static struct japan_bandcheck j_bandcheck[] = {
+ {F1_5170_5230, AR_EEPROM_EEREGCAP_EN_KK_U1_ODD},
+ {F4_5180_5240, AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN},
+ {F2_5260_5320, AR_EEPROM_EEREGCAP_EN_KK_U2},
+ {F4_5500_5700, AR_EEPROM_EEREGCAP_EN_KK_MIDBAND}
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARN_REGD_COMMON_H */
diff --git a/usr/src/uts/common/io/arn/arn_xmit.c b/usr/src/uts/common/io/arn/arn_xmit.c
new file mode 100644
index 0000000000..98649b9d11
--- /dev/null
+++ b/usr/src/uts/common/io/arn/arn_xmit.c
@@ -0,0 +1,1016 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * 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.
+ */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/stream.h>
+#include <sys/termio.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <sys/cmn_err.h>
+#include <sys/stropts.h>
+#include <sys/strsubr.h>
+#include <sys/strtty.h>
+#include <sys/kbio.h>
+#include <sys/cred.h>
+#include <sys/stat.h>
+#include <sys/consdev.h>
+#include <sys/kmem.h>
+#include <sys/modctl.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/pci.h>
+#include <sys/errno.h>
+#include <sys/mac_provider.h>
+#include <sys/dlpi.h>
+#include <sys/ethernet.h>
+#include <sys/list.h>
+#include <sys/byteorder.h>
+#include <sys/strsun.h>
+#include <sys/policy.h>
+#include <inet/common.h>
+#include <inet/nd.h>
+#include <inet/mi.h>
+#include <inet/wifi_ioctl.h>
+#include <sys/mac_wifi.h>
+
+#include "arn_core.h"
+
+#define BITS_PER_BYTE 8
+#define OFDM_PLCP_BITS 22
+#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f)
+#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
+#define L_STF 8
+#define L_LTF 8
+#define L_SIG 4
+#define HT_SIG 8
+#define HT_STF 4
+#define HT_LTF(_ns) (4 * (_ns))
+#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */
+#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */
+#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
+#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
+
+#define OFDM_SIFS_TIME 16
+
+#define IS_HT_RATE(_rate) ((_rate) & 0x80)
+
+static void
+arn_get_beaconconfig(struct arn_softc *sc, struct ath_beacon_config *conf)
+{
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ieee80211_node *in = ic->ic_bss;
+
+ /* fill in beacon config data */
+
+ conf->beacon_interval = in->in_intval ?
+ in->in_intval : ATH_DEFAULT_BINTVAL;
+ conf->listen_interval = 100;
+ conf->dtim_count = 1;
+ conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
+}
+
+static void
+arn_tx_stopdma(struct arn_softc *sc, struct ath_txq *txq)
+{
+ struct ath_hal *ah = sc->sc_ah;
+
+ (void) ath9k_hw_stoptxdma(ah, txq->axq_qnum);
+
+ ARN_DBG((ARN_DBG_XMIT, "arn: arn_drain_txdataq(): "
+ "tx queue [%u] %x, link %p\n",
+ txq->axq_qnum,
+ ath9k_hw_gettxbuf(ah, txq->axq_qnum), txq->axq_link));
+
+}
+
+/* Drain only the data queues */
+/* ARGSUSED */
+static void
+arn_drain_txdataq(struct arn_softc *sc, boolean_t retry_tx)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ int i, status, npend = 0;
+
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ARN_TXQ_SETUP(sc, i)) {
+ arn_tx_stopdma(sc, &sc->sc_txq[i]);
+ /*
+ * The TxDMA may not really be stopped.
+ * Double check the hal tx pending count
+ */
+ npend += ath9k_hw_numtxpending(ah,
+ sc->sc_txq[i].axq_qnum);
+ }
+ }
+ }
+
+ if (npend) {
+ /* TxDMA not stopped, reset the hal */
+ ARN_DBG((ARN_DBG_XMIT, "arn: arn_drain_txdataq(): "
+ "Unable to stop TxDMA. Reset HAL!\n"));
+
+ if (!ath9k_hw_reset(ah,
+ sc->sc_ah->ah_curchan,
+ sc->tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, B_TRUE, &status)) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: arn_drain_txdataq(): "
+ "unable to reset hardware; hal status %u\n",
+ status));
+ }
+ }
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ARN_TXQ_SETUP(sc, i))
+ arn_tx_draintxq(sc, &sc->sc_txq[i]);
+ }
+}
+
+/* Setup a h/w transmit queue */
+struct ath_txq *
+arn_txq_setup(struct arn_softc *sc, int qtype, int subtype)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath9k_tx_queue_info qi;
+ int qnum;
+
+ (void) memset(&qi, 0, sizeof (qi));
+ qi.tqi_subtype = subtype;
+ qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
+ qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+ qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
+ qi.tqi_physCompBuf = 0;
+
+ /*
+ * Enable interrupts only for EOL and DESC conditions.
+ * We mark tx descriptors to receive a DESC interrupt
+ * when a tx queue gets deep; otherwise waiting for the
+ * EOL to reap descriptors. Note that this is done to
+ * reduce interrupt load and this only defers reaping
+ * descriptors, never transmitting frames. Aside from
+ * reducing interrupts this also permits more concurrency.
+ * The only potential downside is if the tx queue backs
+ * up in which case the top half of the kernel may backup
+ * due to a lack of tx descriptors.
+ *
+ * The UAPSD queue is an exception, since we take a desc-
+ * based intr on the EOSP frames.
+ */
+ if (qtype == ATH9K_TX_QUEUE_UAPSD)
+ qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
+ else
+ qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
+ TXQ_FLAG_TXDESCINT_ENABLE;
+ qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
+ if (qnum == -1) {
+ /*
+ * NB: don't print a message, this happens
+ * normally on parts with too few tx queues
+ */
+ return (NULL);
+ }
+ if (qnum >= ARRAY_SIZE(sc->sc_txq)) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: arn_txq_setup(): "
+ "hal qnum %u out of range, max %u!\n",
+ qnum, (unsigned int)ARRAY_SIZE(sc->sc_txq)));
+ (void) ath9k_hw_releasetxqueue(ah, qnum);
+ return (NULL);
+ }
+ if (!ARN_TXQ_SETUP(sc, qnum)) {
+ struct ath_txq *txq = &sc->sc_txq[qnum];
+
+ txq->axq_qnum = qnum;
+ txq->axq_intrcnt = 0;
+ txq->axq_link = NULL;
+
+ list_create(&txq->axq_list, sizeof (struct ath_buf),
+ offsetof(struct ath_buf, bf_node));
+ mutex_init(&txq->axq_lock, NULL, MUTEX_DRIVER, NULL);
+
+ txq->axq_depth = 0;
+ txq->axq_aggr_depth = 0;
+ txq->axq_totalqueued = 0;
+ /* txq->axq_linkbuf = NULL; */
+ sc->sc_txqsetup |= 1<<qnum;
+ }
+ return (&sc->sc_txq[qnum]);
+}
+
+/* Reclaim resources for a setup queue */
+
+void
+arn_tx_cleanupq(struct arn_softc *sc, struct ath_txq *txq)
+{
+ (void) ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
+ sc->sc_txqsetup &= ~(1<<txq->axq_qnum);
+}
+
+/*
+ * Setup a hardware data transmit queue for the specified
+ * access control. The hal may not support all requested
+ * queues in which case it will return a reference to a
+ * previously setup queue. We record the mapping from ac's
+ * to h/w queues for use by arn_tx_start and also track
+ * the set of h/w queues being used to optimize work in the
+ * transmit interrupt handler and related routines.
+ */
+
+int
+arn_tx_setup(struct arn_softc *sc, int haltype)
+{
+ struct ath_txq *txq;
+
+ if (haltype >= ARRAY_SIZE(sc->sc_haltype2q)) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: arn_tx_setup(): "
+ "HAL AC %u out of range, max %zu!\n",
+ haltype, ARRAY_SIZE(sc->sc_haltype2q)));
+ return (0);
+ }
+ txq = arn_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
+ if (txq != NULL) {
+ sc->sc_haltype2q[haltype] = txq->axq_qnum;
+ return (1);
+ } else
+ return (0);
+}
+
+int
+arn_tx_get_qnum(struct arn_softc *sc, int qtype, int haltype)
+{
+ int qnum;
+
+ switch (qtype) {
+ case ATH9K_TX_QUEUE_DATA:
+ if (haltype >= ARRAY_SIZE(sc->sc_haltype2q)) {
+ ARN_DBG((ARN_DBG_FATAL, "arn: arn_tx_get_qnum(): "
+ "HAL AC %u out of range, max %zu!\n",
+ haltype, ARRAY_SIZE(sc->sc_haltype2q)));
+ return (-1);
+ }
+ qnum = sc->sc_haltype2q[haltype];
+ break;
+ case ATH9K_TX_QUEUE_BEACON:
+ qnum = sc->sc_beaconq;
+ break;
+ case ATH9K_TX_QUEUE_CAB:
+ qnum = sc->sc_cabq->axq_qnum;
+ break;
+ default:
+ qnum = -1;
+ }
+ return (qnum);
+}
+
+void
+arn_tx_draintxq(struct arn_softc *sc, struct ath_txq *txq)
+{
+ struct ath_buf *bf;
+
+ /*
+ * This assumes output has been stopped.
+ */
+ for (;;) {
+ mutex_enter(&txq->axq_lock);
+ bf = list_head(&txq->axq_list);
+ if (bf == NULL) {
+ txq->axq_link = NULL;
+ mutex_exit(&txq->axq_lock);
+ break;
+ }
+ list_remove(&txq->axq_list, bf);
+ mutex_exit(&txq->axq_lock);
+ bf->bf_in = NULL;
+ mutex_enter(&sc->sc_txbuflock);
+ list_insert_tail(&sc->sc_txbuf_list, bf);
+ mutex_exit(&sc->sc_txbuflock);
+ }
+}
+
+/* Drain the transmit queues and reclaim resources */
+
+void
+arn_draintxq(struct arn_softc *sc, boolean_t retry_tx)
+{
+ /*
+ * stop beacon queue. The beacon will be freed when
+ * we go to INIT state
+ */
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_beaconq);
+ ARN_DBG((ARN_DBG_XMIT, "arn: arn_draintxq(): "
+ "beacon queue %x\n",
+ ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_beaconq)));
+ }
+
+ arn_drain_txdataq(sc, retry_tx);
+}
+
+uint32_t
+arn_txq_depth(struct arn_softc *sc, int qnum)
+{
+ return (sc->sc_txq[qnum].axq_depth);
+}
+
+uint32_t
+arn_txq_aggr_depth(struct arn_softc *sc, int qnum)
+{
+ return (sc->sc_txq[qnum].axq_aggr_depth);
+}
+
+/* Update parameters for a transmit queue */
+int
+arn_txq_update(struct arn_softc *sc, int qnum,
+ struct ath9k_tx_queue_info *qinfo)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ int error = 0;
+ struct ath9k_tx_queue_info qi;
+
+ if (qnum == sc->sc_beaconq) {
+ /*
+ * XXX: for beacon queue, we just save the parameter.
+ * It will be picked up by arn_beaconq_config() when
+ * it's necessary.
+ */
+ sc->sc_beacon_qi = *qinfo;
+ return (0);
+ }
+
+ ASSERT(sc->sc_txq[qnum].axq_qnum == qnum);
+
+ (void) ath9k_hw_get_txq_props(ah, qnum, &qi);
+ qi.tqi_aifs = qinfo->tqi_aifs;
+ qi.tqi_cwmin = qinfo->tqi_cwmin;
+ qi.tqi_cwmax = qinfo->tqi_cwmax;
+ qi.tqi_burstTime = qinfo->tqi_burstTime;
+ qi.tqi_readyTime = qinfo->tqi_readyTime;
+
+ if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
+ ARN_DBG((ARN_DBG_FATAL,
+ "Unable to update hardware queue %u!\n", qnum));
+ error = -EIO;
+ } else {
+ (void) ath9k_hw_resettxqueue(ah, qnum); /* push to h/w */
+ }
+
+ return (error);
+}
+
+int
+ath_cabq_update(struct arn_softc *sc)
+{
+ struct ath9k_tx_queue_info qi;
+ int qnum = sc->sc_cabq->axq_qnum;
+ struct ath_beacon_config conf;
+
+ (void) ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
+ /*
+ * Ensure the readytime % is within the bounds.
+ */
+ if (sc->sc_config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
+ sc->sc_config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
+ else if (sc->sc_config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
+ sc->sc_config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
+
+ arn_get_beaconconfig(sc, &conf);
+ qi.tqi_readyTime =
+ (conf.beacon_interval * sc->sc_config.cabqReadytime) / 100;
+ (void) arn_txq_update(sc, qnum, &qi);
+
+ return (0);
+}
+
+static uint32_t
+arn_tx_get_keytype(const struct ieee80211_cipher *cip)
+{
+ uint32_t index;
+ static const uint8_t ciphermap[] = {
+ ATH9K_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */
+ ATH9K_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */
+ ATH9K_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */
+ ATH9K_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */
+ ATH9K_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */
+ ATH9K_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */
+ };
+
+ ASSERT(cip->ic_cipher < ARRAY_SIZE(ciphermap));
+ index = cip->ic_cipher;
+
+ if (ciphermap[index] == ATH9K_CIPHER_WEP)
+ return (ATH9K_KEY_TYPE_WEP);
+ else if (ciphermap[index] == ATH9K_CIPHER_TKIP)
+ return (ATH9K_KEY_TYPE_TKIP);
+ else if (ciphermap[index] == ATH9K_CIPHER_AES_CCM)
+ return (ATH9K_KEY_TYPE_AES);
+
+ return (ATH9K_KEY_TYPE_CLEAR);
+
+}
+
+/*
+ * The input parameter mp has following assumption:
+ * For data packets, GLDv3 mac_wifi plugin allocates and fills the
+ * ieee80211 header. For management packets, net80211 allocates and
+ * fills the ieee80211 header. In both cases, enough spaces in the
+ * header are left for encryption option.
+ */
+static int32_t
+arn_tx_start(struct arn_softc *sc, struct ieee80211_node *in,
+ struct ath_buf *bf, mblk_t *mp)
+{
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ieee80211_frame *wh;
+ struct ath_hal *ah = sc->sc_ah;
+ uint32_t flags;
+ uint32_t subtype, ctsduration;
+ int32_t keyix, iswep, hdrlen, pktlen, mblen, mbslen;
+ /* LINTED E_FUNC_SET_NOT_USED */
+ int32_t try0;
+ uint8_t rix, cix, txrate, ctsrate;
+ struct ath_desc *ds;
+ struct ath_txq *txq;
+ enum ath9k_pkt_type atype;
+ struct ath_rate_table *rt;
+ boolean_t shortPreamble;
+ boolean_t is_pspoll;
+ struct ath_node *an;
+ caddr_t dest;
+ uint32_t keytype = ATH9K_KEY_TYPE_CLEAR;
+
+ /*
+ * CRC are added by H/W, not encaped by driver,
+ * but we must count it in pkt length.
+ */
+ pktlen = IEEE80211_CRC_LEN;
+
+ wh = (struct ieee80211_frame *)mp->b_rptr;
+ iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
+ keyix = ATH9K_TXKEYIX_INVALID;
+ hdrlen = sizeof (struct ieee80211_frame);
+ if (iswep != 0) {
+ const struct ieee80211_cipher *cip;
+ struct ieee80211_key *k;
+
+ /*
+ * Construct the 802.11 header+trailer for an encrypted
+ * frame. The only reason this can fail is because of an
+ * unknown or unsupported cipher/key type.
+ */
+ k = ieee80211_crypto_encap(ic, mp);
+ if (k == NULL) {
+ ARN_DBG((ARN_DBG_XMIT, "arn: arn_tx_start "
+ "crypto_encap failed\n"));
+ /*
+ * This can happen when the key is yanked after the
+ * frame was queued. Just discard the frame; the
+ * 802.11 layer counts failures and provides
+ * debugging/diagnostics.
+ */
+ return (EIO);
+ }
+ cip = k->wk_cipher;
+
+ keytype = arn_tx_get_keytype(cip);
+
+ /*
+ * Adjust the packet + header lengths for the crypto
+ * additions and calculate the h/w key index. When
+ * a s/w mic is done the frame will have had any mic
+ * added to it prior to entry so m0->m_pkthdr.len above will
+ * account for it. Otherwise we need to add it to the
+ * packet length.
+ */
+ hdrlen += cip->ic_header;
+ pktlen += cip->ic_trailer;
+ if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0)
+ pktlen += cip->ic_miclen;
+
+ keyix = k->wk_keyix;
+
+ /* packet header may have moved, reset our local pointer */
+ wh = (struct ieee80211_frame *)mp->b_rptr;
+ }
+
+ dest = bf->bf_dma.mem_va;
+ for (; mp != NULL; mp = mp->b_cont) {
+ mblen = MBLKL(mp);
+ bcopy(mp->b_rptr, dest, mblen);
+ dest += mblen;
+ }
+ mbslen = (uintptr_t)dest - (uintptr_t)bf->bf_dma.mem_va;
+ pktlen += mbslen;
+
+ bf->bf_in = in;
+
+ /* setup descriptors */
+ ds = bf->bf_desc;
+ rt = sc->sc_currates;
+ ASSERT(rt != NULL);
+
+ /*
+ * The 802.11 layer marks whether or not we should
+ * use short preamble based on the current mode and
+ * negotiated parameters.
+ */
+ if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
+ (in->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
+ shortPreamble = B_TRUE;
+ sc->sc_stats.ast_tx_shortpre++;
+ } else {
+ shortPreamble = B_FALSE;
+ }
+
+ an = (struct ath_node *)(in);
+
+ /*
+ * Calculate Atheros packet type from IEEE80211 packet header
+ * and setup for rate calculations.
+ */
+ switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
+ case IEEE80211_FC0_TYPE_MGT:
+ subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+ if (subtype == IEEE80211_FC0_SUBTYPE_BEACON)
+ atype = ATH9K_PKT_TYPE_BEACON;
+ else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
+ atype = ATH9K_PKT_TYPE_PROBE_RESP;
+ else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM)
+ atype = ATH9K_PKT_TYPE_ATIM;
+ else
+ atype = ATH9K_PKT_TYPE_NORMAL;
+ rix = 0; /* lowest rate */
+ try0 = ATH_TXMAXTRY;
+ if (shortPreamble) {
+ txrate = an->an_tx_mgtratesp;
+ } else {
+ txrate = an->an_tx_mgtrate;
+ }
+ /* force all ctl frames to highest queue */
+ txq = &sc->sc_txq[arn_get_hal_qnum(WME_AC_VO, sc)];
+ break;
+ case IEEE80211_FC0_TYPE_CTL:
+ atype = ATH9K_PKT_TYPE_PSPOLL;
+ is_pspoll = B_TRUE;
+ subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+ rix = 0; /* lowest rate */
+ try0 = ATH_TXMAXTRY;
+ if (shortPreamble)
+ txrate = an->an_tx_mgtratesp;
+ else
+ txrate = an->an_tx_mgtrate;
+ /* force all ctl frames to highest queue */
+ txq = &sc->sc_txq[arn_get_hal_qnum(WME_AC_VO, sc)];
+ break;
+ case IEEE80211_FC0_TYPE_DATA:
+ atype = ATH9K_PKT_TYPE_NORMAL;
+ rix = an->an_tx_rix0;
+ try0 = an->an_tx_try0;
+ if (shortPreamble)
+ txrate = an->an_tx_rate0sp;
+ else
+ txrate = an->an_tx_rate0;
+ /* Always use background queue */
+ txq = &sc->sc_txq[arn_get_hal_qnum(WME_AC_BK, sc)];
+ break;
+ default:
+ /* Unknown 802.11 frame */
+ sc->sc_stats.ast_tx_invalid++;
+ return (1);
+ }
+
+ /*
+ * Calculate miscellaneous flags.
+ */
+ flags = ATH9K_TXDESC_CLRDMASK;
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ flags |= ATH9K_TXDESC_NOACK; /* no ack on broad/multicast */
+ sc->sc_stats.ast_tx_noack++;
+ } else if (pktlen > ic->ic_rtsthreshold) {
+ flags |= ATH9K_TXDESC_RTSENA; /* RTS based on frame length */
+ sc->sc_stats.ast_tx_rts++;
+ }
+
+ /*
+ * Calculate duration. This logically belongs in the 802.11
+ * layer but it lacks sufficient information to calculate it.
+ */
+ if ((flags & ATH9K_TXDESC_NOACK) == 0 &&
+ (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
+ IEEE80211_FC0_TYPE_CTL) {
+ uint16_t dur;
+ dur = ath9k_hw_computetxtime(ah, rt, IEEE80211_ACK_SIZE,
+ rix, shortPreamble);
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ *(uint16_t *)wh->i_dur = LE_16(dur);
+ }
+
+ /*
+ * Calculate RTS/CTS rate and duration if needed.
+ */
+ ctsduration = 0;
+ if (flags & (ATH9K_TXDESC_RTSENA|ATH9K_TXDESC_CTSENA)) {
+ /*
+ * CTS transmit rate is derived from the transmit rate
+ * by looking in the h/w rate table. We must also factor
+ * in whether or not a short preamble is to be used.
+ */
+ cix = rt->info[rix].ctrl_rate;
+ ctsrate = rt->info[cix].ratecode;
+ if (shortPreamble)
+ ctsrate |= rt->info[cix].short_preamble;
+ /*
+ * Compute the transmit duration based on the size
+ * of an ACK frame. We call into the HAL to do the
+ * computation since it depends on the characteristics
+ * of the actual PHY being used.
+ */
+ if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */
+ ctsduration += ath9k_hw_computetxtime(ah,
+ rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
+ }
+ /* SIFS + data */
+ ctsduration += ath9k_hw_computetxtime(ah,
+ rt, pktlen, rix, shortPreamble);
+ if ((flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */
+ ctsduration += ath9k_hw_computetxtime(ah,
+ rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
+ }
+ } else
+ ctsrate = 0;
+
+ if (++txq->axq_intrcnt >= 5) {
+ flags |= ATH9K_TXDESC_INTREQ;
+ txq->axq_intrcnt = 0;
+ }
+
+ /* setup descriptor */
+ ds->ds_link = 0;
+ ds->ds_data = bf->bf_dma.cookie.dmac_address;
+
+ /*
+ * Formulate first tx descriptor with tx controls.
+ */
+ ath9k_hw_set11n_txdesc(ah, ds,
+ pktlen, /* packet length */
+ atype, /* Atheros packet type */
+ MAX_RATE_POWER /* MAX_RATE_POWER */,
+ keyix /* ATH9K_TXKEYIX_INVALID */,
+ keytype /* ATH9K_KEY_TYPE_CLEAR */,
+ flags /* flags */);
+ bf->bf_flags = (uint16_t)flags; /* LINT */
+
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ ARN_DBG((ARN_DBG_XMIT, "arn: arn_tx_start(): to %s totlen=%d "
+ "an->an_tx_rate1sp=%d tx_rate2sp=%d tx_rate3sp=%d "
+ "qnum=%d rix=%d sht=%d dur = %d\n",
+ ieee80211_macaddr_sprintf(wh->i_addr1), mbslen, an->an_tx_rate1sp,
+ an->an_tx_rate2sp, an->an_tx_rate3sp,
+ txq->axq_qnum, rix, shortPreamble, *(uint16_t *)wh->i_dur));
+
+ (void) ath9k_hw_filltxdesc(ah, ds,
+ mbslen, /* segment length */
+ B_TRUE, /* first segment */
+ B_TRUE, /* last segment */
+ ds); /* first descriptor */
+
+ /* set rate related fields in tx descriptor */
+ struct ath9k_11n_rate_series series[4];
+ (void) memset(series, 0, sizeof (struct ath9k_11n_rate_series) * 4);
+
+#ifdef MULTIRATE_RETRY
+ int i;
+ for (i = 1; i < 4; i++) {
+ series[i].Tries = 2; /* ??? */
+ series[i].ChSel = sc->sc_tx_chainmask;
+
+ series[i].RateFlags &= ~ATH9K_RATESERIES_RTS_CTS;
+ series[i].RateFlags &= ~ATH9K_RATESERIES_2040;
+ series[i].RateFlags &= ~ATH9K_RATESERIES_HALFGI;
+
+ series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
+ rt, pktlen, rix, shortPreamble);
+ }
+#endif
+
+ /* main rate */
+ series[0].Rate = txrate;
+ series[0].Tries = ATH_TXMAXTRY;
+ series[0].RateFlags &= ~ATH9K_RATESERIES_RTS_CTS;
+ series[0].RateFlags &= ~ATH9K_RATESERIES_2040;
+ series[0].RateFlags &= ~ATH9K_RATESERIES_HALFGI;
+ series[0].ChSel = sc->sc_tx_chainmask;
+ series[0].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, rt, pktlen,
+ rix, shortPreamble);
+
+#ifdef MULTIRATE_RETRY
+ if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
+ (in->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
+ series[1].Rate = an->an_tx_rate1sp;
+ series[2].Rate = an->an_tx_rate2sp;
+ series[3].Rate = an->an_tx_rate3sp;
+ }
+ else
+ {
+ series[1].Rate = an->an_tx_rate1;
+ series[2].Rate = an->an_tx_rate2;
+ series[3].Rate = an->an_tx_rate3;
+ }
+#endif
+
+ /* set dur_update_en for l-sig computation except for PS-Poll frames */
+ ath9k_hw_set11n_ratescenario(sc->sc_ah, ds,
+ ds, !is_pspoll, ctsrate, 0, series, 4, flags);
+
+ ARN_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV);
+
+ mutex_enter(&txq->axq_lock);
+ list_insert_tail(&txq->axq_list, bf);
+ if (txq->axq_link == NULL) {
+ (void) ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+ } else {
+ *txq->axq_link = bf->bf_daddr;
+ }
+ txq->axq_link = &ds->ds_link;
+ mutex_exit(&txq->axq_lock);
+
+ (void) ath9k_hw_txstart(ah, txq->axq_qnum);
+
+ ic->ic_stats.is_tx_frags++;
+ ic->ic_stats.is_tx_bytes += pktlen;
+
+ return (0);
+}
+
+/*
+ * Transmit a management frame.
+ * Note that management frames come directly from the 802.11 layer
+ * and do not honor the send queue flow control.
+ */
+/* Upon failure caller should free mp */
+int
+arn_tx(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
+{
+ struct arn_softc *sc = (struct arn_softc *)ic;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_node *in = NULL;
+ struct ath_buf *bf = NULL;
+ struct ieee80211_frame *wh;
+ int error = 0;
+
+ ASSERT(mp->b_next == NULL);
+ /* should check later */
+ if (sc->sc_flags & SC_OP_INVALID) {
+ if ((type & IEEE80211_FC0_TYPE_MASK) !=
+ IEEE80211_FC0_TYPE_DATA) {
+ freemsg(mp);
+ }
+ return (ENXIO);
+ }
+
+ /* Grab a TX buffer */
+ mutex_enter(&sc->sc_txbuflock);
+ bf = list_head(&sc->sc_txbuf_list);
+ /* Check if a tx buffer is available */
+ if (bf != NULL)
+ list_remove(&sc->sc_txbuf_list, bf);
+ if (list_empty(&sc->sc_txbuf_list)) {
+ ARN_DBG((ARN_DBG_XMIT, "arn: arn_tx(): "
+ "stop queue\n"));
+ sc->sc_stats.ast_tx_qstop++;
+ }
+ mutex_exit(&sc->sc_txbuflock);
+ if (bf == NULL) {
+ ARN_DBG((ARN_DBG_XMIT, "arn: arn_tx(): discard, "
+ "no xmit buf\n"));
+ ic->ic_stats.is_tx_nobuf++;
+ if ((type & IEEE80211_FC0_TYPE_MASK) ==
+ IEEE80211_FC0_TYPE_DATA) {
+ sc->sc_stats.ast_tx_nobuf++;
+ mutex_enter(&sc->sc_resched_lock);
+ sc->sc_resched_needed = B_TRUE;
+ mutex_exit(&sc->sc_resched_lock);
+ } else {
+ sc->sc_stats.ast_tx_nobufmgt++;
+ freemsg(mp);
+ }
+ return (ENOMEM);
+ }
+
+ wh = (struct ieee80211_frame *)mp->b_rptr;
+
+ /* Locate node */
+ in = ieee80211_find_txnode(ic, wh->i_addr1);
+ if (in == NULL) {
+ error = EIO;
+ goto bad;
+ }
+
+ in->in_inact = 0;
+ switch (type & IEEE80211_FC0_TYPE_MASK) {
+ case IEEE80211_FC0_TYPE_DATA:
+ (void) ieee80211_encap(ic, mp, in);
+ break;
+ default:
+ if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
+ IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
+ /* fill time stamp */
+ uint64_t tsf;
+ uint32_t *tstamp;
+
+ tsf = ath9k_hw_gettsf64(ah);
+ /* adjust 100us delay to xmit */
+ tsf += 100;
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ tstamp = (uint32_t *)&wh[1];
+ tstamp[0] = LE_32(tsf & 0xffffffff);
+ tstamp[1] = LE_32(tsf >> 32);
+ }
+ sc->sc_stats.ast_tx_mgmt++;
+ break;
+ }
+
+ error = arn_tx_start(sc, in, bf, mp);
+
+ if (error != 0) {
+bad:
+ ic->ic_stats.is_tx_failed++;
+ if (bf != NULL) {
+ mutex_enter(&sc->sc_txbuflock);
+ list_insert_tail(&sc->sc_txbuf_list, bf);
+ mutex_exit(&sc->sc_txbuflock);
+ }
+ }
+ if (in != NULL)
+ ieee80211_free_node(in);
+ if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA ||
+ error == 0) {
+ freemsg(mp);
+ }
+
+ return (error);
+}
+
+static void
+arn_printtxbuf(struct ath_buf *bf, int done)
+{
+ struct ath_desc *ds = bf->bf_desc;
+ const struct ath_tx_status *ts = &ds->ds_txstat;
+
+ ARN_DBG((ARN_DBG_XMIT, "arn: T(%p %p) %08x %08x %08x %08x %08x"
+ " %08x %08x %08x %c\n",
+ ds, bf->bf_daddr,
+ ds->ds_link, ds->ds_data,
+ ds->ds_ctl0, ds->ds_ctl1,
+ ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
+ !done ? ' ' : (ts->ts_status == 0) ? '*' : '!'));
+}
+
+/* Process completed xmit descriptors from the specified queue */
+
+static int
+arn_tx_processq(struct arn_softc *sc, struct ath_txq *txq)
+{
+ ieee80211com_t *ic = (ieee80211com_t *)sc;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_buf *bf;
+ struct ath_desc *ds;
+ struct ieee80211_node *in;
+ int32_t sr, lr, nacked = 0;
+ struct ath_tx_status *ts;
+ int status;
+ struct ath_node *an;
+
+ for (;;) {
+ mutex_enter(&txq->axq_lock);
+ bf = list_head(&txq->axq_list);
+ if (bf == NULL) {
+ txq->axq_link = NULL;
+ mutex_exit(&txq->axq_lock);
+ break;
+ }
+ ds = bf->bf_desc; /* last decriptor */
+ ts = &ds->ds_txstat;
+ status = ath9k_hw_txprocdesc(ah, ds);
+
+#ifdef DEBUG
+ arn_printtxbuf(bf, status == 0);
+#endif
+
+ if (status == EINPROGRESS) {
+ mutex_exit(&txq->axq_lock);
+ break;
+ }
+ list_remove(&txq->axq_list, bf);
+ mutex_exit(&txq->axq_lock);
+ in = bf->bf_in;
+ if (in != NULL) {
+ an = ATH_NODE(in);
+ /* Successful transmition */
+ if (ts->ts_status == 0) {
+ an->an_tx_ok++;
+ an->an_tx_antenna = ts->ts_antenna;
+ sc->sc_stats.ast_tx_rssidelta =
+ ts->ts_rssi - sc->sc_stats.ast_tx_rssi;
+ sc->sc_stats.ast_tx_rssi = ts->ts_rssi;
+ } else {
+ an->an_tx_err++;
+ if (ts->ts_status & ATH9K_TXERR_XRETRY) {
+ sc->sc_stats.ast_tx_xretries++;
+ }
+ if (ts->ts_status & ATH9K_TXERR_FIFO) {
+ sc->sc_stats.ast_tx_fifoerr++;
+ }
+ if (ts->ts_status & ATH9K_TXERR_FILT) {
+ sc->sc_stats.ast_tx_filtered++;
+ }
+ an->an_tx_antenna = 0; /* invalidate */
+ }
+ sr = ts->ts_shortretry;
+ lr = ts->ts_longretry;
+ sc->sc_stats.ast_tx_shortretry += sr;
+ sc->sc_stats.ast_tx_longretry += lr;
+ /*
+ * Hand the descriptor to the rate control algorithm.
+ */
+ if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
+ (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) {
+ /*
+ * If frame was ack'd update the last rx time
+ * used to workaround phantom bmiss interrupts.
+ */
+ if (ts->ts_status == 0) {
+ nacked++;
+ an->an_tx_ok++;
+ } else {
+ an->an_tx_err++;
+ }
+ an->an_tx_retr += sr + lr;
+ }
+ }
+ bf->bf_in = NULL;
+ mutex_enter(&sc->sc_txbuflock);
+ list_insert_tail(&sc->sc_txbuf_list, bf);
+ mutex_exit(&sc->sc_txbuflock);
+
+ /*
+ * Reschedule stalled outbound packets
+ */
+ mutex_enter(&sc->sc_resched_lock);
+ if (sc->sc_resched_needed) {
+ sc->sc_resched_needed = B_FALSE;
+ mac_tx_update(ic->ic_mach);
+ }
+ mutex_exit(&sc->sc_resched_lock);
+ }
+
+ return (nacked);
+}
+
+static void
+arn_tx_handler(struct arn_softc *sc)
+{
+ int i;
+ int nacked = 0;
+ uint32_t qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
+ ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
+
+ /*
+ * Process each active queue.
+ */
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ARN_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) {
+ nacked += arn_tx_processq(sc, &sc->sc_txq[i]);
+ }
+ }
+
+ if (nacked)
+ sc->sc_lastrx = ath9k_hw_gettsf64(sc->sc_ah);
+}
+
+/* Deferred processing of transmit interrupt */
+
+void
+arn_tx_int_proc(void *arg)
+{
+ struct arn_softc *sc = arg;
+ arn_tx_handler(sc);
+}
diff --git a/usr/src/uts/intel/Makefile.intel.shared b/usr/src/uts/intel/Makefile.intel.shared
index af7ffa81ba..bc76eab8d5 100644
--- a/usr/src/uts/intel/Makefile.intel.shared
+++ b/usr/src/uts/intel/Makefile.intel.shared
@@ -190,6 +190,7 @@ DRV_KMODS += amr
DRV_KMODS += agpgart
DRV_KMODS += srn
DRV_KMODS += agptarget
+DRV_KMODS += arn
DRV_KMODS += arp
DRV_KMODS += asy
DRV_KMODS += ata
diff --git a/usr/src/uts/intel/arn/Makefile b/usr/src/uts/intel/arn/Makefile
new file mode 100644
index 0000000000..7bbf268098
--- /dev/null
+++ b/usr/src/uts/intel/arn/Makefile
@@ -0,0 +1,94 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+
+#
+# This file makes the atheros IEEE 802.11n driver for an intel system
+#
+# intel architecture dependent
+#
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+#
+# Define the module and object file sets.
+#
+MODULE = arn
+OBJECTS = $(ARN_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(ARN_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+# Define targets
+#
+ALL_TARGET = $(BINARY)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+#
+# Driver depends on GLDv3 & wifi kernel support module.
+#
+LDFLAGS += -dy -Nmisc/mac -Nmisc/net80211
+
+LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN
+
+#
+# Default build targets.
+#
+.KEEP_STATE:
+
+def: $(DEF_DEPS)
+
+all: $(ALL_DEPS)
+
+clean: $(CLEAN_DEPS)
+
+clobber: $(CLOBBER_DEPS)
+
+lint: $(LINT_DEPS)
+
+modlintlib: $(MODLINTLIB_DEPS)
+
+clean.lint: $(CLEAN_LINT_DEPS)
+
+install: $(INSTALL_DEPS)
+
+#
+# Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
+
+#
+# If you have any special case that general
+# Makefile rules don't serve for you, just do
+# it yourself.
+#
diff --git a/usr/src/uts/intel/os/minor_perm b/usr/src/uts/intel/os/minor_perm
index 5cf674046c..40009e14af 100644
--- a/usr/src/uts/intel/os/minor_perm
+++ b/usr/src/uts/intel/os/minor_perm
@@ -128,6 +128,7 @@ clone:e1000g 0666 root sys
clone:chxge 0666 root sys
clone:pcn 0666 root sys
clone:rtls 0666 root sys
+clone:arn 0666 root sys
clone:ath 0666 root sys
clone:atu 0666 root sys
clone:vnic 0666 root sys
@@ -160,6 +161,7 @@ e1000g:* 0666 root sys
chxge:* 0666 root sys
pcn:* 0666 root sys
rtls:* 0666 root sys
+arn:* 0666 root sys
ath:* 0666 root sys
atu:* 0666 root sys
vnic:* 0666 root sys