# HG changeset patch # User lin wang - Sun Microsystems - Beijing China # Date 1245690529 -28800 # Node ID 7e332a7c18f5497a2b9e7f5fb232e008d7ac0ed4 # Parent 4aa6e446614db7fc0ee458ccc592159273ef19a8 6814300 Need support for Atheros AR9280 and AR9281 6834736 Need support for new wireless chipset AR9285 diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/pkgdefs/Makefile --- a/usr/src/pkgdefs/Makefile Mon Jun 22 08:25:32 2009 -0700 +++ b/usr/src/pkgdefs/Makefile Tue Jun 23 01:08:49 2009 +0800 @@ -115,6 +115,7 @@ SUNWamt \ SUNWamt-lms \ SUNWarcmsr \ + SUNWarn \ SUNWatheros \ SUNWatigfx \ SUNWatu \ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/pkgdefs/SUNWarn/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWarn/Makefile Tue Jun 23 01:08:49 2009 +0800 @@ -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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/pkgdefs/SUNWarn/pkginfo.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWarn/pkginfo.tmpl Tue Jun 23 01:08:49 2009 +0800 @@ -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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/pkgdefs/SUNWarn/postinstall --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWarn/postinstall Tue Jun 23 01:08:49 2009 +0800 @@ -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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/pkgdefs/SUNWarn/postremove --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWarn/postremove Tue Jun 23 01:08:49 2009 +0800 @@ -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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/pkgdefs/SUNWarn/prototype_com --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWarn/prototype_com Tue Jun 23 01:08:49 2009 +0800 @@ -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 # where to find pkg objects +#!include # include another 'prototype' file +#!default # default used if not specified on entry +#!= # puts parameter in pkg environment + +# +# SUNWarn +# + +i pkginfo +i copyright +i depend +i postinstall +i postremove diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/pkgdefs/SUNWarn/prototype_i386 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWarn/prototype_i386 Tue Jun 23 01:08:49 2009 +0800 @@ -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 # where to find pkg objects +#!include # include another 'prototype' file +#!default # default used if not specified on entry +#!= # 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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/pkgdefs/common_files/i.minorperm_i386 --- a/usr/src/pkgdefs/common_files/i.minorperm_i386 Mon Jun 22 08:25:32 2009 -0700 +++ b/usr/src/pkgdefs/common_files/i.minorperm_i386 Tue Jun 23 01:08:49 2009 +0800 @@ -109,6 +109,7 @@ 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 @@ -138,6 +139,7 @@ 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* @@ -294,6 +296,7 @@ clone:chxge clone:pcn clone:rtls +clone:arn clone:ath clone:atu clone:ipw @@ -323,6 +326,7 @@ chxge:* pcn:* rtls:* +arn:* ath:* atu:* ipw:* diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/tools/opensolaris/license-list --- a/usr/src/tools/opensolaris/license-list Mon Jun 22 08:25:32 2009 -0700 +++ b/usr/src/tools/opensolaris/license-list Tue Jun 23 01:08:49 2009 +0800 @@ -139,6 +139,7 @@ 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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/Makefile.files --- a/usr/src/uts/common/Makefile.files Mon Jun 22 08:25:32 2009 -0700 +++ b/usr/src/uts/common/Makefile.files Tue Jun 23 01:08:49 2009 +0800 @@ -1702,6 +1702,9 @@ URTW_OBJS += urtw.o +ARN_OBJS += hw.o eeprom.o mac.o calib.o ani.o phy.o regd.o beacon.o \ + arn_main.o recv.o xmit.o rc.o + ATH_OBJS += ath_aux.o ath_main.o ath_osdep.o ath_rate.o ATU_OBJS += atu.o diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/Makefile.rules --- a/usr/src/uts/common/Makefile.rules Mon Jun 22 08:25:32 2009 -0700 +++ b/usr/src/uts/common/Makefile.rules Tue Jun 23 01:08:49 2009 +0800 @@ -528,6 +528,10 @@ $(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) @@ -1759,6 +1763,9 @@ $(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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/LICENSE Tue Jun 23 01:08:49 2009 +0800 @@ -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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/LICENSE.descrip --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/LICENSE.descrip Tue Jun 23 01:08:49 2009 +0800 @@ -0,0 +1,1 @@ +Atheros AR5416/5418/9280/9281/9285 IEEE802.11 a/b/g/n Wireless Network Driver diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/ani.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/ani.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 "core.h" +#include "hw.h" +#include "reg.h" +#include "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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/arn_main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/arn_main.c Tue Jun 23 01:08:49 2009 +0800 @@ -0,0 +1,3187 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ath9k.h" +#include "core.h" +#include "reg.h" +#include "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) + 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"); + } + } + +#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")); + } +#endif + + ARN_UNLOCK(sc); + + 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.0", /* 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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/ath9k.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/ath9k.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _ATH9K_H +#define _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 /* _ATH9K_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/beacon.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/beacon.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 +#include +#include +#include +#include +#include + +#include "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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/calib.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/calib.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 "core.h" +#include "hw.h" +#include "reg.h" +#include "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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/core.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/core.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _CORE_H +#define _CORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "ath9k.h" +#include "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<= 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 /* _CORE_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/eeprom.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/eeprom.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "hw.h" +#include "reg.h" +#include "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, ¢ers); + + 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, ¢ers); + + 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, ¢ers); + freq = (isExtTarget) ? centers.ext_center : centers.ctl_center; + + if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, + IS_CHAN_2GHZ(chan))) { + matchIndex = 0; + } else { + for (i = 0; (i < numChannels) && + (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel, + IS_CHAN_2GHZ(chan))) { + matchIndex = i; + break; + } else if ((freq < + ath9k_hw_fbin2freq(powInfo[i].bChannel, + IS_CHAN_2GHZ(chan))) && + (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, + IS_CHAN_2GHZ(chan)))) { + lowIndex = i - 1; + break; + } + } + if ((matchIndex == -1) && (lowIndex == -1)) + matchIndex = i - 1; + } + + if (matchIndex != -1) { + *pNewPower = powInfo[matchIndex]; + } else { + clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, + IS_CHAN_2GHZ(chan)); + chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, + IS_CHAN_2GHZ(chan)); + + for (i = 0; i < numRates; i++) { + pNewPower->tPow2x[i] = + (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, ¢ers); + freq = isHt40Target ? centers.synth_center : centers.ctl_center; + + if (freq <= + ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) { + matchIndex = 0; + } else { + for (i = 0; (i < numChannels) && + (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel, + IS_CHAN_2GHZ(chan))) { + matchIndex = i; + break; + } else + if ((freq < + ath9k_hw_fbin2freq(powInfo[i].bChannel, + IS_CHAN_2GHZ(chan))) && + (freq > ath9k_hw_fbin2freq + (powInfo[i - 1].bChannel, + IS_CHAN_2GHZ(chan)))) { + lowIndex = i - 1; + break; + } + } + if ((matchIndex == -1) && (lowIndex == -1)) + matchIndex = i - 1; + } + + if (matchIndex != -1) { + *pNewPower = powInfo[matchIndex]; + } else { + clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, + IS_CHAN_2GHZ(chan)); + chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, + IS_CHAN_2GHZ(chan)); + + for (i = 0; i < numRates; i++) { + pNewPower->tPow2x[i] = + (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, ¢ers); + + 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, ¢ers); + + 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, ¢ers); + + 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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/hw.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/hw.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 +#include +#include +#include +#include +#include +#include + +#include "ath9k.h" +#include "core.h" +#include "hw.h" +#include "reg.h" +#include "phy.h" +#include "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, ¢ers); + coef_scaled = clockMhzScaled / centers.synth_center; + + ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, + &ds_coef_exp); + + REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_MAN, ds_coef_man); + REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); + + coef_scaled = (9 * coef_scaled) / 10; + + ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, + &ds_coef_exp); + + REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_MAN, ds_coef_man); + REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); +} + +static 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, ¢ers); + 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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/hw.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/hw.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _HW_H +#define _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 /* _HW_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/initvals.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/initvals.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _INITVALS_H +#define _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 /* _INITVALS_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/mac.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/mac.c Tue Jun 23 01:08:49 2009 +0800 @@ -0,0 +1,1106 @@ +/* + * 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 +#include "core.h" +#include "hw.h" +#include "reg.h" +#include "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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/phy.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/phy.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 "core.h" +#include "hw.h" +#include "reg.h" +#include "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, ¢ers); + 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, ¢ers); + 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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/phy.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/phy.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _PHY_H +#define _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 /* _PHY_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/rc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/rc.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 +#include +#include + +#include "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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/rc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/rc.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _RC_H +#define _RC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "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 /* _RC_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/recv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/recv.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 + +#include "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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/reg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/reg.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _REG_H +#define _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 /* _REG_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/regd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/regd.c Tue Jun 23 01:08:49 2009 +0800 @@ -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 "core.h" +#include "hw.h" +#include "regd.h" +#include "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, ®Domains[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 = ®DomainPairs[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 = ®Dmn5GhzFreq[0]; + ctl = rd->conformanceTestLimit; + break; + case ATH9K_MODE_11B: + rd = &rd2GHz; + channelBM = rd->chan11b; + freqs = ®Dmn2GhzFreq[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 = ®Dmn2Ghz11gFreq[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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/regd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/regd.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _REGD_H +#define _REGD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "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 /* _REGD_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/regd_common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/regd_common.h Tue Jun 23 01:08:49 2009 +0800 @@ -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 _REGD_COMMON_H +#define _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 /* _REGD_COMMON_H */ diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/common/io/arn/xmit.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/arn/xmit.c Tue Jun 23 01:08:49 2009 +0800 @@ -0,0 +1,1018 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "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) + +#define MULTIRATE_RETRY 0 + +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<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<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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/intel/Makefile.intel.shared --- a/usr/src/uts/intel/Makefile.intel.shared Mon Jun 22 08:25:32 2009 -0700 +++ b/usr/src/uts/intel/Makefile.intel.shared Tue Jun 23 01:08:49 2009 +0800 @@ -190,6 +190,7 @@ DRV_KMODS += agpgart DRV_KMODS += srn DRV_KMODS += agptarget +DRV_KMODS += arn DRV_KMODS += arp DRV_KMODS += asy DRV_KMODS += ata diff -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/intel/arn/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/intel/arn/Makefile Tue Jun 23 01:08:49 2009 +0800 @@ -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 -r 4aa6e446614d -r 7e332a7c18f5 usr/src/uts/intel/os/minor_perm --- a/usr/src/uts/intel/os/minor_perm Mon Jun 22 08:25:32 2009 -0700 +++ b/usr/src/uts/intel/os/minor_perm Tue Jun 23 01:08:49 2009 +0800 @@ -128,6 +128,7 @@ 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 @@ -159,6 +160,7 @@ 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