diff options
author | sam <sam@FreeBSD.org> | 2009-01-15 23:38:21 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2009-01-15 23:38:21 +0000 |
commit | 5acbdb14cf274bf22b8cf5c4f886b64ad77f831a (patch) | |
tree | b8bcce98acafa5a83ad4aa4a3114b49c46b41567 /tools/tools | |
parent | 7fc852ff0ae1d283a6bc38a0ca40c0c629ac1a88 (diff) | |
download | FreeBSD-src-5acbdb14cf274bf22b8cf5c4f886b64ad77f831a.zip FreeBSD-src-5acbdb14cf274bf22b8cf5c4f886b64ad77f831a.tar.gz |
add athrd tool that dumps ath hal regulatory info; note this is soon to
obsolete but commit now so it's available for anyone that's interested
Diffstat (limited to 'tools/tools')
-rw-r--r-- | tools/tools/ath/Makefile | 2 | ||||
-rw-r--r-- | tools/tools/ath/Makefile.inc | 7 | ||||
-rw-r--r-- | tools/tools/ath/athrd/Makefile | 21 | ||||
-rw-r--r-- | tools/tools/ath/athrd/athrd.1 | 176 | ||||
-rw-r--r-- | tools/tools/ath/athrd/athrd.c | 1887 | ||||
-rwxr-xr-x | tools/tools/ath/athrd/run.sh | 17 |
6 files changed, 2106 insertions, 4 deletions
diff --git a/tools/tools/ath/Makefile b/tools/tools/ath/Makefile index 16a87ae..ed421bc 100644 --- a/tools/tools/ath/Makefile +++ b/tools/tools/ath/Makefile @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= athdebug athkey athprom athregs athstats +SUBDIR= athdebug athkey athprom athrd athregs athstats .include <bsd.subdir.mk> diff --git a/tools/tools/ath/Makefile.inc b/tools/tools/ath/Makefile.inc index 68ea6a9..81f0a80 100644 --- a/tools/tools/ath/Makefile.inc +++ b/tools/tools/ath/Makefile.inc @@ -6,6 +6,7 @@ NO_MAN= ATH_DEFAULT= ath0 CFLAGS+=-DATH_DEFAULT='"${ATH_DEFAULT}"' -CFLAGS+=-I../common -CFLAGS+=-I../../../../sys/dev/ath -CFLAGS+=-I../../../../sys/dev/ath/ath_hal +CFLAGS+=-I${.CURDIR} +CFLAGS+=-I${.CURDIR}/../common +CFLAGS+=-I${.CURDIR}/../../../../sys/dev/ath +CFLAGS+=-I${.CURDIR}/../../../../sys/dev/ath/ath_hal diff --git a/tools/tools/ath/athrd/Makefile b/tools/tools/ath/athrd/Makefile new file mode 100644 index 0000000..352d712 --- /dev/null +++ b/tools/tools/ath/athrd/Makefile @@ -0,0 +1,21 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../sys/dev/ath/ath_hal + +PROG= athrd + +SRCS= athrd.c ah_regdomain.c opt_ah.h + +CLEANFILES+= opt_ah.h + +CFLAGS+= -fno-inline + +.include <../Makefile.inc> + +MAN= athrd.1 + +opt_ah.h: + echo "#define AH_DEBUG 1" > opt_ah.h + echo "#define AH_DEBUG_COUNTRY 1" >> opt_ah.h + +.include <bsd.prog.mk> diff --git a/tools/tools/ath/athrd/athrd.1 b/tools/tools/ath/athrd/athrd.1 new file mode 100644 index 0000000..8edc79e --- /dev/null +++ b/tools/tools/ath/athrd/athrd.1 @@ -0,0 +1,176 @@ +.\"- +.\" Copyright (c) 2002-2009 Sam Leffler, Errno Consulting +.\" All rights reserved. +.\"" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer, +.\" without modification. +.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer +.\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any +.\" redistribution must be conditioned upon including a substantially +.\" similar Disclaimer requirement for further binary redistribution. +.\" +.\" NO WARRANTY +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY +.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +.\" THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, +.\" OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +.\" THE POSSIBILITY OF SUCH DAMAGES. +.\" +.\" $FreeBSD$ +.\"/ +.Dd January 15, 2009 +.Dt ATHRD 1 +.Os +.Sh NAME +.Nm athrd +.Nd list channels and transmit power for a country/regulatory domain +.Sh SYNOPSIS +.Nm +.Op Fl aioedlpcfr4ABGT +.Op Fl m Ar mode +.Bk +.Op Ar country +.Ek +.Sh DESCRIPTION +.Nm +displays the list of frequencies and the associated maximum transmit +power permitted within a regulatory domain and/or country. +.Pp +If no command line options are given, a default country (\c +.Ql US ) +is used. +Country and regulatory names are case insensitive. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl a +By default +.Nm +will display B channels only if they are not also marked as available for +use as G channels and similary for A and T channels. +With this option +.Nm +will list all channels. +.It Fl i +Calculate channels based on indoor use. +.It Fl o +Calculate channels based on outdoor use (default). +.It Fl e +Calculate channels not assuming extended channel mode. +.It Fl d +Enabling debugging in the HAL code that calculates the available channels +and transmit power values. +.It Fl l +Provide a list of all known country and regulatory domain names. +.It Fl m Ar mode +Calculate channels and transmit power for operation in +.Ql mode ; +one of +.Ql station , +.Ql ibss , +.Ql monitor , +and +.Ql ap +(or the first two letters). +.It Fl p +Mark passive scan channels with lower case letters and active +scan channels with upper case letters. +.It Fl r +Mark channels that require DFS with a +.Ql * . +.It Fl 4 +Mark channels that have a 4ms packet limit with a +.Ql 4 . +.It Fl c +Display IEEE channel numbers instead of frequencies. +.It Fl f +Display frequencies (default). +.It Fl A +Display only 11A channels. +.It Fl B +Display only 11B channels. +.It Fl G +Display only 11G channels. +.It Fl T +Display only Turbo channels. +.El +.Sh EXAMPLES +The following demonstrates how to list the permissible frequencies +and maximum transport power per channel for use in Spain: +.Pp +.nf +tubby% athrd es +\& +SPAIN (ES, 0x2d4, 724) NULL1_WORLD (0x3, 3) +2412G 14.0 2417G 14.0 2422G 14.0 2427G 17.0 2432G 14.0 2437G 17.0 +2442G 14.0 2447G 17.0 2452G 17.0 2457G 14.0 2462G 17.0 +.fi +.Pp +Each frequency has a suffix that is one of: +.Ql G , +.Ql B , +.Ql A , +or +.Ql T +according to whether the channel is usable with 802.11g, 802.11b, +802.11a, or Atheros Turbo mode. +All channels listed as +.Ql G +are also usable in +.Ql B . +Likewise, all channels listed as +.Ql A +are usable in +.Ql T . +Channels listed as +.Ql B +or +.Ql T +are only usable in those modes. +(Note that when the +.Fl p +option is specified passive scan channels are marked with a lower case +.Ql g , +.Ql b , +.Ql a , +or +.Ql t .) +The transmit power is given in units of dbM. +.Sh DIAGNOSTICS +Various diagnostics about unknown regulatory domains and/or country +codes may be encountered. +Use the +.Fl l +option for a list of valid names. +.Sh SEE ALSO +.Xr ath 4 , +.Xr ath_hal 4 +.Sh STANDARDS +Lots belong here. +.Sh NOTES +.Nm +use the HAL to calculate the set of channels. +The transmit power calculations are done by emulating +how the HAL works. +Because +.Nm +does not +read the actual EEPROM contents from a device this emulation may lag +behind current practice. +.Sh BUGS +The HAL reset logic should be used to calculate the transmit power +for each channel instead of using a separate copy of the code. +The data presented by +.Nm +are the expected values; for compliance testing one must measure the actual +operation of the driver and the HAL. diff --git a/tools/tools/ath/athrd/athrd.c b/tools/tools/ath/athrd/athrd.c new file mode 100644 index 0000000..eaaf861 --- /dev/null +++ b/tools/tools/ath/athrd/athrd.c @@ -0,0 +1,1887 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_eeprom_v3.h" /* XXX */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> + +#define IEEE80211_CHAN_MAX 255 +#define IEEE80211_REGCLASSIDS_MAX 10 + +int ath_hal_debug = 0; +HAL_CTRY_CODE cc = CTRY_DEFAULT; +HAL_REG_DOMAIN rd = 169; /* FCC */ +HAL_BOOL outdoor = AH_TRUE; +HAL_BOOL Amode = 1; +HAL_BOOL Bmode = 1; +HAL_BOOL Gmode = 1; +HAL_BOOL HT20mode = 1; +HAL_BOOL HT40mode = 1; +HAL_BOOL turbo5Disable = AH_FALSE; +HAL_BOOL turbo2Disable = AH_FALSE; + +u_int16_t _numCtls = 8; +u_int16_t _ctl[32] = + { 0x10, 0x13, 0x40, 0x30, 0x11, 0x31, 0x12, 0x32 }; +RD_EDGES_POWER _rdEdgesPower[NUM_EDGES*NUM_CTLS] = { + { 5180, 28, 0 }, /* 0x10 */ + { 5240, 60, 0 }, + { 5260, 36, 0 }, + { 5320, 27, 0 }, + { 5745, 36, 0 }, + { 5765, 36, 0 }, + { 5805, 36, 0 }, + { 5825, 36, 0 }, + + { 5210, 28, 0 }, /* 0x13 */ + { 5250, 28, 0 }, + { 5290, 30, 0 }, + { 5760, 36, 0 }, + { 5800, 36, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + + { 5170, 60, 0 }, /* 0x40 */ + { 5230, 60, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + + { 5180, 33, 0 }, /* 0x30 */ + { 5320, 33, 0 }, + { 5500, 34, 0 }, + { 5700, 34, 0 }, + { 5745, 35, 0 }, + { 5765, 35, 0 }, + { 5785, 35, 0 }, + { 5825, 35, 0 }, + + { 2412, 36, 0 }, /* 0x11 */ + { 2417, 36, 0 }, + { 2422, 36, 0 }, + { 2432, 36, 0 }, + { 2442, 36, 0 }, + { 2457, 36, 0 }, + { 2467, 36, 0 }, + { 2472, 36, 0 }, + + { 2412, 36, 0 }, /* 0x31 */ + { 2417, 36, 0 }, + { 2422, 36, 0 }, + { 2432, 36, 0 }, + { 2442, 36, 0 }, + { 2457, 36, 0 }, + { 2467, 36, 0 }, + { 2472, 36, 0 }, + + { 2412, 36, 0 }, /* 0x12 */ + { 2417, 36, 0 }, + { 2422, 36, 0 }, + { 2432, 36, 0 }, + { 2442, 36, 0 }, + { 2457, 36, 0 }, + { 2467, 36, 0 }, + { 2472, 36, 0 }, + + { 2412, 28, 0 }, /* 0x32 */ + { 2417, 28, 0 }, + { 2422, 28, 0 }, + { 2432, 28, 0 }, + { 2442, 28, 0 }, + { 2457, 28, 0 }, + { 2467, 28, 0 }, + { 2472, 28, 0 }, +}; + +u_int16_t turbo2WMaxPower5 = 32; +u_int16_t turbo2WMaxPower2; +int8_t antennaGainMax[2] = { 0, 0 }; /* XXX */ +int eeversion = AR_EEPROM_VER3_1; +TRGT_POWER_ALL_MODES tpow = { + 8, { + { 22, 24, 28, 32, 5180 }, + { 22, 24, 28, 32, 5200 }, + { 22, 24, 28, 32, 5320 }, + { 26, 30, 34, 34, 5500 }, + { 26, 30, 34, 34, 5700 }, + { 20, 30, 34, 36, 5745 }, + { 20, 30, 34, 36, 5825 }, + { 20, 30, 34, 36, 5850 }, + }, + 2, { + { 23, 27, 31, 34, 2412 }, + { 23, 27, 31, 34, 2447 }, + }, + 2, { + { 36, 36, 36, 36, 2412 }, + { 36, 36, 36, 36, 2484 }, + } +}; +#define numTargetPwr_11a tpow.numTargetPwr_11a +#define trgtPwr_11a tpow.trgtPwr_11a +#define numTargetPwr_11g tpow.numTargetPwr_11g +#define trgtPwr_11g tpow.trgtPwr_11g +#define numTargetPwr_11b tpow.numTargetPwr_11b +#define trgtPwr_11b tpow.trgtPwr_11b + +static HAL_BOOL +getChannelEdges(struct ath_hal *ah, u_int16_t flags, u_int16_t *low, u_int16_t *high) +{ + struct ath_hal_private *ahp = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahp->ah_caps; + + if (flags & CHANNEL_5GHZ) { + *low = pCap->halLow5GhzChan; + *high = pCap->halHigh5GhzChan; + return AH_TRUE; + } + if (flags & CHANNEL_2GHZ) { + *low = pCap->halLow2GhzChan; + *high = pCap->halHigh2GhzChan; + return AH_TRUE; + } + return AH_FALSE; +} + +static u_int +getWirelessModes(struct ath_hal *ah) +{ + u_int mode = 0; + + if (Amode) { + mode = HAL_MODE_11A; + if (!turbo5Disable) + mode |= HAL_MODE_TURBO; + } + if (Bmode) + mode |= HAL_MODE_11B; + if (Gmode) { + mode |= HAL_MODE_11G; + if (!turbo2Disable) + mode |= HAL_MODE_108G; + } + if (HT20mode) + mode |= HAL_MODE_11NG_HT20|HAL_MODE_11NA_HT20; + if (HT40mode) + mode |= HAL_MODE_11NG_HT40PLUS|HAL_MODE_11NA_HT40PLUS + | HAL_MODE_11NG_HT40MINUS|HAL_MODE_11NA_HT40MINUS + ; + return mode; +} + +/* + * Country/Region Codes from MS WINNLS.H + * Numbering from ISO 3166 + */ +enum CountryCode { + CTRY_ALBANIA = 8, /* Albania */ + CTRY_ALGERIA = 12, /* Algeria */ + CTRY_ARGENTINA = 32, /* Argentina */ + CTRY_ARMENIA = 51, /* Armenia */ + CTRY_AUSTRALIA = 36, /* Australia */ + CTRY_AUSTRIA = 40, /* Austria */ + CTRY_AZERBAIJAN = 31, /* Azerbaijan */ + CTRY_BAHRAIN = 48, /* Bahrain */ + CTRY_BELARUS = 112, /* Belarus */ + CTRY_BELGIUM = 56, /* Belgium */ + CTRY_BELIZE = 84, /* Belize */ + CTRY_BOLIVIA = 68, /* Bolivia */ + CTRY_BRAZIL = 76, /* Brazil */ + CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */ + CTRY_BULGARIA = 100, /* Bulgaria */ + CTRY_CANADA = 124, /* Canada */ + CTRY_CHILE = 152, /* Chile */ + CTRY_CHINA = 156, /* People's Republic of China */ + CTRY_COLOMBIA = 170, /* Colombia */ + CTRY_COSTA_RICA = 188, /* Costa Rica */ + CTRY_CROATIA = 191, /* Croatia */ + CTRY_CYPRUS = 196, + CTRY_CZECH = 203, /* Czech Republic */ + CTRY_DENMARK = 208, /* Denmark */ + CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */ + CTRY_ECUADOR = 218, /* Ecuador */ + CTRY_EGYPT = 818, /* Egypt */ + CTRY_EL_SALVADOR = 222, /* El Salvador */ + CTRY_ESTONIA = 233, /* Estonia */ + CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */ + CTRY_FINLAND = 246, /* Finland */ + CTRY_FRANCE = 250, /* France */ + CTRY_FRANCE2 = 255, /* France2 */ + CTRY_GEORGIA = 268, /* Georgia */ + CTRY_GERMANY = 276, /* Germany */ + CTRY_GREECE = 300, /* Greece */ + CTRY_GSM = 843, /* 900MHz/GSM */ + CTRY_GUATEMALA = 320, /* Guatemala */ + CTRY_HONDURAS = 340, /* Honduras */ + CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */ + CTRY_HUNGARY = 348, /* Hungary */ + CTRY_ICELAND = 352, /* Iceland */ + CTRY_INDIA = 356, /* India */ + CTRY_INDONESIA = 360, /* Indonesia */ + CTRY_IRAN = 364, /* Iran */ + CTRY_IRAQ = 368, /* Iraq */ + CTRY_IRELAND = 372, /* Ireland */ + CTRY_ISRAEL = 376, /* Israel */ + CTRY_ITALY = 380, /* Italy */ + CTRY_JAMAICA = 388, /* Jamaica */ + CTRY_JAPAN = 392, /* Japan */ + CTRY_JAPAN1 = 393, /* Japan (JP1) */ + CTRY_JAPAN2 = 394, /* Japan (JP0) */ + CTRY_JAPAN3 = 395, /* Japan (JP1-1) */ + CTRY_JAPAN4 = 396, /* Japan (JE1) */ + CTRY_JAPAN5 = 397, /* Japan (JE2) */ + CTRY_JAPAN6 = 399, /* Japan (JP6) */ + + CTRY_JAPAN7 = 4007, /* Japan (J7) */ + CTRY_JAPAN8 = 4008, /* Japan (J8) */ + CTRY_JAPAN9 = 4009, /* Japan (J9) */ + + CTRY_JAPAN10 = 4010, /* Japan (J10) */ + CTRY_JAPAN11 = 4011, /* Japan (J11) */ + CTRY_JAPAN12 = 4012, /* Japan (J12) */ + + CTRY_JAPAN13 = 4013, /* Japan (J13) */ + CTRY_JAPAN14 = 4014, /* Japan (J14) */ + CTRY_JAPAN15 = 4015, /* Japan (J15) */ + + CTRY_JAPAN16 = 4016, /* Japan (J16) */ + CTRY_JAPAN17 = 4017, /* Japan (J17) */ + CTRY_JAPAN18 = 4018, /* Japan (J18) */ + + CTRY_JAPAN19 = 4019, /* Japan (J19) */ + CTRY_JAPAN20 = 4020, /* Japan (J20) */ + CTRY_JAPAN21 = 4021, /* Japan (J21) */ + + CTRY_JAPAN22 = 4022, /* Japan (J22) */ + CTRY_JAPAN23 = 4023, /* Japan (J23) */ + CTRY_JAPAN24 = 4024, /* Japan (J24) */ + + CTRY_JORDAN = 400, /* Jordan */ + CTRY_KAZAKHSTAN = 398, /* Kazakhstan */ + CTRY_KENYA = 404, /* Kenya */ + CTRY_KOREA_NORTH = 408, /* North Korea */ + CTRY_KOREA_ROC = 410, /* South Korea */ + CTRY_KOREA_ROC2 = 411, /* South Korea */ + CTRY_KOREA_ROC3 = 412, /* South Korea */ + CTRY_KUWAIT = 414, /* Kuwait */ + CTRY_LATVIA = 428, /* Latvia */ + CTRY_LEBANON = 422, /* Lebanon */ + CTRY_LIBYA = 434, /* Libya */ + CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */ + CTRY_LITHUANIA = 440, /* Lithuania */ + CTRY_LUXEMBOURG = 442, /* Luxembourg */ + CTRY_MACAU = 446, /* Macau */ + CTRY_MACEDONIA = 807, /* the Former Yugoslav Republic of Macedonia */ + CTRY_MALAYSIA = 458, /* Malaysia */ + CTRY_MALTA = 470, /* Malta */ + CTRY_MEXICO = 484, /* Mexico */ + CTRY_MONACO = 492, /* Principality of Monaco */ + CTRY_MOROCCO = 504, /* Morocco */ + CTRY_NETHERLANDS = 528, /* Netherlands */ + CTRY_NEW_ZEALAND = 554, /* New Zealand */ + CTRY_NICARAGUA = 558, /* Nicaragua */ + CTRY_NORWAY = 578, /* Norway */ + CTRY_OMAN = 512, /* Oman */ + CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */ + CTRY_PANAMA = 591, /* Panama */ + CTRY_PARAGUAY = 600, /* Paraguay */ + CTRY_PERU = 604, /* Peru */ + CTRY_PHILIPPINES = 608, /* Republic of the Philippines */ + CTRY_POLAND = 616, /* Poland */ + CTRY_PORTUGAL = 620, /* Portugal */ + CTRY_PUERTO_RICO = 630, /* Puerto Rico */ + CTRY_QATAR = 634, /* Qatar */ + CTRY_ROMANIA = 642, /* Romania */ + CTRY_RUSSIA = 643, /* Russia */ + CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */ + CTRY_SINGAPORE = 702, /* Singapore */ + CTRY_SLOVAKIA = 703, /* Slovak Republic */ + CTRY_SLOVENIA = 705, /* Slovenia */ + CTRY_SOUTH_AFRICA = 710, /* South Africa */ + CTRY_SPAIN = 724, /* Spain */ + CTRY_SWEDEN = 752, /* Sweden */ + CTRY_SWITZERLAND = 756, /* Switzerland */ + CTRY_SYRIA = 760, /* Syria */ + CTRY_TAIWAN = 158, /* Taiwan */ + CTRY_THAILAND = 764, /* Thailand */ + CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */ + CTRY_TUNISIA = 788, /* Tunisia */ + CTRY_TURKEY = 792, /* Turkey */ + CTRY_UAE = 784, /* U.A.E. */ + CTRY_UKRAINE = 804, /* Ukraine */ + CTRY_UNITED_KINGDOM = 826, /* United Kingdom */ + CTRY_UNITED_STATES = 840, /* United States */ + CTRY_UNITED_STATES_FCC49 = 842, /* United States (Public Safety)*/ + CTRY_URUGUAY = 858, /* Uruguay */ + CTRY_UZBEKISTAN = 860, /* Uzbekistan */ + CTRY_VENEZUELA = 862, /* Venezuela */ + CTRY_VIET_NAM = 704, /* Viet Nam */ + CTRY_YEMEN = 887, /* Yemen */ + CTRY_ZIMBABWE = 716 /* Zimbabwe */ +}; + + +/* Enumerated Regulatory Domain Information 8 bit values indicate that + * the regdomain is really a pair of unitary regdomains. 12 bit values + * are the real unitary regdomains and are the only ones which have the + * frequency bitmasks and flags set. + */ + +enum EnumRd { + /* + * The following regulatory domain definitions are + * found in the EEPROM. Each regulatory domain + * can operate in either a 5GHz or 2.4GHz wireless mode or + * both 5GHz and 2.4GHz wireless modes. + * In general, the value holds no special + * meaning and is used to decode into either specific + * 2.4GHz or 5GHz wireless mode for that particular + * regulatory domain. + */ + NO_ENUMRD = 0x00, + NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ + NULL1_ETSIB = 0x07, /* Israel */ + NULL1_ETSIC = 0x08, + NULL1_GSM = 0x09, /* GSM-only operation */ + FCC1_FCCA = 0x10, /* USA */ + FCC1_WORLD = 0x11, /* Hong Kong */ + FCC4_FCCA = 0x12, /* USA - Public Safety */ + + FCC2_FCCA = 0x20, /* Canada */ + FCC2_WORLD = 0x21, /* Australia & HK */ + FCC2_ETSIC = 0x22, + FRANCE_RES = 0x31, /* Legacy France for OEM */ + FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ + FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ + + ETSI1_WORLD = 0x37, + ETSI3_ETSIA = 0x32, /* France (optional) */ + ETSI2_WORLD = 0x35, /* Hungary & others */ + ETSI3_WORLD = 0x36, /* France & others */ + ETSI4_WORLD = 0x30, + ETSI4_ETSIC = 0x38, + ETSI5_WORLD = 0x39, + ETSI6_WORLD = 0x34, /* Bulgaria */ + ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ + + MKK1_MKKA = 0x40, /* Japan (JP1) */ + MKK1_MKKB = 0x41, /* Japan (JP0) */ + APL4_WORLD = 0x42, /* Singapore */ + MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ + APL_RESERVED = 0x44, /* Reserved (Do not used) */ + APL2_WORLD = 0x45, /* Korea */ + APL2_APLC = 0x46, + APL3_WORLD = 0x47, + MKK1_FCCA = 0x48, /* Japan (JP1-1) */ + APL2_APLD = 0x49, /* Korea with 2.3G channels */ + MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ + MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ + MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ + + APL3_FCCA = 0x50, + APL1_WORLD = 0x52, /* Latin America */ + APL1_FCCA = 0x53, + APL1_APLA = 0x54, + APL1_ETSIC = 0x55, + APL2_ETSIC = 0x56, /* Venezuela */ + APL5_WORLD = 0x58, /* Chile */ + APL6_WORLD = 0x5B, /* Singapore */ + APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ + APL8_WORLD = 0x5D, /* Malaysia 5GHz */ + APL9_WORLD = 0x5E, /* Korea 5GHz */ + + /* + * World mode SKUs + */ + WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ + WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ + WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ + WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ + WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ + WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ + + WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ + WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ + EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ + + WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ + WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ + + MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ + MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ + MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ + + MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ + MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ + MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ + + MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ + MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ + MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ + + MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ + MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ + MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ + + MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ + MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ + MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ + + MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ + MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ + MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ + + /* Following definitions are used only by s/w to map old + * Japan SKUs. + */ + MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ + MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ + MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ + MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ + MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ + MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ + MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ + MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ + + /* + * Regulator domains ending in a number (e.g. APL1, + * MK1, ETSI4, etc) apply to 5GHz channel and power + * information. Regulator domains ending in a letter + * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and + * power information. + */ + APL1 = 0x0150, /* LAT & Asia */ + APL2 = 0x0250, /* LAT & Asia */ + APL3 = 0x0350, /* Taiwan */ + APL4 = 0x0450, /* Jordan */ + APL5 = 0x0550, /* Chile */ + APL6 = 0x0650, /* Singapore */ + APL8 = 0x0850, /* Malaysia */ + APL9 = 0x0950, /* Korea (South) ROC 3 */ + + ETSI1 = 0x0130, /* Europe & others */ + ETSI2 = 0x0230, /* Europe & others */ + ETSI3 = 0x0330, /* Europe & others */ + ETSI4 = 0x0430, /* Europe & others */ + ETSI5 = 0x0530, /* Europe & others */ + ETSI6 = 0x0630, /* Europe & others */ + ETSIA = 0x0A30, /* France */ + ETSIB = 0x0B30, /* Israel */ + ETSIC = 0x0C30, /* Latin America */ + + FCC1 = 0x0110, /* US & others */ + FCC2 = 0x0120, /* Canada, Australia & New Zealand */ + FCC3 = 0x0160, /* US w/new middle band & DFS */ + FCC4 = 0x0165, /* US Public Safety */ + FCCA = 0x0A10, + + APLD = 0x0D50, /* South Korea */ + + MKK1 = 0x0140, /* Japan (UNI-1 odd)*/ + MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ + MKK3 = 0x0340, /* Japan (UNI-1 even) */ + MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ + MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ + MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ + MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ + MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ + MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ + MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKKA = 0x0A40, /* Japan */ + MKKC = 0x0A50, + + NULL1 = 0x0198, + WORLD = 0x0199, + GSM = 0x019a, + DEBUG_REG_DMN = 0x01ff, +}; +#define DEF_REGDMN FCC1_FCCA + +static struct { + const char *name; + HAL_REG_DOMAIN rd; +} domains[] = { +#define D(_x) { #_x, _x } + D(NO_ENUMRD), + D(NULL1_WORLD), /* For 11b-only countries (no 11a allowed) */ + D(NULL1_ETSIB), /* Israel */ + D(NULL1_ETSIC), + D(NULL1_GSM), /* GSM-only operation */ + D(FCC1_FCCA), /* USA */ + D(FCC1_WORLD), /* Hong Kong */ + D(FCC4_FCCA), /* USA - Public Safety */ + + D(FCC2_FCCA), /* Canada */ + D(FCC2_WORLD), /* Australia & HK */ + D(FCC2_ETSIC), + D(FRANCE_RES), /* Legacy France for OEM */ + D(FCC3_FCCA), + D(FCC3_WORLD), + + D(ETSI1_WORLD), + D(ETSI3_ETSIA), /* France (optional) */ + D(ETSI2_WORLD), /* Hungary & others */ + D(ETSI3_WORLD), /* France & others */ + D(ETSI4_WORLD), + D(ETSI4_ETSIC), + D(ETSI5_WORLD), + D(ETSI6_WORLD), /* Bulgaria */ + D(ETSI_RESERVED), /* Reserved (Do not used) */ + + D(MKK1_MKKA), /* Japan (JP1) */ + D(MKK1_MKKB), /* Japan (JP0) */ + D(APL4_WORLD), /* Singapore */ + D(MKK2_MKKA), /* Japan with 4.9G channels */ + D(APL_RESERVED), /* Reserved (Do not used) */ + D(APL2_WORLD), /* Korea */ + D(APL2_APLC), + D(APL3_WORLD), + D(MKK1_FCCA), /* Japan (JP1-1) */ + D(APL2_APLD), /* Korea with 2.3G channels */ + D(MKK1_MKKA1), /* Japan (JE1) */ + D(MKK1_MKKA2), /* Japan (JE2) */ + D(MKK1_MKKC), + + D(APL3_FCCA), + D(APL1_WORLD), /* Latin America */ + D(APL1_FCCA), + D(APL1_APLA), + D(APL1_ETSIC), + D(APL2_ETSIC), /* Venezuela */ + D(APL5_WORLD), /* Chile */ + D(APL6_WORLD), /* Singapore */ + D(APL7_FCCA), /* Taiwan 5.47 Band */ + D(APL8_WORLD), /* Malaysia 5GHz */ + D(APL9_WORLD), /* Korea 5GHz */ + + D(WOR0_WORLD), /* World0 (WO0 SKU) */ + D(WOR1_WORLD), /* World1 (WO1 SKU) */ + D(WOR2_WORLD), /* World2 (WO2 SKU) */ + D(WOR3_WORLD), /* World3 (WO3 SKU) */ + D(WOR4_WORLD), /* World4 (WO4 SKU) */ + D(WOR5_ETSIC), /* World5 (WO5 SKU) */ + + D(WOR01_WORLD), /* World0-1 (WW0-1 SKU) */ + D(WOR02_WORLD), /* World0-2 (WW0-2 SKU) */ + D(EU1_WORLD), + + D(WOR9_WORLD), /* World9 (WO9 SKU) */ + D(WORA_WORLD), /* WorldA (WOA SKU) */ + + D(MKK3_MKKB), /* Japan UNI-1 even + MKKB */ + D(MKK3_MKKA2), /* Japan UNI-1 even + MKKA2 */ + D(MKK3_MKKC), /* Japan UNI-1 even + MKKC */ + + D(MKK4_MKKB), /* Japan UNI-1 even + UNI-2 + MKKB */ + D(MKK4_MKKA2), /* Japan UNI-1 even + UNI-2 + MKKA2 */ + D(MKK4_MKKC), /* Japan UNI-1 even + UNI-2 + MKKC */ + + D(MKK5_MKKB), /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ + D(MKK5_MKKA2), /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ + D(MKK5_MKKC), /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ + + D(MKK6_MKKB), /* Japan UNI-1 even + UNI-1 odd MKKB */ + D(MKK6_MKKA2), /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ + D(MKK6_MKKC), /* Japan UNI-1 even + UNI-1 odd + MKKC */ + + D(MKK7_MKKB), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ + D(MKK7_MKKA2), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ + D(MKK7_MKKC), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ + + D(MKK8_MKKB), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ + D(MKK8_MKKA2), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ + D(MKK8_MKKC), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ + + D(MKK3_MKKA), /* Japan UNI-1 even + MKKA */ + D(MKK3_MKKA1), /* Japan UNI-1 even + MKKA1 */ + D(MKK3_FCCA), /* Japan UNI-1 even + FCCA */ + D(MKK4_MKKA), /* Japan UNI-1 even + UNI-2 + MKKA */ + D(MKK4_MKKA1), /* Japan UNI-1 even + UNI-2 + MKKA1 */ + D(MKK4_FCCA), /* Japan UNI-1 even + UNI-2 + FCCA */ + D(MKK9_MKKA), /* Japan UNI-1 even + 4.9GHz */ + D(MKK10_MKKA), /* Japan UNI-1 even + UNI-2 + 4.9GHz */ + + D(APL1), /* LAT & Asia */ + D(APL2), /* LAT & Asia */ + D(APL3), /* Taiwan */ + D(APL4), /* Jordan */ + D(APL5), /* Chile */ + D(APL6), /* Singapore */ + D(APL8), /* Malaysia */ + D(APL9), /* Korea (South) ROC 3 */ + + D(ETSI1), /* Europe & others */ + D(ETSI2), /* Europe & others */ + D(ETSI3), /* Europe & others */ + D(ETSI4), /* Europe & others */ + D(ETSI5), /* Europe & others */ + D(ETSI6), /* Europe & others */ + D(ETSIA), /* France */ + D(ETSIB), /* Israel */ + D(ETSIC), /* Latin America */ + + D(FCC1), /* US & others */ + D(FCC2), + D(FCC3), /* US w/new middle band & DFS */ + D(FCC4), /* US Public Safety */ + D(FCCA), + + D(APLD), /* South Korea */ + + D(MKK1), /* Japan (UNI-1 odd)*/ + D(MKK2), /* Japan (4.9 GHz + UNI-1 odd) */ + D(MKK3), /* Japan (UNI-1 even) */ + D(MKK4), /* Japan (UNI-1 even + UNI-2) */ + D(MKK5), /* Japan (UNI-1 even + UNI-2 + mid-band) */ + D(MKK6), /* Japan (UNI-1 odd + UNI-1 even) */ + D(MKK7), /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ + D(MKK8), /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ + D(MKK9), /* Japan (UNI-1 even + 4.9 GHZ) */ + D(MKK10), /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + D(MKKA), /* Japan */ + D(MKKC), + + D(NULL1), + D(WORLD), + D(GSM), + D(DEBUG_REG_DMN), +#undef D +}; + +static HAL_BOOL +rdlookup(const char *name, HAL_REG_DOMAIN *rd) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + for (i = 0; i < N(domains); i++) + if (strcasecmp(domains[i].name, name) == 0) { + *rd = domains[i].rd; + return AH_TRUE; + } + return AH_FALSE; +#undef N +} + +static const char * +getrdname(HAL_REG_DOMAIN rd) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + for (i = 0; i < N(domains); i++) + if (domains[i].rd == rd) + return domains[i].name; + return NULL; +#undef N +} + +static void +rdlist() +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + printf("\nRegulatory domains:\n\n"); + for (i = 0; i < N(domains); i++) + printf("%-15s%s", domains[i].name, + ((i+1)%5) == 0 ? "\n" : ""); + printf("\n"); +#undef N +} + +typedef struct { + HAL_CTRY_CODE countryCode; + HAL_REG_DOMAIN regDmnEnum; + const char* isoName; + const char* name; + HAL_BOOL allow11g; + HAL_BOOL allow11aTurbo; + HAL_BOOL allow11gTurbo; + u_int16_t outdoorChanStart; +} COUNTRY_CODE_TO_ENUM_RD; + +#define YES AH_TRUE +#define NO AH_FALSE +/* Index into table to avoid DEBUG and NO COUNTRY SET entries */ +#define CTRY_ONLY_INDEX 2 +/* + * Country Code Table to Enumerated RD + */ + +static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { + {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, 7000 }, + {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES, 7000 }, + {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, 7000 }, + {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, 7000 }, + {CTRY_ARGENTINA, APL3_WORLD, "AR", "ARGENTINA", NO, NO, NO, 7000 }, + {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, 7000 }, + {CTRY_AUSTRALIA, FCC2_WORLD, "AU", "AUSTRALIA", YES, YES, YES, 7000 }, + {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA", YES, NO, YES, 7000 }, + {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES, 7000 }, + {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, 7000 }, + {CTRY_BELARUS, NULL1_WORLD, "BY", "BELARUS", YES, NO, YES, 7000 }, + {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, 7000 }, + {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE", YES, YES, YES, 7000 }, + {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLVIA", YES, YES, YES, 7000 }, + {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL", YES, NO, NO, 7000 }, + {CTRY_BRUNEI_DARUSSALAM,APL1_WORLD,"BN", "BRUNEI DARUSSALAM", YES, YES, YES, 7000 }, + {CTRY_BULGARIA, ETSI6_WORLD, "BG", "BULGARIA", YES, NO, YES, 7000 }, + {CTRY_CANADA, FCC2_FCCA, "CA", "CANADA", YES, YES, YES, 7000 }, + {CTRY_CHILE, APL6_WORLD, "CL", "CHILE", YES, YES, YES, 7000 }, + {CTRY_CHINA, APL1_WORLD, "CN", "CHINA", YES, YES, YES, 7000 }, + {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA", YES, NO, YES, 7000 }, + {CTRY_COSTA_RICA, NULL1_WORLD, "CR", "COSTA RICA", YES, NO, YES, 7000 }, + {CTRY_CROATIA, ETSI3_WORLD, "HR", "CROATIA", YES, NO, YES, 7000 }, + {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS", YES, YES, YES, 7000 }, + {CTRY_CZECH, ETSI3_WORLD, "CZ", "CZECH REPUBLIC", YES, NO, YES, 7000 }, + {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK", YES, NO, YES, 7000 }, + {CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA,"DO", "DOMINICAN REPUBLIC", YES, YES, YES, 7000 }, + {CTRY_ECUADOR, NULL1_WORLD, "EC", "ECUADOR", NO, NO, NO, 7000 }, + {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT", YES, NO, YES, 7000 }, + {CTRY_EL_SALVADOR, NULL1_WORLD, "SV", "EL SALVADOR", YES, NO, YES, 7000 }, + {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA", YES, NO, YES, 7000 }, + {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND", YES, NO, YES, 7000 }, + {CTRY_FRANCE, ETSI3_WORLD, "FR", "FRANCE", YES, NO, YES, 7000 }, + {CTRY_FRANCE2, ETSI3_WORLD, "F2", "FRANCE_RES", YES, NO, YES, 7000 }, + {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA", YES, YES, YES, 7000 }, + {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY", YES, NO, YES, 7000 }, + {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE", YES, NO, YES, 7000 }, + {CTRY_GSM, NULL1_GSM, "GS", "GSM", YES, NO, NO, 7000 }, + {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA", YES, YES, YES, 7000 }, + {CTRY_HONDURAS, NULL1_WORLD, "HN", "HONDURAS", YES, NO, YES, 7000 }, + {CTRY_HONG_KONG, FCC2_WORLD, "HK", "HONG KONG", YES, YES, YES, 7000 }, + {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY", YES, NO, YES, 7000 }, + {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND", YES, NO, YES, 7000 }, + {CTRY_INDIA, APL6_WORLD, "IN", "INDIA", YES, NO, YES, 7000 }, + {CTRY_INDONESIA, APL1_WORLD, "ID", "INDONESIA", YES, NO, YES, 7000 }, + {CTRY_IRAN, APL1_WORLD, "IR", "IRAN", YES, YES, YES, 7000 }, + {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND", YES, NO, YES, 7000 }, + {CTRY_ISRAEL, NULL1_WORLD, "IL", "ISRAEL", YES, NO, YES, 7000 }, + {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY", YES, NO, YES, 7000 }, + {CTRY_JAPAN, MKK1_MKKA, "JP", "JAPAN", YES, NO, NO, 7000 }, + {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1", YES, NO, NO, 7000 }, + {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2", YES, NO, NO, 7000 }, + {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3", YES, NO, NO, 7000 }, + {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4", YES, NO, NO, 7000 }, + {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5", YES, NO, NO, 7000 }, + {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6", YES, NO, NO, 7000 }, + + {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7", YES, NO, NO, 7000 }, + {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8", YES, NO, NO, 7000 }, + {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9", YES, NO, NO, 7000 }, + + {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10", YES, NO, NO, 7000 }, + {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11", YES, NO, NO, 7000 }, + {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12", YES, NO, NO, 7000 }, + + {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13", YES, NO, NO, 7000 }, + {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14", YES, NO, NO, 7000 }, + {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15", YES, NO, NO, 7000 }, + + {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16", YES, NO, NO, 7000 }, + {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17", YES, NO, NO, 7000 }, + {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18", YES, NO, NO, 7000 }, + + {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19", YES, NO, NO, 7000 }, + {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20", YES, NO, NO, 7000 }, + {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21", YES, NO, NO, 7000 }, + + {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22", YES, NO, NO, 7000 }, + {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23", YES, NO, NO, 7000 }, + {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24", YES, NO, NO, 7000 }, + + {CTRY_JORDAN, APL4_WORLD, "JO", "JORDAN", YES, NO, YES, 7000 }, + {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN", YES, NO, YES, 7000 }, + {CTRY_KOREA_NORTH, APL2_WORLD, "KP", "NORTH KOREA", YES, YES, YES, 7000 }, + {CTRY_KOREA_ROC, APL2_WORLD, "KR", "KOREA REPUBLIC", YES, NO, NO, 7000 }, + {CTRY_KOREA_ROC2, APL2_WORLD, "K2", "KOREA REPUBLIC2",YES, NO, NO, 7000 }, + {CTRY_KOREA_ROC3, APL9_WORLD, "K3", "KOREA REPUBLIC3",YES, NO, NO, 7000 }, + {CTRY_KUWAIT, NULL1_WORLD, "KW", "KUWAIT", YES, NO, YES, 7000 }, + {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA", YES, NO, YES, 7000 }, + {CTRY_LEBANON, NULL1_WORLD, "LB", "LEBANON", YES, NO, YES, 7000 }, + {CTRY_LIECHTENSTEIN,ETSI1_WORLD, "LI", "LIECHTENSTEIN", YES, NO, YES, 7000 }, + {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA", YES, NO, YES, 7000 }, + {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG", YES, NO, YES, 7000 }, + {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU", YES, YES, YES, 7000 }, + {CTRY_MACEDONIA, NULL1_WORLD, "MK", "MACEDONIA", YES, NO, YES, 7000 }, + {CTRY_MALAYSIA, APL8_WORLD, "MY", "MALAYSIA", YES, NO, NO, 7000 }, + {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA", YES, NO, YES, 7000 }, + {CTRY_MEXICO, FCC1_FCCA, "MX", "MEXICO", YES, YES, YES, 7000 }, + {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO", YES, YES, YES, 7000 }, + {CTRY_MOROCCO, NULL1_WORLD, "MA", "MOROCCO", YES, NO, YES, 7000 }, + {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS", YES, NO, YES, 7000 }, + {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ", "NEW ZEALAND", YES, NO, YES, 7000 }, + {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY", YES, NO, YES, 7000 }, + {CTRY_OMAN, APL6_WORLD, "OM", "OMAN", YES, NO, YES, 7000 }, + {CTRY_PAKISTAN, NULL1_WORLD, "PK", "PAKISTAN", YES, NO, YES, 7000 }, + {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA", YES, YES, YES, 7000 }, + {CTRY_PERU, APL1_WORLD, "PE", "PERU", YES, NO, YES, 7000 }, + {CTRY_PHILIPPINES, APL1_WORLD, "PH", "PHILIPPINES", YES, YES, YES, 7000 }, + {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND", YES, NO, YES, 7000 }, + {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL", YES, NO, YES, 7000 }, + {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO", YES, YES, YES, 7000 }, + {CTRY_QATAR, NULL1_WORLD, "QA", "QATAR", YES, NO, YES, 7000 }, + {CTRY_ROMANIA, NULL1_WORLD, "RO", "ROMANIA", YES, NO, YES, 7000 }, + {CTRY_RUSSIA, NULL1_WORLD, "RU", "RUSSIA", YES, NO, YES, 7000 }, + {CTRY_SAUDI_ARABIA,NULL1_WORLD, "SA", "SAUDI ARABIA", YES, NO, YES, 7000 }, + {CTRY_SINGAPORE, APL6_WORLD, "SG", "SINGAPORE", YES, YES, YES, 7000 }, + {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAK REPUBLIC",YES, NO, YES, 7000 }, + {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA", YES, NO, YES, 7000 }, + {CTRY_SOUTH_AFRICA,FCC3_WORLD, "ZA", "SOUTH AFRICA", YES, NO, YES, 7000 }, + {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN", YES, NO, YES, 7000 }, + {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN", YES, NO, YES, 7000 }, + {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND", YES, NO, YES, 7000 }, + {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIA", YES, NO, YES, 7000 }, + {CTRY_TAIWAN, APL3_FCCA, "TW", "TAIWAN", YES, YES, YES, 7000 }, + {CTRY_THAILAND, NULL1_WORLD, "TH", "THAILAND", YES, NO, YES, 7000 }, + {CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD,"TT", "TRINIDAD & TOBAGO", YES, NO, YES, 7000 }, + {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA", YES, NO, YES, 7000 }, + {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY", YES, NO, YES, 7000 }, + {CTRY_UKRAINE, NULL1_WORLD, "UA", "UKRAINE", YES, NO, YES, 7000 }, + {CTRY_UAE, NULL1_WORLD, "AE", "UNITED ARAB EMIRATES", YES, NO, YES, 7000 }, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD,"GB", "UNITED KINGDOM", YES, NO, YES, 7000 }, + {CTRY_UNITED_STATES, FCC1_FCCA, "US", "UNITED STATES", YES, YES, YES, 5825 }, + {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS", "UNITED STATES (PUBLIC SAFETY)", YES, YES, YES, 7000 }, + {CTRY_URUGUAY, APL2_WORLD, "UY", "URUGUAY", YES, NO, YES, 7000 }, + {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN", YES, YES, YES, 7000 }, + {CTRY_VENEZUELA, APL2_ETSIC, "VE", "VENEZUELA", YES, NO, YES, 7000 }, + {CTRY_VIET_NAM, NULL1_WORLD, "VN", "VIET NAM", YES, NO, YES, 7000 }, + {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, 7000 }, + {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, 7000 } +}; +#undef YES +#undef NO + +static HAL_BOOL +cclookup(const char *name, HAL_REG_DOMAIN *rd, HAL_CTRY_CODE *cc) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + for (i = 0; i < N(allCountries); i++) + if (strcasecmp(allCountries[i].isoName, name) == 0 || + strcasecmp(allCountries[i].name, name) == 0) { + *rd = allCountries[i].regDmnEnum; + *cc = allCountries[i].countryCode; + return AH_TRUE; + } + return AH_FALSE; +#undef N +} + +static const char * +getccname(HAL_CTRY_CODE cc) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + for (i = 0; i < N(allCountries); i++) + if (allCountries[i].countryCode == cc) + return allCountries[i].name; + return NULL; +#undef N +} + +static const char * +getccisoname(HAL_CTRY_CODE cc) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + for (i = 0; i < N(allCountries); i++) + if (allCountries[i].countryCode == cc) + return allCountries[i].isoName; + return NULL; +#undef N +} + +static void +cclist() +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + int i; + + printf("\nCountry codes:\n"); + for (i = 0; i < N(allCountries); i++) + printf("%2s %-15.15s%s", + allCountries[i].isoName, + allCountries[i].name, + ((i+1)%4) == 0 ? "\n" : " "); + printf("\n"); +#undef N +} + +static HAL_BOOL +setRateTable(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t tpcScaleReduction, int16_t powerLimit, + int16_t *pMinPower, int16_t *pMaxPower); + +static void +calctxpower(struct ath_hal *ah, int nchan, HAL_CHANNEL *chans, + int16_t tpcScaleReduction, int16_t powerLimit, int16_t *txpow) +{ + int16_t minpow; + int i; + + for (i = 0; i < nchan; i++) + if (!setRateTable(ah, &chans[i], + tpcScaleReduction, powerLimit, &minpow, &txpow[i])) { + printf("unable to set rate table\n"); + exit(-1); + } +} + +int n = 1; +const char *sep = ""; +int dopassive = 0; +int showchannels = 0; +int isdfs = 0; +int is4ms = 0; + +static int +anychan(const HAL_CHANNEL *chans, int nc, int flag) +{ + int i; + + for (i = 0; i < nc; i++) + if ((chans[i].privFlags & flag) != 0) + return 1; + return 0; +} + +static __inline int +mapgsm(u_int freq, u_int flags) +{ + freq *= 10; + if (flags & CHANNEL_QUARTER) + freq += 5; + else if (flags & CHANNEL_HALF) + freq += 10; + else + freq += 20; + return (freq - 24220) / 5; +} + +static __inline int +mappsb(u_int freq, u_int flags) +{ + return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5; +} + +/* + * Convert GHz frequency to IEEE channel number. + */ +int +ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags) +{ + if (flags & CHANNEL_2GHZ) { /* 2GHz band */ + if (freq == 2484) + return 14; + if (freq < 2484) { + if (ath_hal_isgsmsku(ah)) + return mapgsm(freq, flags); + return ((int)freq - 2407) / 5; + } else + return 15 + ((freq - 2512) / 20); + } else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */ + if (ath_hal_ispublicsafetysku(ah) && + IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { + return mappsb(freq, flags); + } else if ((flags & CHANNEL_A) && (freq <= 5000)) { + return (freq - 4000) / 5; + } else { + return (freq - 5000) / 5; + } + } else { /* either, guess */ + if (freq == 2484) + return 14; + if (freq < 2484) { + if (ath_hal_isgsmsku(ah)) + return mapgsm(freq, flags); + return ((int)freq - 2407) / 5; + } + if (freq < 5000) { + if (ath_hal_ispublicsafetysku(ah) && + IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { + return mappsb(freq, flags); + } else if (freq > 4900) { + return (freq - 4000) / 5; + } else { + return 15 + ((freq - 2512) / 20); + } + } + return (freq - 5000) / 5; + } +} + +#define IS_CHAN_DFS(_c) (((_c)->privFlags & CHANNEL_DFS) != 0) +#define IS_CHAN_4MS(_c) (((_c)->privFlags & CHANNEL_4MS_LIMIT) != 0) + +static void +dumpchannels(struct ath_hal *ah, int nc, HAL_CHANNEL *chans, int16_t *txpow) +{ + int i; + + for (i = 0; i < nc; i++) { + HAL_CHANNEL *c = &chans[i]; + int type; + + if (showchannels) + printf("%s%3d", sep, + ath_hal_mhz2ieee(ah, c->channel, c->channelFlags)); + else + printf("%s%u", sep, c->channel); + if (IS_CHAN_HALF_RATE(c)) + type = 'H'; + else if (IS_CHAN_QUARTER_RATE(c)) + type = 'Q'; + else if (IS_CHAN_TURBO(c)) + type = 'T'; + else if (IS_CHAN_HT(c)) + type = 'N'; + else if (IS_CHAN_A(c)) + type = 'A'; + else if (IS_CHAN_108G(c)) + type = 'T'; + else if (IS_CHAN_G(c)) + type = 'G'; + else + type = 'B'; + if (dopassive && IS_CHAN_PASSIVE(c)) + type = tolower(type); + if (isdfs && is4ms) + printf("%c%c%c %d.%d", type, + IS_CHAN_DFS(c) ? '*' : ' ', + IS_CHAN_4MS(c) ? '4' : ' ', + txpow[i]/2, (txpow[i]%2)*5); + else if (isdfs) + printf("%c%c %d.%d", type, + IS_CHAN_DFS(c) ? '*' : ' ', + txpow[i]/2, (txpow[i]%2)*5); + else if (is4ms) + printf("%c%c %d.%d", type, + IS_CHAN_4MS(c) ? '4' : ' ', + txpow[i]/2, (txpow[i]%2)*5); + else + printf("%c %d.%d", type, txpow[i]/2, (txpow[i]%2)*5); + if ((n++ % (showchannels ? 7 : 6)) == 0) + sep = "\n"; + else + sep = " "; + } +} + +static void +checkchannels(struct ath_hal *ah, HAL_CHANNEL *chans, int nchan) +{ + int i; + + for (i = 0; i < nchan; i++) { + HAL_CHANNEL *c = &chans[i]; + if (!ath_hal_checkchannel(ah, c)) + printf("Channel %u (0x%x) disallowed\n", + c->channel, c->channelFlags); + } +} + +static void +intersect(HAL_CHANNEL *dst, int16_t *dtxpow, int *nd, + const HAL_CHANNEL *src, int16_t *stxpow, int ns) +{ + int i = 0, j, k, l; + while (i < *nd) { + for (j = 0; j < ns && dst[i].channel != src[j].channel; j++) + ; + if (j < ns && dtxpow[i] == stxpow[j]) { + for (k = i+1, l = i; k < *nd; k++, l++) + dst[l] = dst[k]; + (*nd)--; + } else + i++; + } +} + +static void +usage(const char *progname) +{ + printf("usage: %s [-acdefoilpr4ABGT] [-m opmode] [cc | rd]\n", progname); + exit(-1); +} + +static HAL_BOOL +getChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchan) +{ +} + +static HAL_BOOL +eepromRead(struct ath_hal *ah, u_int off, u_int16_t *data) +{ + /* emulate enough stuff to handle japan channel shift */ + switch (off) { + case AR_EEPROM_VERSION: + *data = eeversion; + return AH_TRUE; + case AR_EEPROM_REG_CAPABILITIES_OFFSET: + *data = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A; + return AH_TRUE; + case AR_EEPROM_REG_CAPABILITIES_OFFSET_PRE4_0: + *data = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0; + return AH_TRUE; + } + return AH_FALSE; +} + +HAL_STATUS +getCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + uint32_t capability, uint32_t *result) +{ + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + switch (type) { + case HAL_CAP_REG_DMN: /* regulatory domain */ + *result = AH_PRIVATE(ah)->ah_currentRD; + return HAL_OK; + default: + return HAL_EINVAL; + } +} + +#define HAL_MODE_HT20 \ + (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20) +#define HAL_MODE_HT40 \ + (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \ + HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS) +#define HAL_MODE_HT (HAL_MODE_HT20 | HAL_MODE_HT40) + +int +main(int argc, char *argv[]) +{ + static const u_int16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, MAX_RATE_POWER }; + struct ath_hal_private ahp; + HAL_CHANNEL achans[IEEE80211_CHAN_MAX]; + int16_t atxpow[IEEE80211_CHAN_MAX]; + HAL_CHANNEL bchans[IEEE80211_CHAN_MAX]; + int16_t btxpow[IEEE80211_CHAN_MAX]; + HAL_CHANNEL gchans[IEEE80211_CHAN_MAX]; + int16_t gtxpow[IEEE80211_CHAN_MAX]; + HAL_CHANNEL tchans[IEEE80211_CHAN_MAX]; + int16_t ttxpow[IEEE80211_CHAN_MAX]; + HAL_CHANNEL tgchans[IEEE80211_CHAN_MAX]; + int16_t tgtxpow[IEEE80211_CHAN_MAX]; + HAL_CHANNEL nchans[IEEE80211_CHAN_MAX]; + int16_t ntxpow[IEEE80211_CHAN_MAX]; + int i, na, nb, ng, nt, ntg, nn; + HAL_BOOL showall = AH_FALSE; + HAL_BOOL extendedChanMode = AH_TRUE; + int modes = 0; + int16_t tpcReduction, powerLimit; + int8_t regids[IEEE80211_REGCLASSIDS_MAX]; + int nregids; + int showdfs = 0; + int show4ms = 0; + + memset(&ahp, 0, sizeof(ahp)); + ahp.ah_getChannelEdges = getChannelEdges; + ahp.ah_getWirelessModes = getWirelessModes; + ahp.ah_eepromRead = eepromRead; + ahp.ah_getChipPowerLimits = getChipPowerLimits; + ahp.ah_caps.halWirelessModes = HAL_MODE_ALL; + ahp.ah_caps.halLow5GhzChan = 4920; + ahp.ah_caps.halHigh5GhzChan = 6100; + ahp.ah_caps.halLow2GhzChan = 2312; + ahp.ah_caps.halHigh2GhzChan = 2732; + ahp.ah_caps.halChanHalfRate = AH_TRUE; + ahp.ah_caps.halChanQuarterRate = AH_TRUE; + ahp.h.ah_getCapability = getCapability; + ahp.ah_opmode = HAL_M_STA; + + tpcReduction = tpcScaleReductionTable[0]; + powerLimit = MAX_RATE_POWER; + + while ((i = getopt(argc, argv, "acdefoilm:pr4ABGhHNT")) != -1) + switch (i) { + case 'a': + showall = AH_TRUE; + break; + case 'c': + showchannels = AH_TRUE; + break; + case 'd': + ath_hal_debug = HAL_DEBUG_ANY; + break; + case 'e': + extendedChanMode = AH_FALSE; + break; + case 'f': + showchannels = AH_FALSE; + break; + case 'o': + outdoor = AH_TRUE; + break; + case 'i': + outdoor = AH_FALSE; + break; + case 'l': + cclist(); + rdlist(); + exit(0); + case 'm': + if (strncasecmp(optarg, "sta", 2) == 0) + ahp.ah_opmode = HAL_M_STA; + else if (strncasecmp(optarg, "ibss", 2) == 0) + ahp.ah_opmode = HAL_M_IBSS; + else if (strncasecmp(optarg, "adhoc", 2) == 0) + ahp.ah_opmode = HAL_M_IBSS; + else if (strncasecmp(optarg, "ap", 2) == 0) + ahp.ah_opmode = HAL_M_HOSTAP; + else if (strncasecmp(optarg, "hostap", 2) == 0) + ahp.ah_opmode = HAL_M_HOSTAP; + else if (strncasecmp(optarg, "monitor", 2) == 0) + ahp.ah_opmode = HAL_M_MONITOR; + else + usage(argv[0]); + break; + case 'p': + dopassive = 1; + break; + case 'A': + modes |= HAL_MODE_11A; + break; + case 'B': + modes |= HAL_MODE_11B; + break; + case 'G': + modes |= HAL_MODE_11G; + break; + case 'h': + modes |= HAL_MODE_HT20; + break; + case 'H': + modes |= HAL_MODE_HT40; + break; + case 'N': + modes |= HAL_MODE_HT; + break; + case 'T': + modes |= HAL_MODE_TURBO | HAL_MODE_108G; + break; + case 'r': + showdfs = 1; + break; + case '4': + show4ms = 1; + break; + default: + usage(argv[0]); + } + switch (argc - optind) { + case 0: + if (!cclookup("US", &rd, &cc)) { + printf("%s: unknown country code\n", "US"); + exit(-1); + } + break; + case 1: /* cc/regdomain */ + if (!cclookup(argv[optind], &rd, &cc)) { + if (!rdlookup(argv[optind], &rd)) { + const char* rdname; + + rd = strtoul(argv[optind], NULL, 0); + rdname = getrdname(rd); + if (rdname == NULL) { + printf("%s: unknown country/regulatory " + "domain code\n", argv[optind]); + exit(-1); + } + } + cc = CTRY_DEFAULT; + } + break; + default: /* regdomain cc */ + if (!rdlookup(argv[optind], &rd)) { + const char* rdname; + + rd = strtoul(argv[optind], NULL, 0); + rdname = getrdname(rd); + if (rdname == NULL) { + printf("%s: unknown country/regulatory " + "domain code\n", argv[optind]); + exit(-1); + } + } + if (!cclookup(argv[optind+1], &rd, &cc)) + cc = strtoul(argv[optind+1], NULL, 0); + break; + } + if (cc != CTRY_DEFAULT) + printf("\n%s (%s, 0x%x, %u) %s (0x%x, %u)\n", + getccname(cc), getccisoname(cc), cc, cc, + getrdname(rd), rd, rd); + else + printf("\n%s (0x%x, %u)\n", + getrdname(rd), rd, rd); + + if (modes == 0) + modes = HAL_MODE_11A | HAL_MODE_11B | + HAL_MODE_11G | HAL_MODE_TURBO | HAL_MODE_108G | + HAL_MODE_HT; + na = nb = ng = nt = ntg = nn = 0; + if (modes & HAL_MODE_11G) { + ahp.ah_currentRD = rd; + if (ath_hal_init_channels(&ahp.h, + gchans, IEEE80211_CHAN_MAX, &ng, + regids, IEEE80211_REGCLASSIDS_MAX, &nregids, + cc, HAL_MODE_11G, outdoor, extendedChanMode)) { + checkchannels(&ahp.h, gchans, ng); + calctxpower(&ahp.h, ng, gchans, tpcReduction, powerLimit, gtxpow); + if (showdfs) + isdfs |= anychan(gchans, ng, CHANNEL_DFS); + if (show4ms) + is4ms |= anychan(gchans, ng, CHANNEL_4MS_LIMIT); + } + } + if (modes & HAL_MODE_11B) { + ahp.ah_currentRD = rd; + if (ath_hal_init_channels(&ahp.h, + bchans, IEEE80211_CHAN_MAX, &nb, + regids, IEEE80211_REGCLASSIDS_MAX, &nregids, + cc, HAL_MODE_11B, outdoor, extendedChanMode)) { + checkchannels(&ahp.h, bchans, nb); + calctxpower(&ahp.h, nb, bchans, tpcReduction, powerLimit, btxpow); + if (showdfs) + isdfs |= anychan(bchans, nb, CHANNEL_DFS); + if (show4ms) + is4ms |= anychan(bchans, nb, CHANNEL_4MS_LIMIT); + } + } + if (modes & HAL_MODE_11A) { + ahp.ah_currentRD = rd; + if (ath_hal_init_channels(&ahp.h, + achans, IEEE80211_CHAN_MAX, &na, + regids, IEEE80211_REGCLASSIDS_MAX, &nregids, + cc, HAL_MODE_11A, outdoor, extendedChanMode)) { + checkchannels(&ahp.h, achans, na); + calctxpower(&ahp.h, na, achans, tpcReduction, powerLimit, atxpow); + if (showdfs) + isdfs |= anychan(achans, na, CHANNEL_DFS); + if (show4ms) + is4ms |= anychan(achans, na, CHANNEL_4MS_LIMIT); + } + } + if (modes & HAL_MODE_TURBO) { + ahp.ah_currentRD = rd; + if (ath_hal_init_channels(&ahp.h, + tchans, IEEE80211_CHAN_MAX, &nt, + regids, IEEE80211_REGCLASSIDS_MAX, &nregids, + cc, HAL_MODE_TURBO, outdoor, extendedChanMode)) { + checkchannels(&ahp.h, tchans, nt); + calctxpower(&ahp.h, nt, tchans, tpcReduction, powerLimit, ttxpow); + if (showdfs) + isdfs |= anychan(tchans, nt, CHANNEL_DFS); + if (show4ms) + is4ms |= anychan(tchans, nt, CHANNEL_4MS_LIMIT); + } + } + if (modes & HAL_MODE_108G) { + ahp.ah_currentRD = rd; + if (ath_hal_init_channels(&ahp.h, + tgchans, IEEE80211_CHAN_MAX, &ntg, + regids, IEEE80211_REGCLASSIDS_MAX, &nregids, + cc, HAL_MODE_108G, outdoor, extendedChanMode)) { + checkchannels(&ahp.h, tgchans, ntg); + calctxpower(&ahp.h, ntg, tgchans, tpcReduction, powerLimit, tgtxpow); + if (showdfs) + isdfs |= anychan(tgchans, ntg, CHANNEL_DFS); + if (show4ms) + is4ms |= anychan(tgchans, ntg, CHANNEL_4MS_LIMIT); + } + } + if (modes & HAL_MODE_HT) { + ahp.ah_currentRD = rd; + if (ath_hal_init_channels(&ahp.h, + nchans, IEEE80211_CHAN_MAX, &nn, + regids, IEEE80211_REGCLASSIDS_MAX, &nregids, + cc, modes & HAL_MODE_HT, outdoor, extendedChanMode)) { + checkchannels(&ahp.h, nchans, nn); + calctxpower(&ahp.h, nn, nchans, tpcReduction, powerLimit, ntxpow); + if (showdfs) + isdfs |= anychan(nchans, nn, CHANNEL_DFS); + if (show4ms) + is4ms |= anychan(nchans, nn, CHANNEL_4MS_LIMIT); + } + } + + if (!showall) { +#define CHECKMODES(_modes, _m) ((_modes & (_m)) == (_m)) + if (CHECKMODES(modes, HAL_MODE_11B|HAL_MODE_11G)) { + /* b ^= g */ + intersect(bchans, btxpow, &nb, gchans, gtxpow, ng); + } + if (CHECKMODES(modes, HAL_MODE_11A|HAL_MODE_TURBO)) { + /* t ^= a */ + intersect(tchans, ttxpow, &nt, achans, atxpow, na); + } + if (CHECKMODES(modes, HAL_MODE_11G|HAL_MODE_108G)) { + /* tg ^= g */ + intersect(tgchans, tgtxpow, &ntg, gchans, gtxpow, ng); + } + if (CHECKMODES(modes, HAL_MODE_11G|HAL_MODE_HT)) { + /* g ^= n */ + intersect(gchans, gtxpow, &ng, nchans, ntxpow, nn); + } + if (CHECKMODES(modes, HAL_MODE_11A|HAL_MODE_HT)) { + /* a ^= n */ + intersect(achans, atxpow, &na, nchans, ntxpow, nn); + } +#undef CHECKMODES + } + + if (modes & HAL_MODE_11G) + dumpchannels(&ahp.h, ng, gchans, gtxpow); + if (modes & HAL_MODE_11B) + dumpchannels(&ahp.h, nb, bchans, btxpow); + if (modes & HAL_MODE_11A) + dumpchannels(&ahp.h, na, achans, atxpow); + if (modes & HAL_MODE_108G) + dumpchannels(&ahp.h, ntg, tgchans, tgtxpow); + if (modes & HAL_MODE_TURBO) + dumpchannels(&ahp.h, nt, tchans, ttxpow); + if (modes & HAL_MODE_HT) + dumpchannels(&ahp.h, nn, nchans, ntxpow); + printf("\n"); + return (0); +} + +/* + * Search a list for a specified value v that is within + * EEP_DELTA of the search values. Return the closest + * values in the list above and below the desired value. + * EEP_DELTA is a factional value; everything is scaled + * so only integer arithmetic is used. + * + * NB: the input list is assumed to be sorted in ascending order + */ +static void +ar5212GetLowerUpperValues(u_int16_t v, u_int16_t *lp, u_int16_t listSize, + u_int16_t *vlo, u_int16_t *vhi) +{ + u_int32_t target = v * EEP_SCALE; + u_int16_t *ep = lp+listSize; + + /* + * Check first and last elements for out-of-bounds conditions. + */ + if (target < (u_int32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) { + *vlo = *vhi = lp[0]; + return; + } + if (target > (u_int32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) { + *vlo = *vhi = ep[-1]; + return; + } + + /* look for value being near or between 2 values in list */ + for (; lp < ep; lp++) { + /* + * If value is close to the current value of the list + * then target is not between values, it is one of the values + */ + if (abs(lp[0] * EEP_SCALE - target) < EEP_DELTA) { + *vlo = *vhi = lp[0]; + return; + } + /* + * Look for value being between current value and next value + * if so return these 2 values + */ + if (target < (u_int32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) { + *vlo = lp[0]; + *vhi = lp[1]; + return; + } + } +} + +/* + * Find the maximum conformance test limit for the given channel and CTL info + */ +static u_int16_t +ar5212GetMaxEdgePower(u_int16_t channel, RD_EDGES_POWER *pRdEdgesPower) +{ + /* temp array for holding edge channels */ + u_int16_t tempChannelList[NUM_EDGES]; + u_int16_t clo, chi, twiceMaxEdgePower; + int i, numEdges; + + /* Get the edge power */ + for (i = 0; i < NUM_EDGES; i++) { + if (pRdEdgesPower[i].rdEdge == 0) + break; + tempChannelList[i] = pRdEdgesPower[i].rdEdge; + } + numEdges = i; + + ar5212GetLowerUpperValues(channel, tempChannelList, + numEdges, &clo, &chi); + /* Get the index for the lower channel */ + for (i = 0; i < numEdges && clo != tempChannelList[i]; i++) + ; + /* Is lower channel ever outside the rdEdge? */ + HALASSERT(i != numEdges); + + if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) { + /* + * If there's an exact channel match or an inband flag set + * on the lower channel use the given rdEdgePower + */ + twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; + HALASSERT(twiceMaxEdgePower > 0); + } else + twiceMaxEdgePower = MAX_RATE_POWER; + return twiceMaxEdgePower; +} + +/* + * Returns interpolated or the scaled up interpolated value + */ +static u_int16_t +interpolate(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight, + u_int16_t targetLeft, u_int16_t targetRight) +{ + u_int16_t rv; + int16_t lRatio; + + /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ + if ((targetLeft * targetRight) == 0) + return 0; + + if (srcRight != srcLeft) { + /* + * Note the ratio always need to be scaled, + * since it will be a fraction. + */ + lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); + if (lRatio < 0) { + /* Return as Left target if value would be negative */ + rv = targetLeft; + } else if (lRatio > EEP_SCALE) { + /* Return as Right target if Ratio is greater than 100% (SCALE) */ + rv = targetRight; + } else { + rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * + targetLeft) / EEP_SCALE; + } + } else { + rv = targetLeft; + } + return rv; +} + +/* + * Return the four rates of target power for the given target power table + * channel, and number of channels + */ +static void +ar5212GetTargetPowers(struct ath_hal *ah, HAL_CHANNEL *chan, + TRGT_POWER_INFO *powInfo, + u_int16_t numChannels, TRGT_POWER_INFO *pNewPower) +{ + /* temp array for holding target power channels */ + u_int16_t tempChannelList[NUM_TEST_FREQUENCIES]; + u_int16_t clo, chi, ixlo, ixhi; + int i; + + /* Copy the target powers into the temp channel list */ + for (i = 0; i < numChannels; i++) + tempChannelList[i] = powInfo[i].testChannel; + + ar5212GetLowerUpperValues(chan->channel, tempChannelList, + numChannels, &clo, &chi); + + /* Get the indices for the channel */ + ixlo = ixhi = 0; + for (i = 0; i < numChannels; i++) { + if (clo == tempChannelList[i]) { + ixlo = i; + } + if (chi == tempChannelList[i]) { + ixhi = i; + break; + } + } + + /* + * Get the lower and upper channels, target powers, + * and interpolate between them. + */ + pNewPower->twicePwr6_24 = interpolate(chan->channel, clo, chi, + powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24); + pNewPower->twicePwr36 = interpolate(chan->channel, clo, chi, + powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36); + pNewPower->twicePwr48 = interpolate(chan->channel, clo, chi, + powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48); + pNewPower->twicePwr54 = interpolate(chan->channel, clo, chi, + powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54); +} + +static RD_EDGES_POWER* +findEdgePower(struct ath_hal *ah, u_int ctl) +{ + int i; + + for (i = 0; i < _numCtls; i++) + if (_ctl[i] == ctl) + return &_rdEdgesPower[i * NUM_EDGES]; + return AH_NULL; +} + +/* + * Sets the transmit power in the baseband for the given + * operating channel and mode. + */ +static HAL_BOOL +setRateTable(struct ath_hal *ah, HAL_CHANNEL *chan, + int16_t tpcScaleReduction, int16_t powerLimit, + int16_t *pMinPower, int16_t *pMaxPower) +{ + u_int16_t ratesArray[16]; + u_int16_t *rpow = ratesArray; + u_int16_t twiceMaxRDPower, twiceMaxEdgePower, twiceMaxEdgePowerCck; + int8_t twiceAntennaGain, twiceAntennaReduction; + TRGT_POWER_INFO targetPowerOfdm, targetPowerCck; + RD_EDGES_POWER *rep; + int16_t scaledPower; + u_int8_t cfgCtl; + + twiceMaxRDPower = chan->maxRegTxPower * 2; + *pMaxPower = -MAX_RATE_POWER; + *pMinPower = MAX_RATE_POWER; + + /* Get conformance test limit maximum for this channel */ + cfgCtl = ath_hal_getctl(ah, chan); + rep = findEdgePower(ah, cfgCtl); + if (rep != AH_NULL) + twiceMaxEdgePower = ar5212GetMaxEdgePower(chan->channel, rep); + else + twiceMaxEdgePower = MAX_RATE_POWER; + + if (IS_CHAN_G(chan)) { + /* Check for a CCK CTL for 11G CCK powers */ + cfgCtl = (cfgCtl & 0xFC) | 0x01; + rep = findEdgePower(ah, cfgCtl); + if (rep != AH_NULL) + twiceMaxEdgePowerCck = ar5212GetMaxEdgePower(chan->channel, rep); + else + twiceMaxEdgePowerCck = MAX_RATE_POWER; + } else { + /* Set the 11B cck edge power to the one found before */ + twiceMaxEdgePowerCck = twiceMaxEdgePower; + } + + /* Get Antenna Gain reduction */ + if (IS_CHAN_5GHZ(chan)) { + twiceAntennaGain = antennaGainMax[0]; + } else { + twiceAntennaGain = antennaGainMax[1]; + } + twiceAntennaReduction = + ath_hal_getantennareduction(ah, chan, twiceAntennaGain); + + if (IS_CHAN_OFDM(chan)) { + /* Get final OFDM target powers */ + if (IS_CHAN_G(chan)) { + /* TODO - add Turbo 2.4 to this mode check */ + ar5212GetTargetPowers(ah, chan, trgtPwr_11g, + numTargetPwr_11g, &targetPowerOfdm); + } else { + ar5212GetTargetPowers(ah, chan, trgtPwr_11a, + numTargetPwr_11a, &targetPowerOfdm); + } + + /* Get Maximum OFDM power */ + /* Minimum of target and edge powers */ + scaledPower = AH_MIN(twiceMaxEdgePower, + twiceMaxRDPower - twiceAntennaReduction); + + /* + * If turbo is set, reduce power to keep power + * consumption under 2 Watts. Note that we always do + * this unless specially configured. Then we limit + * power only for non-AP operation. + */ + if (IS_CHAN_TURBO(chan) +#ifdef AH_ENABLE_AP_SUPPORT + && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP +#endif + ) { + /* + * If turbo is set, reduce power to keep power + * consumption under 2 Watts + */ + if (eeversion >= AR_EEPROM_VER3_1) + scaledPower = AH_MIN(scaledPower, + turbo2WMaxPower5); + /* + * EEPROM version 4.0 added an additional + * constraint on 2.4GHz channels. + */ + if (eeversion >= AR_EEPROM_VER4_0 && + IS_CHAN_2GHZ(chan)) + scaledPower = AH_MIN(scaledPower, + turbo2WMaxPower2); + } + /* Reduce power by max regulatory domain allowed restrictions */ + scaledPower -= (tpcScaleReduction * 2); + scaledPower = (scaledPower < 0) ? 0 : scaledPower; + scaledPower = AH_MIN(scaledPower, powerLimit); + + scaledPower = AH_MIN(scaledPower, targetPowerOfdm.twicePwr6_24); + + /* Set OFDM rates 9, 12, 18, 24, 36, 48, 54, XR */ + rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower; + rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36); + rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48); + rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54); + +#ifdef notyet + if (eeversion >= AR_EEPROM_VER4_0) { + /* Setup XR target power from EEPROM */ + rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ? + xrTargetPower2 : xrTargetPower5); + } else { + /* XR uses 6mb power */ + rpow[15] = rpow[0]; + } +#else + rpow[15] = rpow[0]; +#endif + + *pMinPower = rpow[7]; + *pMaxPower = rpow[0]; + +#if 0 + ahp->ah_ofdmTxPower = rpow[0]; +#endif + + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: MaxRD: %d TurboMax: %d MaxCTL: %d " + "TPC_Reduction %d\n", __func__, + twiceMaxRDPower, turbo2WMaxPower5, + twiceMaxEdgePower, tpcScaleReduction * 2); + } + + if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { + /* Get final CCK target powers */ + ar5212GetTargetPowers(ah, chan, trgtPwr_11b, + numTargetPwr_11b, &targetPowerCck); + + /* Reduce power by max regulatory domain allowed restrictions */ + scaledPower = AH_MIN(twiceMaxEdgePowerCck, + twiceMaxRDPower - twiceAntennaReduction); + + scaledPower -= (tpcScaleReduction * 2); + scaledPower = (scaledPower < 0) ? 0 : scaledPower; + scaledPower = AH_MIN(scaledPower, powerLimit); + + rpow[8] = (scaledPower < 1) ? 1 : scaledPower; + + /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */ + rpow[8] = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24); + rpow[9] = AH_MIN(scaledPower, targetPowerCck.twicePwr36); + rpow[10] = rpow[9]; + rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48); + rpow[12] = rpow[11]; + rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54); + rpow[14] = rpow[13]; + + /* Set min/max power based off OFDM values or initialization */ + if (rpow[13] < *pMinPower) + *pMinPower = rpow[13]; + if (rpow[9] > *pMaxPower) + *pMaxPower = rpow[9]; + + } +#if 0 + ahp->ah_tx6PowerInHalfDbm = *pMaxPower; +#endif + return AH_TRUE; +} + +void* +ath_hal_malloc(size_t size) +{ + return calloc(1, size); +} + +void +ath_hal_free(void* p) +{ + return free(p); +} + +void +ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap) +{ + vprintf(fmt, ap); +} + +void +ath_hal_printf(struct ath_hal *ah, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + ath_hal_vprintf(ah, fmt, ap); + va_end(ap); +} + +void +HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) +{ + if (ath_hal_debug & mask) { + __va_list ap; + va_start(ap, fmt); + ath_hal_vprintf(ah, fmt, ap); + va_end(ap); + } +} diff --git a/tools/tools/ath/athrd/run.sh b/tools/tools/ath/athrd/run.sh new file mode 100755 index 0000000..3e1e01a --- /dev/null +++ b/tools/tools/ath/athrd/run.sh @@ -0,0 +1,17 @@ +# $FreeBSD$ + +COUNTRIES=${@:-" + DB NA AL DZ AR AM AU AT AZ BH BY BE BZ BO BR BN BG + CA CL CN CO CR HR CY CZ DK DO EC EG SV EE FI FR GE + DE GR GT HN HK HU IS IN ID IR IE IL IT JP J1 J2 J3 + J4 J5 JO KZ KP KR K2 KW LV LB LI LT LU MO MK MY MX + MC MA NL NZ NO OM PK PA PE PH PL PT PR QA RO RU SA + SG SK SI ZA ES SE CH SY TW TH TT TN TR UA AE GB US + UY UZ VE VN YE ZW WOR0_WORLD WOR1_WORLD WOR2_WORLD WOR3_WORLD + WOR4_WORLD, WOR5_ETSIC EU1_WORLD WOR01_WORLD WOR02_WORLD +"} + +for i in $COUNTRIES +do + ./athrd -o $i +done |