1 /*
2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3  * Copyright (c) 2005-2006 Atheros Communications, Inc.
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * $Id: ah_regdomain.c,v 1.2 2008/12/11 05:30:29 alc Exp $
19  */
20 #include "opt_ah.h"
21 
22 #include "ah.h"
23 #include "ah_internal.h"
24 #include "ah_eeprom.h"
25 #include "ah_devid.h"
26 
27 /*
28  * XXX this code needs a audit+review
29  */
30 
31 /* used throughout this file... */
32 #define   N(a)      (sizeof (a) / sizeof (a[0]))
33 
34 #define HAL_MODE_11A_TURBO    HAL_MODE_108A
35 #define HAL_MODE_11G_TURBO    HAL_MODE_108G
36 
37 /* 10MHz is half the 11A bandwidth used to determine upper edge freq
38    of the outdoor channel */
39 #define HALF_MAXCHANBW                  10
40 
41 /*
42  * BMLEN defines the size of the bitmask used to hold frequency
43  * band specifications.  Note this must agree with the BM macro
44  * definition that's used to setup initializers.  See also further
45  * comments below.
46  */
47 #define BMLEN 2               /* 2 x 64 bits in each channel bitmask */
48 typedef uint64_t chanbmask_t[BMLEN];
49 
50 #define   W0(_a) \
51           (((_a) >= 0 && (_a) < 64 ? (((uint64_t) 1)<<(_a)) : (uint64_t) 0))
52 #define   W1(_a) \
53           (((_a) > 63 && (_a) < 128 ? (((uint64_t) 1)<<((_a)-64)) : (uint64_t) 0))
54 #define BM1(_fa)    { W0(_fa), W1(_fa) }
55 #define BM2(_fa, _fb)         { W0(_fa) | W0(_fb), W1(_fa) | W1(_fb) }
56 #define BM3(_fa, _fb, _fc) \
57           { W0(_fa) | W0(_fb) | W0(_fc), W1(_fa) | W1(_fb) | W1(_fc) }
58 #define BM4(_fa, _fb, _fc, _fd)                                                           \
59           { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd),                              \
60             W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) }
61 #define BM5(_fa, _fb, _fc, _fd, _fe)                                            \
62           { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe),                    \
63             W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) }
64 #define BM6(_fa, _fb, _fc, _fd, _fe, _ff)                                       \
65           { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff),          \
66             W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) }
67 #define BM7(_fa, _fb, _fc, _fd, _fe, _ff, _fg)    \
68           { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) |         \
69             W0(_fg),\
70             W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) |         \
71             W1(_fg) }
72 #define BM8(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh)         \
73           { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) |         \
74             W0(_fg) | W0(_fh) ,         \
75             W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) |         \
76             W1(_fg) | W1(_fh) }
77 
78 /*
79  * Country/Region Codes
80  * Numbering from ISO 3166
81  */
82 enum {
83     CTRY_ALBANIA              = 8,       /* Albania */
84     CTRY_ALGERIA              = 12,      /* Algeria */
85     CTRY_ARGENTINA            = 32,      /* Argentina */
86     CTRY_ARMENIA              = 51,      /* Armenia */
87     CTRY_AUSTRALIA            = 36,      /* Australia */
88     CTRY_AUSTRIA              = 40,      /* Austria */
89     CTRY_AZERBAIJAN           = 31,      /* Azerbaijan */
90     CTRY_BAHRAIN              = 48,      /* Bahrain */
91     CTRY_BELARUS              = 112,     /* Belarus */
92     CTRY_BELGIUM              = 56,      /* Belgium */
93     CTRY_BELIZE               = 84,      /* Belize */
94     CTRY_BOLIVIA              = 68,      /* Bolivia */
95     CTRY_BRAZIL               = 76,      /* Brazil */
96     CTRY_BRUNEI_DARUSSALAM    = 96,      /* Brunei Darussalam */
97     CTRY_BULGARIA             = 100,     /* Bulgaria */
98     CTRY_CANADA               = 124,     /* Canada */
99     CTRY_CHILE                = 152,     /* Chile */
100     CTRY_CHINA                = 156,     /* People's Republic of China */
101     CTRY_COLOMBIA             = 170,     /* Colombia */
102     CTRY_COSTA_RICA           = 188,     /* Costa Rica */
103     CTRY_CROATIA              = 191,     /* Croatia */
104     CTRY_CYPRUS               = 196,
105     CTRY_CZECH                = 203,     /* Czech Republic */
106     CTRY_DENMARK              = 208,     /* Denmark */
107     CTRY_DOMINICAN_REPUBLIC   = 214,     /* Dominican Republic */
108     CTRY_ECUADOR              = 218,     /* Ecuador */
109     CTRY_EGYPT                = 818,     /* Egypt */
110     CTRY_EL_SALVADOR          = 222,     /* El Salvador */
111     CTRY_ESTONIA              = 233,     /* Estonia */
112     CTRY_FAEROE_ISLANDS       = 234,     /* Faeroe Islands */
113     CTRY_FINLAND              = 246,     /* Finland */
114     CTRY_FRANCE               = 250,     /* France */
115     CTRY_FRANCE2              = 255,     /* France2 */
116     CTRY_GEORGIA              = 268,     /* Georgia */
117     CTRY_GERMANY              = 276,     /* Germany */
118     CTRY_GREECE               = 300,     /* Greece */
119     CTRY_GUATEMALA            = 320,     /* Guatemala */
120     CTRY_HONDURAS             = 340,     /* Honduras */
121     CTRY_HONG_KONG            = 344,     /* Hong Kong S.A.R., P.R.C. */
122     CTRY_HUNGARY              = 348,     /* Hungary */
123     CTRY_ICELAND              = 352,     /* Iceland */
124     CTRY_INDIA                = 356,     /* India */
125     CTRY_INDONESIA            = 360,     /* Indonesia */
126     CTRY_IRAN                 = 364,     /* Iran */
127     CTRY_IRAQ                 = 368,     /* Iraq */
128     CTRY_IRELAND              = 372,     /* Ireland */
129     CTRY_ISRAEL               = 376,     /* Israel */
130     CTRY_ITALY                = 380,     /* Italy */
131     CTRY_JAMAICA              = 388,     /* Jamaica */
132     CTRY_JAPAN                = 392,     /* Japan */
133     CTRY_JAPAN1               = 393,     /* Japan (JP1) */
134     CTRY_JAPAN2               = 394,     /* Japan (JP0) */
135     CTRY_JAPAN3               = 395,     /* Japan (JP1-1) */
136     CTRY_JAPAN4               = 396,     /* Japan (JE1) */
137     CTRY_JAPAN5               = 397,     /* Japan (JE2) */
138     CTRY_JAPAN6               = 399,     /* Japan (JP6) */
139 
140     CTRY_JAPAN7                     = 4007,        /* Japan (J7) */
141     CTRY_JAPAN8                     = 4008,        /* Japan (J8) */
142     CTRY_JAPAN9                     = 4009,        /* Japan (J9) */
143 
144     CTRY_JAPAN10          = 4010,        /* Japan (J10) */
145     CTRY_JAPAN11          = 4011,        /* Japan (J11) */
146     CTRY_JAPAN12          = 4012,        /* Japan (J12) */
147 
148     CTRY_JAPAN13          = 4013,        /* Japan (J13) */
149     CTRY_JAPAN14          = 4014,        /* Japan (J14) */
150     CTRY_JAPAN15          = 4015,        /* Japan (J15) */
151 
152     CTRY_JAPAN16          = 4016,        /* Japan (J16) */
153     CTRY_JAPAN17          = 4017,        /* Japan (J17) */
154     CTRY_JAPAN18          = 4018,        /* Japan (J18) */
155 
156     CTRY_JAPAN19          = 4019,        /* Japan (J19) */
157     CTRY_JAPAN20          = 4020,        /* Japan (J20) */
158     CTRY_JAPAN21          = 4021,        /* Japan (J21) */
159 
160     CTRY_JAPAN22          = 4022,        /* Japan (J22) */
161     CTRY_JAPAN23          = 4023,        /* Japan (J23) */
162     CTRY_JAPAN24          = 4024,        /* Japan (J24) */
163 
164     CTRY_JORDAN               = 400,     /* Jordan */
165     CTRY_KAZAKHSTAN           = 398,     /* Kazakhstan */
166     CTRY_KENYA                = 404,     /* Kenya */
167     CTRY_KOREA_NORTH          = 408,     /* North Korea */
168     CTRY_KOREA_ROC            = 410,     /* South Korea */
169     CTRY_KOREA_ROC2           = 411,     /* South Korea */
170     CTRY_KOREA_ROC3           = 412,     /* South Korea */
171     CTRY_KUWAIT               = 414,     /* Kuwait */
172     CTRY_LATVIA               = 428,     /* Latvia */
173     CTRY_LEBANON              = 422,     /* Lebanon */
174     CTRY_LIBYA                = 434,     /* Libya */
175     CTRY_LIECHTENSTEIN        = 438,     /* Liechtenstein */
176     CTRY_LITHUANIA            = 440,     /* Lithuania */
177     CTRY_LUXEMBOURG           = 442,     /* Luxembourg */
178     CTRY_MACAU                = 446,     /* Macau */
179     CTRY_MACEDONIA            = 807,     /* the Former Yugoslav Republic of Macedonia */
180     CTRY_MALAYSIA             = 458,     /* Malaysia */
181     CTRY_MALTA                      = 470,         /* Malta */
182     CTRY_MEXICO               = 484,     /* Mexico */
183     CTRY_MONACO               = 492,     /* Principality of Monaco */
184     CTRY_MOROCCO              = 504,     /* Morocco */
185     CTRY_NETHERLANDS          = 528,     /* Netherlands */
186     CTRY_NEW_ZEALAND          = 554,     /* New Zealand */
187     CTRY_NICARAGUA            = 558,     /* Nicaragua */
188     CTRY_NORWAY               = 578,     /* Norway */
189     CTRY_OMAN                 = 512,     /* Oman */
190     CTRY_PAKISTAN             = 586,     /* Islamic Republic of Pakistan */
191     CTRY_PANAMA               = 591,     /* Panama */
192     CTRY_PARAGUAY             = 600,     /* Paraguay */
193     CTRY_PERU                 = 604,     /* Peru */
194     CTRY_PHILIPPINES          = 608,     /* Republic of the Philippines */
195     CTRY_POLAND               = 616,     /* Poland */
196     CTRY_PORTUGAL             = 620,     /* Portugal */
197     CTRY_PUERTO_RICO          = 630,     /* Puerto Rico */
198     CTRY_QATAR                = 634,     /* Qatar */
199     CTRY_ROMANIA              = 642,     /* Romania */
200     CTRY_RUSSIA               = 643,     /* Russia */
201     CTRY_SAUDI_ARABIA         = 682,     /* Saudi Arabia */
202     CTRY_SINGAPORE            = 702,     /* Singapore */
203     CTRY_SLOVAKIA             = 703,     /* Slovak Republic */
204     CTRY_SLOVENIA             = 705,     /* Slovenia */
205     CTRY_SOUTH_AFRICA         = 710,     /* South Africa */
206     CTRY_SPAIN                = 724,     /* Spain */
207     CTRY_SR9                  = 5000,    /* Ubiquiti SR9 (900MHz/GSM) */
208     CTRY_SWEDEN               = 752,     /* Sweden */
209     CTRY_SWITZERLAND          = 756,     /* Switzerland */
210     CTRY_SYRIA                = 760,     /* Syria */
211     CTRY_TAIWAN               = 158,     /* Taiwan */
212     CTRY_THAILAND             = 764,     /* Thailand */
213     CTRY_TRINIDAD_Y_TOBAGO    = 780,     /* Trinidad y Tobago */
214     CTRY_TUNISIA              = 788,     /* Tunisia */
215     CTRY_TURKEY               = 792,     /* Turkey */
216     CTRY_UAE                  = 784,     /* U.A.E. */
217     CTRY_UKRAINE              = 804,     /* Ukraine */
218     CTRY_UNITED_KINGDOM       = 826,     /* United Kingdom */
219     CTRY_UNITED_STATES        = 840,     /* United States */
220     CTRY_UNITED_STATES_FCC49  = 842,     /* United States (Public Safety)*/
221     CTRY_URUGUAY              = 858,     /* Uruguay */
222     CTRY_UZBEKISTAN           = 860,     /* Uzbekistan */
223     CTRY_VENEZUELA            = 862,     /* Venezuela */
224     CTRY_VIET_NAM             = 704,     /* Viet Nam */
225     CTRY_XR9                  = 5001,    /* Ubiquiti XR9 (900MHz/GSM) */
226     CTRY_GZ901                = 5002,    /* Zcomax GZ-901 (900MHz/GSM) */
227     CTRY_YEMEN                = 887,     /* Yemen */
228     CTRY_ZIMBABWE             = 716      /* Zimbabwe */
229 };
230 
231 
232 /*
233  * Mask to check whether a domain is a multidomain or a single domain
234  */
235 #define MULTI_DOMAIN_MASK 0xFF00
236 
237 /*
238  * Enumerated Regulatory Domain Information 8 bit values indicate that
239  * the regdomain is really a pair of unitary regdomains.  12 bit values
240  * are the real unitary regdomains and are the only ones which have the
241  * frequency bitmasks and flags set.
242  */
243 enum {
244           /*
245            * The following regulatory domain definitions are
246            * found in the EEPROM. Each regulatory domain
247            * can operate in either a 5GHz or 2.4GHz wireless mode or
248            * both 5GHz and 2.4GHz wireless modes.
249            * In general, the value holds no special
250            * meaning and is used to decode into either specific
251            * 2.4GHz or 5GHz wireless mode for that particular
252            * regulatory domain.
253            */
254           NO_ENUMRD = 0x00,
255           NULL1_WORLD         = 0x03,             /* For 11b-only countries (no 11a allowed) */
256           NULL1_ETSIB         = 0x07,             /* Israel */
257           NULL1_ETSIC         = 0x08,
258           FCC1_FCCA = 0x10,             /* USA */
259           FCC1_WORLD          = 0x11,             /* Hong Kong */
260           FCC4_FCCA = 0x12,             /* USA - Public Safety */
261           FCC5_FCCB = 0x13,             /* USA w/ 1/2 and 1/4 width channels */
262 
263           FCC2_FCCA = 0x20,             /* Canada */
264           FCC2_WORLD          = 0x21,             /* Australia & HK */
265           FCC2_ETSIC          = 0x22,
266           FRANCE_RES          = 0x31,             /* Legacy France for OEM */
267           FCC3_FCCA = 0x3A,             /* USA & Canada w/5470 band, 11h, DFS enabled */
268           FCC3_WORLD          = 0x3B,             /* USA & Canada w/5470 band, 11h, DFS enabled */
269 
270           ETSI1_WORLD         = 0x37,
271           ETSI3_ETSIA         = 0x32,             /* France (optional) */
272           ETSI2_WORLD         = 0x35,             /* Hungary & others */
273           ETSI3_WORLD         = 0x36,             /* France & others */
274           ETSI4_WORLD         = 0x30,
275           ETSI4_ETSIC         = 0x38,
276           ETSI5_WORLD         = 0x39,
277           ETSI6_WORLD         = 0x34,             /* Bulgaria */
278           ETSI_RESERVED       = 0x33,             /* Reserved (Do not used) */
279 
280           MKK1_MKKA = 0x40,             /* Japan (JP1) */
281           MKK1_MKKB = 0x41,             /* Japan (JP0) */
282           APL4_WORLD          = 0x42,             /* Singapore */
283           MKK2_MKKA = 0x43,             /* Japan with 4.9G channels */
284           APL_RESERVED        = 0x44,             /* Reserved (Do not used)  */
285           APL2_WORLD          = 0x45,             /* Korea */
286           APL2_APLC = 0x46,
287           APL3_WORLD          = 0x47,
288           MKK1_FCCA = 0x48,             /* Japan (JP1-1) */
289           APL2_APLD = 0x49,             /* Korea with 2.3G channels */
290           MKK1_MKKA1          = 0x4A,             /* Japan (JE1) */
291           MKK1_MKKA2          = 0x4B,             /* Japan (JE2) */
292           MKK1_MKKC = 0x4C,             /* Japan (MKK1_MKKA,except Ch14) */
293 
294           APL3_FCCA       = 0x50,
295           APL1_WORLD          = 0x52,             /* Latin America */
296           APL1_FCCA = 0x53,
297           APL1_APLA = 0x54,
298           APL1_ETSIC          = 0x55,
299           APL2_ETSIC          = 0x56,             /* Venezuela */
300           APL5_WORLD          = 0x58,             /* Chile */
301           APL6_WORLD          = 0x5B,             /* Singapore */
302           APL7_FCCA   = 0x5C,     /* Taiwan 5.47 Band */
303           APL8_WORLD  = 0x5D,     /* Malaysia 5GHz */
304           APL9_WORLD  = 0x5E,     /* Korea 5GHz */
305 
306           /*
307            * World mode SKUs
308            */
309           WOR0_WORLD          = 0x60,             /* World0 (WO0 SKU) */
310           WOR1_WORLD          = 0x61,             /* World1 (WO1 SKU) */
311           WOR2_WORLD          = 0x62,             /* World2 (WO2 SKU) */
312           WOR3_WORLD          = 0x63,             /* World3 (WO3 SKU) */
313           WOR4_WORLD          = 0x64,             /* World4 (WO4 SKU) */
314           WOR5_ETSIC          = 0x65,             /* World5 (WO5 SKU) */
315 
316           WOR01_WORLD         = 0x66,             /* World0-1 (WW0-1 SKU) */
317           WOR02_WORLD         = 0x67,             /* World0-2 (WW0-2 SKU) */
318           EU1_WORLD = 0x68,             /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */
319 
320           WOR9_WORLD          = 0x69,             /* World9 (WO9 SKU) */
321           WORA_WORLD          = 0x6A,             /* WorldA (WOA SKU) */
322 
323           MKK3_MKKB = 0x80,             /* Japan UNI-1 even + MKKB */
324           MKK3_MKKA2          = 0x81,             /* Japan UNI-1 even + MKKA2 */
325           MKK3_MKKC = 0x82,             /* Japan UNI-1 even + MKKC */
326 
327           MKK4_MKKB = 0x83,             /* Japan UNI-1 even + UNI-2 + MKKB */
328           MKK4_MKKA2          = 0x84,             /* Japan UNI-1 even + UNI-2 + MKKA2 */
329           MKK4_MKKC = 0x85,             /* Japan UNI-1 even + UNI-2 + MKKC */
330 
331           MKK5_MKKB = 0x86,             /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */
332           MKK5_MKKA2          = 0x87,             /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */
333           MKK5_MKKC = 0x88,             /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */
334 
335           MKK6_MKKB = 0x89,             /* Japan UNI-1 even + UNI-1 odd MKKB */
336           MKK6_MKKA2          = 0x8A,             /* Japan UNI-1 even + UNI-1 odd + MKKA2 */
337           MKK6_MKKC = 0x8B,             /* Japan UNI-1 even + UNI-1 odd + MKKC */
338 
339           MKK7_MKKB = 0x8C,             /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */
340           MKK7_MKKA2          = 0x8D,             /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */
341           MKK7_MKKC = 0x8E,             /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */
342 
343           MKK8_MKKB = 0x8F,             /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */
344           MKK8_MKKA2          = 0x90,             /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */
345           MKK8_MKKC = 0x91,             /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */
346 
347           /* Following definitions are used only by s/w to map old
348            * Japan SKUs.
349            */
350           MKK3_MKKA       = 0xF0,         /* Japan UNI-1 even + MKKA */
351           MKK3_MKKA1      = 0xF1,         /* Japan UNI-1 even + MKKA1 */
352           MKK3_FCCA       = 0xF2,         /* Japan UNI-1 even + FCCA */
353           MKK4_MKKA       = 0xF3,         /* Japan UNI-1 even + UNI-2 + MKKA */
354           MKK4_MKKA1      = 0xF4,         /* Japan UNI-1 even + UNI-2 + MKKA1 */
355           MKK4_FCCA       = 0xF5,         /* Japan UNI-1 even + UNI-2 + FCCA */
356           MKK9_MKKA       = 0xF6,         /* Japan UNI-1 even + 4.9GHz */
357           MKK10_MKKA      = 0xF7,         /* Japan UNI-1 even + UNI-2 + 4.9GHz */
358 
359           /*
360            * Regulator domains ending in a number (e.g. APL1,
361            * MK1, ETSI4, etc) apply to 5GHz channel and power
362            * information.  Regulator domains ending in a letter
363            * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and
364            * power information.
365            */
366           APL1                = 0x0150, /* LAT & Asia */
367           APL2                = 0x0250, /* LAT & Asia */
368           APL3                = 0x0350, /* Taiwan */
369           APL4                = 0x0450, /* Jordan */
370           APL5                = 0x0550, /* Chile */
371           APL6                = 0x0650, /* Singapore */
372           APL8                = 0x0850, /* Malaysia */
373           APL9                = 0x0950, /* Korea (South) ROC 3 */
374 
375           ETSI1               = 0x0130, /* Europe & others */
376           ETSI2               = 0x0230, /* Europe & others */
377           ETSI3               = 0x0330, /* Europe & others */
378           ETSI4               = 0x0430, /* Europe & others */
379           ETSI5               = 0x0530, /* Europe & others */
380           ETSI6               = 0x0630, /* Europe & others */
381           ETSIA               = 0x0A30, /* France */
382           ETSIB               = 0x0B30, /* Israel */
383           ETSIC               = 0x0C30, /* Latin America */
384 
385           FCC1                = 0x0110, /* US & others */
386           FCC2                = 0x0120, /* Canada, Australia & New Zealand */
387           FCC3                = 0x0160, /* US w/new middle band & DFS */
388           FCC4                = 0x0165,           /* US Public Safety */
389           FCC5                = 0x0166,           /* US w/ 1/2 and 1/4 width channels */
390           FCCA                = 0x0A10,
391           FCCB                = 0x0A11, /* US w/ 1/2 and 1/4 width channels */
392 
393           APLD                = 0x0D50, /* South Korea */
394 
395           MKK1                = 0x0140, /* Japan (UNI-1 odd)*/
396           MKK2                = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */
397           MKK3                = 0x0340, /* Japan (UNI-1 even) */
398           MKK4                = 0x0440, /* Japan (UNI-1 even + UNI-2) */
399           MKK5                = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */
400           MKK6                = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */
401           MKK7                = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */
402           MKK8                = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */
403           MKK9            = 0x0940,       /* Japan (UNI-1 even + 4.9 GHZ) */
404           MKK10           = 0x0B40,       /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
405           MKKA                = 0x0A40, /* Japan */
406           MKKC                = 0x0A50,
407 
408           NULL1               = 0x0198,
409           WORLD               = 0x0199,
410           SR9_WORLD = 0x0298,
411           XR9_WORLD = 0x0299,
412           GZ901_WORLD         = 0x029a,
413           DEBUG_REG_DMN       = 0x01ff,
414 };
415 
416 #define   WORLD_SKU_MASK                0x00F0
417 #define   WORLD_SKU_PREFIX    0x0060
418 
419 enum {                                            /* conformance test limits */
420           FCC       = 0x10,
421           MKK       = 0x40,
422           ETSI      = 0x30,
423 };
424 
425 /*
426  * The following are flags for different requirements per reg domain.
427  * These requirements are either inhereted from the reg domain pair or
428  * from the unitary reg domain if the reg domain pair flags value is 0
429  */
430 enum {
431           NO_REQ                        = 0x00000000,       /* NB: must be zero */
432           DISALLOW_ADHOC_11A  = 0x00000001,
433           DISALLOW_ADHOC_11A_TURB       = 0x00000002,
434           NEED_NFC            = 0x00000004,
435           ADHOC_PER_11D                 = 0x00000008,  /* Start Ad-Hoc mode */
436           ADHOC_NO_11A                  = 0x00000010,
437           LIMIT_FRAME_4MS     = 0x00000020,       /* 4msec limit on frame length*/
438           NO_HOSTAP           = 0x00000040,       /* No HOSTAP mode opereation */
439 };
440 
441 /*
442  * The following describe the bit masks for different passive scan
443  * capability/requirements per regdomain.
444  */
445 #define   NO_PSCAN  0x0ULL                        /* NB: must be zero */
446 #define   PSCAN_FCC 0x0000000000000001ULL
447 #define   PSCAN_FCC_T         0x0000000000000002ULL
448 #define   PSCAN_ETSI          0x0000000000000004ULL
449 #define   PSCAN_MKK1          0x0000000000000008ULL
450 #define   PSCAN_MKK2          0x0000000000000010ULL
451 #define   PSCAN_MKKA          0x0000000000000020ULL
452 #define   PSCAN_MKKA_G        0x0000000000000040ULL
453 #define   PSCAN_ETSIA         0x0000000000000080ULL
454 #define   PSCAN_ETSIB         0x0000000000000100ULL
455 #define   PSCAN_ETSIC         0x0000000000000200ULL
456 #define   PSCAN_WWR 0x0000000000000400ULL
457 #define   PSCAN_MKKA1         0x0000000000000800ULL
458 #define   PSCAN_MKKA1_G       0x0000000000001000ULL
459 #define   PSCAN_MKKA2         0x0000000000002000ULL
460 #define   PSCAN_MKKA2_G       0x0000000000004000ULL
461 #define   PSCAN_MKK3          0x0000000000008000ULL
462 #define   PSCAN_DEFER         0x7FFFFFFFFFFFFFFFULL
463 #define   IS_ECM_CHAN         0x8000000000000000ULL
464 
465 /*
466  * THE following table is the mapping of regdomain pairs specified by
467  * an 8 bit regdomain value to the individual unitary reg domains
468  */
469 typedef struct {
470           HAL_REG_DOMAIN regDmnEnum;    /* 16 bit reg domain pair */
471           HAL_REG_DOMAIN regDmn5GHz;    /* 5GHz reg domain */
472           HAL_REG_DOMAIN regDmn2GHz;    /* 2GHz reg domain */
473           uint32_t flags5GHz;           /* Requirements flags (AdHoc
474                                                      disallow, noise floor cal needed,
475                                                      etc) */
476           uint32_t flags2GHz;           /* Requirements flags (AdHoc
477                                                      disallow, noise floor cal needed,
478                                                      etc) */
479           uint64_t pscanMask;           /* Passive Scan flags which
480                                                      can override unitary domain
481                                                      passive scan flags.  This
482                                                      value is used as a mask on
483                                                      the unitary flags*/
484           uint16_t singleCC;            /* Country code of single country if
485                                                      a one-on-one mapping exists */
486 }  REG_DMN_PAIR_MAPPING;
487 
488 static REG_DMN_PAIR_MAPPING regDomainPairs[] = {
489           {NO_ENUMRD,         DEBUG_REG_DMN,      DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
490           {NULL1_WORLD,       NULL1,              WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
491           {NULL1_ETSIB,       NULL1,              ETSIB,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
492           {NULL1_ETSIC,       NULL1,              ETSIC,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
493 
494           {FCC2_FCCA,         FCC2,               FCCA,               NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
495           {FCC2_WORLD,        FCC2,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
496           {FCC2_ETSIC,        FCC2,               ETSIC,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
497           {FCC3_FCCA,         FCC3,               FCCA,               NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
498           {FCC3_WORLD,        FCC3,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
499           {FCC4_FCCA,         FCC4,               FCCA,               DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
500           {FCC5_FCCB,         FCC5,               FCCB,               NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
501 
502           {ETSI1_WORLD,       ETSI1,              WORLD,              DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
503           {ETSI2_WORLD,       ETSI2,              WORLD,              DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
504           {ETSI3_WORLD,       ETSI3,              WORLD,              DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
505           {ETSI4_WORLD,       ETSI4,              WORLD,              DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
506           {ETSI5_WORLD,       ETSI5,              WORLD,              DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
507           {ETSI6_WORLD,       ETSI6,              WORLD,              DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
508 
509           {ETSI3_ETSIA,       ETSI3,              WORLD,              DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
510           {FRANCE_RES,        ETSI3,              WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
511 
512           {FCC1_WORLD,        FCC1,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
513           {FCC1_FCCA,         FCC1,               FCCA,               NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
514           {APL1_WORLD,        APL1,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
515           {APL2_WORLD,        APL2,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
516           {APL3_WORLD,        APL3,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
517           {APL4_WORLD,        APL4,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
518           {APL5_WORLD,        APL5,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
519           {APL6_WORLD,        APL6,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
520           {APL8_WORLD,        APL8,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
521           {APL9_WORLD,        APL9,               WORLD,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
522 
523           {APL3_FCCA,         APL3,               FCCA,               NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
524           {APL1_ETSIC,        APL1,               ETSIC,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
525           {APL2_ETSIC,        APL2,               ETSIC,              NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
526           {APL2_APLD,         APL2,               APLD,               NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
527 
528           {MKK1_MKKA,         MKK1,               MKKA,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN },
529           {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 },
530           {MKK1_FCCA,         MKK1,               FCCA,               DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 },
531           {MKK1_MKKA1,        MKK1,               MKKA,               DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 },
532           {MKK1_MKKA2,        MKK1,               MKKA,               DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 },
533           {MKK1_MKKC,         MKK1,               MKKC,               DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 },
534 
535           /* MKK2 */
536           {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 },
537 
538           /* MKK3 */
539           {MKK3_MKKA,         MKK3,     MKKA,     DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, 0 },
540           {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 },
541           {MKK3_MKKA1,        MKK3,     MKKA,     DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, 0 },
542           {MKK3_MKKA2,MKK3,             MKKA,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 },
543           {MKK3_MKKC,         MKK3,               MKKC,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 },
544           {MKK3_FCCA,         MKK3,     FCCA,     DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, 0 },
545 
546           /* MKK4 */
547           {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 },
548           {MKK4_MKKA1,        MKK4,     MKKA,     DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, 0 },
549           {MKK4_MKKA2,        MKK4,               MKKA,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 },
550           {MKK4_MKKC,         MKK4,               MKKC,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 },
551           {MKK4_FCCA,         MKK4,     FCCA,     DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, 0 },
552 
553           /* MKK5 */
554           {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 },
555           {MKK5_MKKA2,MKK5,             MKKA,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 },
556           {MKK5_MKKC,         MKK5,               MKKC,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 },
557 
558           /* MKK6 */
559           {MKK6_MKKB,         MKK6,               MKKA,               DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16 },
560           {MKK6_MKKA2,        MKK6,               MKKA,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 },
561           {MKK6_MKKC,         MKK6,               MKKC,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 },
562 
563           /* MKK7 */
564           {MKK7_MKKB,         MKK7,               MKKA,               DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19 },
565           {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 },
566           {MKK7_MKKC,         MKK7,               MKKC,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 },
567 
568           /* MKK8 */
569           {MKK8_MKKB,         MKK8,               MKKA,               DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22 },
570           {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 },
571           {MKK8_MKKC,         MKK8,               MKKC,               DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 },
572 
573           {MKK9_MKKA,         MKK9,     MKKA,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, 0 },
574           {MKK10_MKKA,        MKK10,    MKKA,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, 0 },
575 
576                     /* These are super domains */
577           {WOR0_WORLD,        WOR0_WORLD,         WOR0_WORLD,         NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
578           {WOR1_WORLD,        WOR1_WORLD,         WOR1_WORLD,         DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
579           {WOR2_WORLD,        WOR2_WORLD,         WOR2_WORLD,         DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
580           {WOR3_WORLD,        WOR3_WORLD,         WOR3_WORLD,         NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
581           {WOR4_WORLD,        WOR4_WORLD,         WOR4_WORLD,         DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
582           {WOR5_ETSIC,        WOR5_ETSIC,         WOR5_ETSIC,         DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
583           {WOR01_WORLD,       WOR01_WORLD,        WOR01_WORLD,        NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
584           {WOR02_WORLD,       WOR02_WORLD,        WOR02_WORLD,        NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
585           {EU1_WORLD,         EU1_WORLD,          EU1_WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
586           {WOR9_WORLD,        WOR9_WORLD,         WOR9_WORLD,         DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
587           {WORA_WORLD,        WORA_WORLD,         WORA_WORLD,         DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
588           {SR9_WORLD,         NULL1,              SR9_WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_SR9 },
589           {XR9_WORLD,         NULL1,              XR9_WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_XR9 },
590           {GZ901_WORLD,       NULL1,              GZ901_WORLD,        NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_GZ901 },
591 };
592 
593 /*
594  * The following tables are the master list for all different freqeuncy
595  * bands with the complete matrix of all possible flags and settings
596  * for each band if it is used in ANY reg domain.
597  */
598 
599 #define DEF_REGDMN            FCC1_FCCA
600 #define   DEF_DMN_5           FCC1
601 #define   DEF_DMN_2           FCCA
602 #define   COUNTRY_ERD_FLAG        0x8000
603 #define WORLDWIDE_ROAMING_FLAG  0x4000
604 #define   SUPER_DOMAIN_MASK   0x0fff
605 #define   COUNTRY_CODE_MASK   0x3fff
606 
607 #define   YES       AH_TRUE
608 #define   NO        AH_FALSE
609 
610 typedef struct {
611           HAL_CTRY_CODE                 countryCode;
612           HAL_REG_DOMAIN                regDmnEnum;
613           HAL_BOOL            allow11g;
614           HAL_BOOL            allow11aTurbo;
615           HAL_BOOL            allow11gTurbo;
616           HAL_BOOL            allow11ng20;
617           HAL_BOOL            allow11ng40;
618           HAL_BOOL            allow11na20;
619           HAL_BOOL            allow11na40;
620           uint16_t            outdoorChanStart;
621 } COUNTRY_CODE_TO_ENUM_RD;
622 
623 static COUNTRY_CODE_TO_ENUM_RD allCountries[] = {
624     {CTRY_DEBUG,       NO_ENUMRD,       YES, YES, YES, YES,YES, YES,YES, 7000 },
625     {CTRY_DEFAULT,     DEF_REGDMN,      YES, YES, YES, YES,YES, YES,YES, 7000 },
626     {CTRY_ALBANIA,     NULL1_WORLD,     YES,  NO, YES, YES, NO,  NO, NO, 7000 },
627     {CTRY_ALGERIA,     NULL1_WORLD,     YES,  NO, YES, YES, NO,  NO, NO, 7000 },
628     {CTRY_ARGENTINA,   APL3_WORLD,       NO,  NO,  NO,  NO, NO,  NO, NO, 7000 },
629     {CTRY_ARMENIA,     ETSI4_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
630     {CTRY_AUSTRALIA,   FCC2_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
631     {CTRY_AUSTRIA,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
632     {CTRY_AZERBAIJAN,  ETSI4_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
633     {CTRY_BAHRAIN,     APL6_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
634     {CTRY_BELARUS,     NULL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
635     {CTRY_BELGIUM,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
636     {CTRY_BELIZE,      APL1_ETSIC,      YES, YES, YES, YES,YES, YES,YES, 7000 },
637     {CTRY_BOLIVIA,     APL1_ETSIC,      YES, YES, YES, YES,YES, YES,YES, 7000 },
638     {CTRY_BRAZIL,      FCC3_WORLD,      YES,  NO,  NO, YES, NO, YES, NO, 7000 },
639     {CTRY_BRUNEI_DARUSSALAM,APL1_WORLD, YES, YES, YES, YES,YES, YES,YES, 7000 },
640     {CTRY_BULGARIA,    ETSI6_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
641     {CTRY_CANADA,      FCC2_FCCA,       YES, YES, YES, YES,YES, YES,YES, 7000 },
642     {CTRY_CHILE,       APL6_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
643     {CTRY_CHINA,       APL1_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
644     {CTRY_COLOMBIA,    FCC1_FCCA,       YES,  NO, YES, YES,YES, YES, NO, 7000 },
645     {CTRY_COSTA_RICA,  NULL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
646     {CTRY_CROATIA,     ETSI3_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
647     {CTRY_CYPRUS,      ETSI1_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
648     {CTRY_CZECH,       ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
649     {CTRY_DENMARK,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
650     {CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA, YES, YES, YES, YES,YES, YES,YES, 7000 },
651     {CTRY_ECUADOR,     NULL1_WORLD,     NO,   NO,  NO,  NO, NO,  NO, NO, 7000 },
652     {CTRY_EGYPT,       ETSI3_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
653     {CTRY_EL_SALVADOR, NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
654     {CTRY_ESTONIA,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
655     {CTRY_FINLAND,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
656     {CTRY_FRANCE,      ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
657     {CTRY_FRANCE2,     ETSI3_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
658     {CTRY_GEORGIA,     ETSI4_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
659     {CTRY_GERMANY,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
660     {CTRY_GREECE,      ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
661     {CTRY_GUATEMALA,   FCC1_FCCA,       YES, YES, YES, YES,YES, YES,YES, 7000 },
662     {CTRY_GZ901,       GZ901_WORLD,     YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
663     {CTRY_HONDURAS,    NULL1_WORLD,     YES, NO,  YES, YES,YES, YES, NO, 7000 },
664     {CTRY_HONG_KONG,   FCC2_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
665     {CTRY_HUNGARY,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
666     {CTRY_ICELAND,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
667     {CTRY_INDIA,       APL6_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
668     {CTRY_INDONESIA,   APL1_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
669     {CTRY_IRAN,        APL1_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
670     {CTRY_IRELAND,     ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
671     {CTRY_ISRAEL,      NULL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
672     {CTRY_ITALY,       ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
673     {CTRY_JAPAN,       MKK1_MKKA,       YES,  NO,  NO, YES, NO, YES, NO, 7000 },
674     {CTRY_JAPAN1,      MKK1_MKKB,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
675     {CTRY_JAPAN2,      MKK1_FCCA,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
676     {CTRY_JAPAN3,      MKK2_MKKA,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
677     {CTRY_JAPAN4,      MKK1_MKKA1,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
678     {CTRY_JAPAN5,      MKK1_MKKA2,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
679     {CTRY_JAPAN6,      MKK1_MKKC,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
680 
681     {CTRY_JAPAN7,      MKK3_MKKB,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
682     {CTRY_JAPAN8,      MKK3_MKKA2,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
683     {CTRY_JAPAN9,      MKK3_MKKC,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
684 
685     {CTRY_JAPAN10,     MKK4_MKKB,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
686     {CTRY_JAPAN11,     MKK4_MKKA2,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
687     {CTRY_JAPAN12,     MKK4_MKKC,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
688 
689     {CTRY_JAPAN13,     MKK5_MKKB,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
690     {CTRY_JAPAN14,     MKK5_MKKA2,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
691     {CTRY_JAPAN15,     MKK5_MKKC,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
692 
693     {CTRY_JAPAN16,     MKK6_MKKB,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
694     {CTRY_JAPAN17,     MKK6_MKKA2,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
695     {CTRY_JAPAN18,     MKK6_MKKC,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
696 
697     {CTRY_JAPAN19,     MKK7_MKKB,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
698     {CTRY_JAPAN20,     MKK7_MKKA2,      YES,  NO,  NO, YES, NO, YES, NO, 7000 },
699     {CTRY_JAPAN21,     MKK7_MKKC,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
700 
701     {CTRY_JAPAN22,     MKK8_MKKB,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
702     {CTRY_JAPAN23,     MKK8_MKKA2,      YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
703     {CTRY_JAPAN24,     MKK8_MKKC,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
704 
705     {CTRY_JORDAN,      APL4_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
706     {CTRY_KAZAKHSTAN,  NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
707     {CTRY_KOREA_NORTH, APL2_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
708     {CTRY_KOREA_ROC,   APL2_WORLD,      YES,  NO,  NO, YES, NO, YES, NO, 7000 },
709     {CTRY_KOREA_ROC2,  APL2_WORLD,      YES,  NO,  NO, YES, NO, YES, NO, 7000 },
710     {CTRY_KOREA_ROC3,  APL9_WORLD,      YES,  NO,  NO, YES, NO, YES, NO, 7000 },
711     {CTRY_KUWAIT,      NULL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
712     {CTRY_LATVIA,      ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
713     {CTRY_LEBANON,     NULL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
714     {CTRY_LIECHTENSTEIN,ETSI1_WORLD,    YES,  NO, YES, YES,YES, YES,YES, 7000 },
715     {CTRY_LITHUANIA,   ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
716     {CTRY_LUXEMBOURG,  ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
717     {CTRY_MACAU,       FCC2_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
718     {CTRY_MACEDONIA,   NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
719     {CTRY_MALAYSIA,    APL8_WORLD,      YES,  NO,  NO, YES, NO, YES, NO, 7000 },
720     {CTRY_MALTA,       ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
721     {CTRY_MEXICO,      FCC1_FCCA,       YES, YES, YES, YES,YES, YES,YES, 7000 },
722     {CTRY_MONACO,      ETSI4_WORLD,     YES, YES, YES, YES,YES, YES,YES, 7000 },
723     {CTRY_MOROCCO,     NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
724     {CTRY_NETHERLANDS, ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
725     {CTRY_NEW_ZEALAND, FCC2_ETSIC,      YES,  NO, YES, YES,YES, YES,YES, 7000 },
726     {CTRY_NORWAY,      ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
727     {CTRY_OMAN,        APL6_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
728     {CTRY_PAKISTAN,    NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
729     {CTRY_PANAMA,      FCC1_FCCA,       YES, YES, YES, YES,YES, YES,YES, 7000 },
730     {CTRY_PERU,        APL1_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
731     {CTRY_PHILIPPINES, FCC3_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
732     {CTRY_POLAND,      ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
733     {CTRY_PORTUGAL,    ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
734     {CTRY_PUERTO_RICO, FCC1_FCCA,       YES, YES, YES, YES,YES, YES,YES, 7000 },
735     {CTRY_QATAR,       NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
736     {CTRY_ROMANIA,     NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
737     {CTRY_RUSSIA,      NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
738     {CTRY_SAUDI_ARABIA,FCC2_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
739     {CTRY_SINGAPORE,   APL6_WORLD,      YES, YES, YES, YES,YES, YES,YES, 7000 },
740     {CTRY_SLOVAKIA,    ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
741     {CTRY_SLOVENIA,    ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
742     {CTRY_SOUTH_AFRICA,FCC3_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
743     {CTRY_SPAIN,       ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
744     {CTRY_SR9,         SR9_WORLD,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
745     {CTRY_SWEDEN,      ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
746     {CTRY_SWITZERLAND, ETSI1_WORLD,     YES,  NO, YES, YES,YES, YES,YES, 7000 },
747     {CTRY_SYRIA,       NULL1_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
748     {CTRY_TAIWAN,      APL3_FCCA,       YES, YES, YES, YES,YES, YES,YES, 7000 },
749     {CTRY_THAILAND,    NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
750     {CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD,YES,  NO, YES, YES,YES, YES, NO, 7000 },
751     {CTRY_TUNISIA,     ETSI3_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
752     {CTRY_TURKEY,      ETSI3_WORLD,     YES,  NO, YES, YES,YES, YES, NO, 7000 },
753     {CTRY_UKRAINE,     NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
754     {CTRY_UAE,         NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
755     {CTRY_UNITED_KINGDOM, ETSI1_WORLD,  YES,  NO, YES, YES,YES, YES, NO, 7000 },
756     {CTRY_UNITED_STATES, FCC1_FCCA,     YES, YES, YES, YES,YES, YES,YES, 5825 },
757     {CTRY_UNITED_STATES_FCC49,FCC4_FCCA,YES, YES, YES, YES,YES, YES,YES, 7000 },
758     {CTRY_URUGUAY,     FCC1_WORLD,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
759     {CTRY_UZBEKISTAN,  FCC3_FCCA,       YES, YES, YES, YES,YES, YES,YES, 7000 },
760     {CTRY_VENEZUELA,   APL2_ETSIC,      YES,  NO, YES, YES,YES, YES, NO, 7000 },
761     {CTRY_VIET_NAM,    NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
762     {CTRY_XR9,         XR9_WORLD,       YES,  NO,  NO,  NO, NO,  NO, NO, 7000 },
763     {CTRY_YEMEN,       NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 },
764     {CTRY_ZIMBABWE,    NULL1_WORLD,     YES,  NO, YES, YES,YES,  NO, NO, 7000 }
765 };
766 
767 /* Bit masks for DFS per regdomain */
768 enum {
769           NO_DFS   = 0x0000000000000000ULL,       /* NB: must be zero */
770           DFS_FCC3 = 0x0000000000000001ULL,
771           DFS_ETSI = 0x0000000000000002ULL,
772           DFS_MKK4 = 0x0000000000000004ULL,
773 };
774 
775 #define   AFTER(x)  ((x)+1)
776 
777 /*
778  * Frequency band collections are defined using bitmasks.  Each bit
779  * in a mask is the index of an entry in one of the following tables.
780  * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit
781  * vectors must be enlarged or the tables split somehow (e.g. split
782  * 1/2 and 1/4 rate channels into a separate table).
783  *
784  * Beware of ordering; the indices are defined relative to the preceding
785  * entry so if things get off there will be confusion.  A good way to
786  * check the indices is to collect them in a switch statement in a stub
787  * function so the compiler checks for duplicates.
788  */
789 
790 typedef struct {
791           uint16_t  lowChannel;         /* Low channel center in MHz */
792           uint16_t  highChannel;        /* High Channel center in MHz */
793           uint8_t             powerDfs; /* Max power (dBm) for channel
794                                                      range when using DFS */
795           uint8_t             antennaMax;         /* Max allowed antenna gain */
796           uint8_t             channelBW;          /* Bandwidth of the channel */
797           uint8_t             channelSep;         /* Channel separation within
798                                                      the band */
799           uint64_t  useDfs;             /* Use DFS in the RegDomain
800                                                      if corresponding bit is set */
801           uint64_t  usePassScan;        /* Use Passive Scan in the RegDomain
802                                                      if corresponding bit is set */
803           uint8_t             regClassId;         /* Regulatory class id */
804 } REG_DMN_FREQ_BAND;
805 
806 /*
807  * 5GHz 11A channel tags
808  */
809 static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = {
810           { 4915, 4925, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2, 16 },
811 #define   F1_4915_4925        0
812           { 4935, 4945, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2, 16 },
813 #define   F1_4935_4945        AFTER(F1_4915_4925)
814           { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7 },
815 #define   F1_4920_4980        AFTER(F1_4935_4945)
816           { 4942, 4987, 27, 6,  5,  5, NO_DFS, PSCAN_FCC, 0 },
817 #define   F1_4942_4987        AFTER(F1_4920_4980)
818           { 4945, 4985, 30, 6, 10,  5, NO_DFS, PSCAN_FCC, 0 },
819 #define   F1_4945_4985        AFTER(F1_4942_4987)
820           { 4950, 4980, 33, 6, 20,  5, NO_DFS, PSCAN_FCC, 0 },
821 #define   F1_4950_4980        AFTER(F1_4945_4985)
822           { 5035, 5040, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2, 12 },
823 #define   F1_5035_5040        AFTER(F1_4950_4980)
824           { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2 },
825 #define   F1_5040_5080        AFTER(F1_5035_5040)
826           { 5055, 5055, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2, 12 },
827 #define   F1_5055_5055        AFTER(F1_5040_5080)
828 
829           { 5120, 5240, 5,  6, 20, 20, NO_DFS, NO_PSCAN, 0 },
830 #define   F1_5120_5240        AFTER(F1_5055_5055)
831           { 5120, 5240, 5,  6, 10, 10, NO_DFS, NO_PSCAN, 0 },
832 #define   F2_5120_5240        AFTER(F1_5120_5240)
833           { 5120, 5240, 5,  6,  5,  5, NO_DFS, NO_PSCAN, 0 },
834 #define   F3_5120_5240        AFTER(F2_5120_5240)
835 
836           { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 },
837 #define   F1_5170_5230        AFTER(F3_5120_5240)
838           { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 },
839 #define   F2_5170_5230        AFTER(F1_5170_5230)
840 
841           { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 },
842 #define   F1_5180_5240        AFTER(F2_5170_5230)
843           { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC, 1 },
844 #define   F2_5180_5240        AFTER(F1_5180_5240)
845           { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 },
846 #define   F3_5180_5240        AFTER(F2_5180_5240)
847           { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 },
848 #define   F4_5180_5240        AFTER(F3_5180_5240)
849           { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0 },
850 #define   F5_5180_5240        AFTER(F4_5180_5240)
851           { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0 },
852 #define   F6_5180_5240        AFTER(F5_5180_5240)
853           { 5180, 5240, 17, 6, 20, 10, NO_DFS, PSCAN_FCC, 1 },
854 #define   F7_5180_5240        AFTER(F6_5180_5240)
855           { 5180, 5240, 17, 6, 20,  5, NO_DFS, PSCAN_FCC, 1 },
856 #define   F8_5180_5240        AFTER(F7_5180_5240)
857 
858           { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 },
859 #define   F1_5180_5320        AFTER(F8_5180_5240)
860 
861           { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0 },
862 #define   F1_5240_5280        AFTER(F1_5180_5320)
863 
864           { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 },
865 #define   F1_5260_5280        AFTER(F1_5240_5280)
866 
867           { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 },
868 #define   F1_5260_5320        AFTER(F1_5260_5280)
869 
870           { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 , 0 },
871 #define   F2_5260_5320        AFTER(F1_5260_5320)
872 
873           { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 },
874 #define   F3_5260_5320        AFTER(F2_5260_5320)
875           { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 },
876 #define   F4_5260_5320        AFTER(F3_5260_5320)
877           { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 },
878 #define   F5_5260_5320        AFTER(F4_5260_5320)
879           { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
880 #define   F6_5260_5320        AFTER(F5_5260_5320)
881           { 5260, 5320, 23, 6, 20, 10, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 },
882 #define   F7_5260_5320        AFTER(F6_5260_5320)
883           { 5260, 5320, 23, 6, 20,  5, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 },
884 #define   F8_5260_5320        AFTER(F7_5260_5320)
885 
886           { 5260, 5700, 5,  6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 },
887 #define   F1_5260_5700        AFTER(F8_5260_5320)
888           { 5260, 5700, 5,  6, 10, 10, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 },
889 #define   F2_5260_5700        AFTER(F1_5260_5700)
890           { 5260, 5700, 5,  6,  5,  5, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 },
891 #define   F3_5260_5700        AFTER(F2_5260_5700)
892 
893           { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0 },
894 #define   F1_5280_5320        AFTER(F3_5260_5700)
895 
896           { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 },
897 #define   F1_5500_5620        AFTER(F1_5280_5320)
898 
899           { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4 },
900 #define   F1_5500_5700        AFTER(F1_5500_5620)
901           { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 },
902 #define   F2_5500_5700        AFTER(F1_5500_5700)
903           { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 },
904 #define   F3_5500_5700        AFTER(F2_5500_5700)
905           { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC, 0 },
906 #define   F4_5500_5700        AFTER(F3_5500_5700)
907 
908           { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
909 #define   F1_5745_5805        AFTER(F4_5500_5700)
910           { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 },
911 #define   F2_5745_5805        AFTER(F1_5745_5805)
912           { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 },
913 #define   F3_5745_5805        AFTER(F2_5745_5805)
914           { 5745, 5825, 5,  6, 20, 20, NO_DFS, NO_PSCAN, 0 },
915 #define   F1_5745_5825        AFTER(F3_5745_5805)
916           { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
917 #define   F2_5745_5825        AFTER(F1_5745_5825)
918           { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
919 #define   F3_5745_5825        AFTER(F2_5745_5825)
920           { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 },
921 #define   F4_5745_5825        AFTER(F3_5745_5825)
922           { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3 },
923 #define   F5_5745_5825        AFTER(F4_5745_5825)
924           { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 },
925 #define   F6_5745_5825        AFTER(F5_5745_5825)
926           { 5745, 5825, 5,  6, 10, 10, NO_DFS, NO_PSCAN, 0 },
927 #define   F7_5745_5825        AFTER(F6_5745_5825)
928           { 5745, 5825, 5,  6,  5,  5, NO_DFS, NO_PSCAN, 0 },
929 #define   F8_5745_5825        AFTER(F7_5745_5825)
930           { 5745, 5825, 30, 6, 20, 10, NO_DFS, NO_PSCAN, 3 },
931 #define   F9_5745_5825        AFTER(F8_5745_5825)
932           { 5745, 5825, 30, 6, 20,  5, NO_DFS, NO_PSCAN, 3 },
933 #define   F10_5745_5825       AFTER(F9_5745_5825)
934 
935           /*
936            * Below are the world roaming channels
937            * All WWR domains have no power limit, instead use the card's CTL
938            * or max power settings.
939            */
940           { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 },
941 #define   W1_4920_4980        AFTER(F10_5745_5825)
942           { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 },
943 #define   W1_5040_5080        AFTER(W1_4920_4980)
944           { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 },
945 #define   W1_5170_5230        AFTER(W1_5040_5080)
946           { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 },
947 #define   W1_5180_5240        AFTER(W1_5170_5230)
948           { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 },
949 #define   W1_5260_5320        AFTER(W1_5180_5240)
950           { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 },
951 #define   W1_5745_5825        AFTER(W1_5260_5320)
952           { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 },
953 #define   W1_5500_5700        AFTER(W1_5745_5825)
954           { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN,  0 },
955 #define   W2_5260_5320        AFTER(W1_5500_5700)
956           { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN,  0 },
957 #define   W2_5180_5240        AFTER(W2_5260_5320)
958           { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 },
959 #define   W2_5825_5825        AFTER(W2_5180_5240)
960 };
961 
962 /*
963  * 5GHz Turbo (dynamic & static) tags
964  */
965 static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = {
966           { 5130, 5210, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
967 #define   T1_5130_5210        0
968           { 5250, 5330, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0},
969 #define   T1_5250_5330        AFTER(T1_5130_5210)
970           { 5370, 5490, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
971 #define   T1_5370_5490        AFTER(T1_5250_5330)
972           { 5530, 5650, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0},
973 #define   T1_5530_5650        AFTER(T1_5370_5490)
974 
975           { 5150, 5190, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
976 #define   T1_5150_5190        AFTER(T1_5530_5650)
977           { 5230, 5310, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0},
978 #define   T1_5230_5310        AFTER(T1_5150_5190)
979           { 5350, 5470, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
980 #define   T1_5350_5470        AFTER(T1_5230_5310)
981           { 5510, 5670, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0},
982 #define   T1_5510_5670        AFTER(T1_5350_5470)
983 
984           { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
985 #define   T1_5200_5240        AFTER(T1_5510_5670)
986           { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
987 #define   T2_5200_5240        AFTER(T1_5200_5240)
988           { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
989 #define   T1_5210_5210        AFTER(T2_5200_5240)
990           { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0},
991 #define   T2_5210_5210        AFTER(T1_5210_5210)
992 
993           { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
994 #define   T1_5280_5280        AFTER(T2_5210_5210)
995           { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
996 #define   T2_5280_5280        AFTER(T1_5280_5280)
997           { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
998 #define   T1_5250_5250        AFTER(T2_5280_5280)
999           { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
1000 #define   T1_5290_5290        AFTER(T1_5250_5250)
1001           { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
1002 #define   T1_5250_5290        AFTER(T1_5290_5290)
1003           { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
1004 #define   T2_5250_5290        AFTER(T1_5250_5290)
1005 
1006           { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0},
1007 #define   T1_5540_5660        AFTER(T2_5250_5290)
1008           { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0},
1009 #define   T1_5760_5800        AFTER(T1_5540_5660)
1010           { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
1011 #define   T2_5760_5800        AFTER(T1_5760_5800)
1012 
1013           { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
1014 #define   T1_5765_5805        AFTER(T2_5760_5800)
1015 
1016           /*
1017            * Below are the WWR frequencies
1018            */
1019           { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
1020 #define   WT1_5210_5250       AFTER(T1_5765_5805)
1021           { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
1022 #define   WT1_5290_5290       AFTER(WT1_5210_5250)
1023           { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
1024 #define   WT1_5540_5660       AFTER(WT1_5290_5290)
1025           { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR, 0},
1026 #define   WT1_5760_5800       AFTER(WT1_5540_5660)
1027 };
1028 
1029 /*
1030  * 2GHz 11b channel tags
1031  */
1032 static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = {
1033           { 2312, 2372, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
1034 #define   F1_2312_2372        0
1035           { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1036 #define   F2_2312_2372        AFTER(F1_2312_2372)
1037 
1038           { 2412, 2472, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
1039 #define   F1_2412_2472        AFTER(F2_2312_2372)
1040           { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0},
1041 #define   F2_2412_2472        AFTER(F1_2412_2472)
1042           { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1043 #define   F3_2412_2472        AFTER(F2_2412_2472)
1044 
1045           { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
1046 #define   F1_2412_2462        AFTER(F3_2412_2472)
1047           { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0},
1048 #define   F2_2412_2462        AFTER(F1_2412_2462)
1049 
1050           { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1051 #define   F1_2432_2442        AFTER(F2_2412_2462)
1052 
1053           { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1054 #define   F1_2457_2472        AFTER(F1_2432_2442)
1055 
1056           { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0},
1057 #define   F1_2467_2472        AFTER(F1_2457_2472)
1058 
1059           { 2484, 2484, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
1060 #define   F1_2484_2484        AFTER(F1_2467_2472)
1061           { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0},
1062 #define   F2_2484_2484        AFTER(F1_2484_2484)
1063 
1064           { 2512, 2732, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
1065 #define   F1_2512_2732        AFTER(F2_2484_2484)
1066 
1067           /*
1068            * WWR have powers opened up to 20dBm.
1069            * Limits should often come from CTL/Max powers
1070            */
1071           { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1072 #define   W1_2312_2372        AFTER(F1_2512_2732)
1073           { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1074 #define   W1_2412_2412        AFTER(W1_2312_2372)
1075           { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1076 #define   W1_2417_2432        AFTER(W1_2412_2412)
1077           { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1078 #define   W1_2437_2442        AFTER(W1_2417_2432)
1079           { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1080 #define   W1_2447_2457        AFTER(W1_2437_2442)
1081           { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1082 #define   W1_2462_2462        AFTER(W1_2447_2457)
1083           { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
1084 #define   W1_2467_2467        AFTER(W1_2462_2462)
1085           { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
1086 #define   W2_2467_2467        AFTER(W1_2467_2467)
1087           { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
1088 #define   W1_2472_2472        AFTER(W2_2467_2467)
1089           { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
1090 #define   W2_2472_2472        AFTER(W1_2472_2472)
1091           { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
1092 #define   W1_2484_2484        AFTER(W2_2472_2472)
1093           { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
1094 #define   W2_2484_2484        AFTER(W1_2484_2484)
1095 };
1096 
1097 /*
1098  * 2GHz 11g channel tags
1099  */
1100 static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = {
1101           { 2312, 2372, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
1102 #define   G1_2312_2372        0
1103           { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1104 #define   G2_2312_2372        AFTER(G1_2312_2372)
1105           { 2312, 2372, 5,  6, 10, 5, NO_DFS, NO_PSCAN, 0},
1106 #define   G3_2312_2372        AFTER(G2_2312_2372)
1107           { 2312, 2372, 5,  6,  5, 5, NO_DFS, NO_PSCAN, 0},
1108 #define   G4_2312_2372        AFTER(G3_2312_2372)
1109 
1110           { 2412, 2472, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
1111 #define   G1_2412_2472        AFTER(G4_2312_2372)
1112           { 2412, 2472, 20, 0, 20, 5,  NO_DFS, PSCAN_MKKA_G, 0},
1113 #define   G2_2412_2472        AFTER(G1_2412_2472)
1114           { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1115 #define   G3_2412_2472        AFTER(G2_2412_2472)
1116           { 2412, 2472, 5,  6, 10, 5, NO_DFS, NO_PSCAN, 0},
1117 #define   G4_2412_2472        AFTER(G3_2412_2472)
1118           { 2412, 2472, 5,  6,  5, 5, NO_DFS, NO_PSCAN, 0},
1119 #define   G5_2412_2472        AFTER(G4_2412_2472)
1120 
1121           { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
1122 #define   G1_2412_2462        AFTER(G5_2412_2472)
1123           { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0},
1124 #define   G2_2412_2462        AFTER(G1_2412_2462)
1125           { 2412, 2462, 27, 6, 10, 5, NO_DFS, NO_PSCAN, 0},
1126 #define   G3_2412_2462        AFTER(G2_2412_2462)
1127           { 2412, 2462, 27, 6,  5, 5, NO_DFS, NO_PSCAN, 0},
1128 #define   G4_2412_2462        AFTER(G3_2412_2462)
1129 
1130           { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1131 #define   G1_2432_2442        AFTER(G4_2412_2462)
1132 
1133           { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1134 #define   G1_2457_2472        AFTER(G1_2432_2442)
1135 
1136           { 2512, 2732, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0},
1137 #define   G1_2512_2732        AFTER(G1_2457_2472)
1138           { 2512, 2732, 5,  6, 10, 5, NO_DFS, NO_PSCAN, 0},
1139 #define   G2_2512_2732        AFTER(G1_2512_2732)
1140           { 2512, 2732, 5,  6,  5, 5, NO_DFS, NO_PSCAN, 0},
1141 #define   G3_2512_2732        AFTER(G2_2512_2732)
1142 
1143           { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0 },
1144 #define   G1_2467_2472        AFTER(G3_2512_2732)
1145 
1146           /*
1147            * WWR open up the power to 20dBm
1148            */
1149           { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1150 #define   WG1_2312_2372       AFTER(G1_2467_2472)
1151           { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1152 #define   WG1_2412_2412       AFTER(WG1_2312_2372)
1153           { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1154 #define   WG1_2417_2432       AFTER(WG1_2412_2412)
1155           { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1156 #define   WG1_2437_2442       AFTER(WG1_2417_2432)
1157           { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1158 #define   WG1_2447_2457       AFTER(WG1_2437_2442)
1159           { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
1160 #define   WG1_2462_2462       AFTER(WG1_2447_2457)
1161           { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
1162 #define   WG1_2467_2467       AFTER(WG1_2462_2462)
1163           { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
1164 #define   WG2_2467_2467       AFTER(WG1_2467_2467)
1165           { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
1166 #define   WG1_2472_2472       AFTER(WG2_2467_2467)
1167           { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
1168 #define   WG2_2472_2472       AFTER(WG1_2472_2472)
1169 
1170           /*
1171            * Mapping for 900MHz cards like Ubiquiti SR9 and XR9
1172            * and ZComax GZ-901.
1173            */
1174           { 2422, 2437, 30, 0,  5, 5, NO_DFS, PSCAN_FCC, 0 },
1175 #define   S1_907_922_5        AFTER(WG2_2472_2472)
1176           { 2422, 2437, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 },
1177 #define   S1_907_922_10       AFTER(S1_907_922_5)
1178           { 2427, 2432, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 },
1179 #define   S1_912_917          AFTER(S1_907_922_10)
1180           { 2427, 2442, 30, 0,  5, 5, NO_DFS, PSCAN_FCC, 0 },
1181 #define   S2_907_922_5        AFTER(S1_912_917)
1182           { 2427, 2442, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 },
1183 #define   S2_907_922_10       AFTER(S2_907_922_5)
1184           { 2432, 2437, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 },
1185 #define   S2_912_917          AFTER(S2_907_922_10)
1186           { 2452, 2467, 30, 0,  5, 5, NO_DFS, PSCAN_FCC, 0 },
1187 #define   S1_908_923_5        AFTER(S2_912_917)
1188           { 2457, 2467, 30, 0, 10, 5, NO_DFS, PSCAN_FCC, 0 },
1189 #define   S1_913_918_10       AFTER(S1_908_923_5)
1190           { 2457, 2467, 30, 0, 20, 5, NO_DFS, PSCAN_FCC, 0 },
1191 #define   S1_913_918          AFTER(S1_913_918_10)
1192 };
1193 
1194 /*
1195  * 2GHz Dynamic turbo tags
1196  */
1197 static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = {
1198           { 2312, 2372, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
1199 #define   T1_2312_2372        0
1200           { 2437, 2437, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
1201 #define   T1_2437_2437        AFTER(T1_2312_2372)
1202           { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0},
1203 #define   T2_2437_2437        AFTER(T1_2437_2437)
1204           { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0},
1205 #define   T3_2437_2437        AFTER(T2_2437_2437)
1206           { 2512, 2732, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0},
1207 #define   T1_2512_2732        AFTER(T3_2437_2437)
1208 };
1209 
1210 typedef struct regDomain {
1211           uint16_t regDmnEnum;                    /* value from EnumRd table */
1212           uint8_t conformanceTestLimit;
1213           uint32_t flags;                         /* Requirement flags (AdHoc disallow,
1214                                                      noise floor cal needed, etc) */
1215           uint64_t dfsMask;             /* DFS bitmask for 5Ghz tables */
1216           uint64_t pscan;                         /* Bitmask for passive scan */
1217           chanbmask_t chan11a;                    /* 11a channels */
1218           chanbmask_t chan11a_turbo;    /* 11a static turbo channels */
1219           chanbmask_t chan11a_dyn_turbo;          /* 11a dynamic turbo channels */
1220           chanbmask_t chan11a_half;     /* 11a 1/2 width channels */
1221           chanbmask_t chan11a_quarter;  /* 11a 1/4 width channels */
1222           chanbmask_t chan11b;                    /* 11b channels */
1223           chanbmask_t chan11g;                    /* 11g channels */
1224           chanbmask_t chan11g_turbo;    /* 11g dynamic turbo channels */
1225           chanbmask_t chan11g_half;     /* 11g 1/2 width channels */
1226           chanbmask_t chan11g_quarter;  /* 11g 1/4 width channels */
1227 } REG_DOMAIN;
1228 
1229 static REG_DOMAIN regDomains[] = {
1230 
1231           {.regDmnEnum                  = DEBUG_REG_DMN,
1232            .conformanceTestLimit        = FCC,
1233            .dfsMask           = DFS_FCC3,
1234            .chan11a           = BM3(F1_5120_5240, F1_5260_5700, F1_5745_5825),
1235            .chan11a_half                = BM3(F2_5120_5240, F2_5260_5700, F7_5745_5825),
1236            .chan11a_quarter   = BM3(F3_5120_5240, F3_5260_5700, F8_5745_5825),
1237            .chan11a_turbo               = BM8(T1_5130_5210,
1238                                               T1_5250_5330,
1239                                               T1_5370_5490,
1240                                               T1_5530_5650,
1241                                               T1_5150_5190,
1242                                               T1_5230_5310,
1243                                               T1_5350_5470,
1244                                               T1_5510_5670),
1245            .chan11a_dyn_turbo = BM4(T1_5200_5240,
1246                                               T1_5280_5280,
1247                                               T1_5540_5660,
1248                                               T1_5765_5805),
1249            .chan11b           = BM4(F1_2312_2372,
1250                                               F1_2412_2472,
1251                                               F1_2484_2484,
1252                                               F1_2512_2732),
1253            .chan11g           = BM3(G1_2312_2372, G1_2412_2472, G1_2512_2732),
1254            .chan11g_turbo               = BM3(T1_2312_2372, T1_2437_2437, T1_2512_2732),
1255            .chan11g_half                = BM3(G2_2312_2372, G4_2412_2472, G2_2512_2732),
1256            .chan11g_quarter   = BM3(G3_2312_2372, G5_2412_2472, G3_2512_2732),
1257           },
1258 
1259           {.regDmnEnum                  = APL1,
1260            .conformanceTestLimit        = FCC,
1261            .chan11a           = BM1(F4_5745_5825),
1262           },
1263 
1264           {.regDmnEnum                  = APL2,
1265            .conformanceTestLimit        = FCC,
1266            .chan11a           = BM1(F1_5745_5805),
1267           },
1268 
1269           {.regDmnEnum                  = APL3,
1270            .conformanceTestLimit        = FCC,
1271            .chan11a           = BM2(F1_5280_5320, F2_5745_5805),
1272           },
1273 
1274           {.regDmnEnum                  = APL4,
1275            .conformanceTestLimit        = FCC,
1276            .chan11a           = BM2(F4_5180_5240, F3_5745_5825),
1277           },
1278 
1279           {.regDmnEnum                  = APL5,
1280            .conformanceTestLimit        = FCC,
1281            .chan11a           = BM1(F2_5745_5825),
1282           },
1283 
1284           {.regDmnEnum                  = APL6,
1285            .conformanceTestLimit        = ETSI,
1286            .dfsMask           = DFS_ETSI,
1287            .pscan                       = PSCAN_FCC_T | PSCAN_FCC,
1288            .chan11a           = BM3(F4_5180_5240, F2_5260_5320, F3_5745_5825),
1289            .chan11a_turbo               = BM3(T2_5210_5210, T1_5250_5290, T1_5760_5800),
1290           },
1291 
1292           {.regDmnEnum                  = APL8,
1293            .conformanceTestLimit        = ETSI,
1294            .flags                       = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
1295            .chan11a           = BM2(F6_5260_5320, F4_5745_5825),
1296           },
1297 
1298           {.regDmnEnum                  = APL9,
1299            .conformanceTestLimit        = ETSI,
1300            .dfsMask           = DFS_ETSI,
1301            .pscan                       = PSCAN_ETSI,
1302            .flags                       = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
1303            .chan11a           = BM3(F1_5180_5320, F1_5500_5620, F3_5745_5805),
1304           },
1305 
1306           {.regDmnEnum                  = ETSI1,
1307            .conformanceTestLimit        = ETSI,
1308            .dfsMask           = DFS_ETSI,
1309            .pscan                       = PSCAN_ETSI,
1310            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1311            .chan11a           = BM3(W2_5180_5240, F2_5260_5320, F2_5500_5700),
1312           },
1313 
1314           {.regDmnEnum                  = ETSI2,
1315            .conformanceTestLimit        = ETSI,
1316            .dfsMask           = DFS_ETSI,
1317            .pscan                       = PSCAN_ETSI,
1318            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1319            .chan11a           = BM1(F3_5180_5240),
1320           },
1321 
1322           {.regDmnEnum                  = ETSI3,
1323            .conformanceTestLimit        = ETSI,
1324            .dfsMask           = DFS_ETSI,
1325            .pscan                       = PSCAN_ETSI,
1326            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1327            .chan11a           = BM2(W2_5180_5240, F2_5260_5320),
1328           },
1329 
1330           {.regDmnEnum                  = ETSI4,
1331            .conformanceTestLimit        = ETSI,
1332            .dfsMask           = DFS_ETSI,
1333            .pscan                       = PSCAN_ETSI,
1334            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1335            .chan11a           = BM2(F3_5180_5240, F1_5260_5320),
1336           },
1337 
1338           {.regDmnEnum                  = ETSI5,
1339            .conformanceTestLimit        = ETSI,
1340            .dfsMask           = DFS_ETSI,
1341            .pscan                       = PSCAN_ETSI,
1342            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1343            .chan11a           = BM1(F1_5180_5240),
1344           },
1345 
1346           {.regDmnEnum                  = ETSI6,
1347            .conformanceTestLimit        = ETSI,
1348            .dfsMask           = DFS_ETSI,
1349            .pscan                       = PSCAN_ETSI,
1350            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1351            .chan11a           = BM3(F5_5180_5240, F1_5260_5280, F3_5500_5700),
1352           },
1353 
1354           {.regDmnEnum                  = FCC1,
1355            .conformanceTestLimit        = FCC,
1356            .chan11a           = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825),
1357            .chan11a_turbo               = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800),
1358            .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805),
1359           },
1360 
1361           {.regDmnEnum                  = FCC2,
1362            .conformanceTestLimit        = FCC,
1363            .chan11a           = BM3(F6_5180_5240, F5_5260_5320, F6_5745_5825),
1364            .chan11a_dyn_turbo = BM3(T2_5200_5240, T1_5280_5280, T1_5765_5805),
1365           },
1366 
1367           {.regDmnEnum                  = FCC3,
1368            .conformanceTestLimit        = FCC,
1369            .dfsMask           = DFS_FCC3,
1370            .pscan                       = PSCAN_FCC | PSCAN_FCC_T,
1371            .chan11a           = BM4(F2_5180_5240,
1372                                               F3_5260_5320,
1373                                               F1_5500_5700,
1374                                               F5_5745_5825),
1375            .chan11a_turbo               = BM4(T1_5210_5210,
1376                                               T1_5250_5250,
1377                                               T1_5290_5290,
1378                                               T2_5760_5800),
1379            .chan11a_dyn_turbo = BM3(T1_5200_5240, T2_5280_5280, T1_5540_5660),
1380           },
1381 
1382           {.regDmnEnum                  = FCC4,
1383            .conformanceTestLimit        = FCC,
1384            .dfsMask           = DFS_FCC3,
1385            .pscan                       = PSCAN_FCC | PSCAN_FCC_T,
1386            .chan11a           = BM1(F1_4950_4980),
1387            .chan11a_half                = BM1(F1_4945_4985),
1388            .chan11a_quarter   = BM1(F1_4942_4987),
1389           },
1390 
1391           /* FCC1 w/ 1/2 and 1/4 width channels */
1392           {.regDmnEnum                  = FCC5,
1393            .conformanceTestLimit        = FCC,
1394            .chan11a           = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825),
1395            .chan11a_turbo               = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800),
1396            .chan11a_dyn_turbo = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805),
1397            .chan11a_half                = BM3(F7_5180_5240, F7_5260_5320, F9_5745_5825),
1398            .chan11a_quarter   = BM3(F8_5180_5240, F8_5260_5320,F10_5745_5825),
1399           },
1400 
1401           {.regDmnEnum                  = MKK1,
1402            .conformanceTestLimit        = MKK,
1403            .pscan                       = PSCAN_MKK1,
1404            .flags                       = DISALLOW_ADHOC_11A_TURB,
1405            .chan11a           = BM1(F1_5170_5230),
1406           },
1407 
1408           {.regDmnEnum                  = MKK2,
1409            .conformanceTestLimit        = MKK,
1410            .pscan                       = PSCAN_MKK2,
1411            .flags                       = DISALLOW_ADHOC_11A_TURB,
1412            .chan11a           = BM3(F1_4920_4980, F1_5040_5080, F1_5170_5230),
1413           .chan11a_half                 = BM4(F1_4915_4925,
1414                                               F1_4935_4945,
1415                                               F1_5035_5040,
1416                                               F1_5055_5055),
1417           },
1418 
1419           /* UNI-1 even */
1420           {.regDmnEnum                  = MKK3,
1421            .conformanceTestLimit        = MKK,
1422            .pscan                       = PSCAN_MKK3,
1423            .flags                       = DISALLOW_ADHOC_11A_TURB,
1424            .chan11a           = BM1(F4_5180_5240),
1425           },
1426 
1427           /* UNI-1 even + UNI-2 */
1428           {.regDmnEnum                  = MKK4,
1429            .conformanceTestLimit        = MKK,
1430            .dfsMask           = DFS_MKK4,
1431            .pscan                       = PSCAN_MKK3,
1432            .flags                       = DISALLOW_ADHOC_11A_TURB,
1433            .chan11a           = BM2(F4_5180_5240, F2_5260_5320),
1434           },
1435 
1436           /* UNI-1 even + UNI-2 + mid-band */
1437           {.regDmnEnum                  = MKK5,
1438            .conformanceTestLimit        = MKK,
1439            .dfsMask           = DFS_MKK4,
1440            .pscan                       = PSCAN_MKK3,
1441            .flags                       = DISALLOW_ADHOC_11A_TURB,
1442            .chan11a           = BM3(F4_5180_5240, F2_5260_5320, F4_5500_5700),
1443           },
1444 
1445           /* UNI-1 odd + even */
1446           {.regDmnEnum                  = MKK6,
1447            .conformanceTestLimit        = MKK,
1448            .pscan                       = PSCAN_MKK1,
1449            .flags                       = DISALLOW_ADHOC_11A_TURB,
1450            .chan11a           = BM2(F2_5170_5230, F4_5180_5240),
1451           },
1452 
1453           /* UNI-1 odd + UNI-1 even + UNI-2 */
1454           {.regDmnEnum                  = MKK7,
1455            .conformanceTestLimit        = MKK,
1456            .dfsMask           = DFS_MKK4,
1457            .pscan                       = PSCAN_MKK1 | PSCAN_MKK3,
1458            .flags                       = DISALLOW_ADHOC_11A_TURB,
1459            .chan11a           = BM3(F1_5170_5230, F4_5180_5240, F2_5260_5320),
1460           },
1461 
1462           /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */
1463           {.regDmnEnum                  = MKK8,
1464            .conformanceTestLimit        = MKK,
1465            .dfsMask           = DFS_MKK4,
1466            .pscan                       = PSCAN_MKK1 | PSCAN_MKK3,
1467            .flags                       = DISALLOW_ADHOC_11A_TURB,
1468            .chan11a           = BM4(F1_5170_5230,
1469                                               F4_5180_5240,
1470                                               F2_5260_5320,
1471                                               F4_5500_5700),
1472           },
1473 
1474         /* UNI-1 even + 4.9 GHZ */
1475         {.regDmnEnum                    = MKK9,
1476            .conformanceTestLimit        = MKK,
1477            .pscan                       = PSCAN_MKK3,
1478            .flags                       = DISALLOW_ADHOC_11A_TURB,
1479          .chan11a             = BM7(F1_4915_4925,
1480                                               F1_4935_4945,
1481                                               F1_4920_4980,
1482                                               F1_5035_5040,
1483                                               F1_5055_5055,
1484                                               F1_5040_5080,
1485                                               F4_5180_5240),
1486         },
1487 
1488         /* UNI-1 even + UNI-2 + 4.9 GHZ */
1489         {.regDmnEnum                    = MKK10,
1490            .conformanceTestLimit        = MKK,
1491            .dfsMask           = DFS_MKK4,
1492            .pscan                       = PSCAN_MKK3,
1493            .flags                       = DISALLOW_ADHOC_11A_TURB,
1494          .chan11a             = BM8(F1_4915_4925,
1495                                               F1_4935_4945,
1496                                               F1_4920_4980,
1497                                               F1_5035_5040,
1498                                               F1_5055_5055,
1499                                               F1_5040_5080,
1500                                               F4_5180_5240,
1501                                               F2_5260_5320),
1502         },
1503 
1504           /* Defined here to use when 2G channels are authorised for country K2 */
1505           {.regDmnEnum                  = APLD,
1506            .conformanceTestLimit        = NO_CTL,
1507            .chan11b           = BM2(F2_2312_2372,F2_2412_2472),
1508            .chan11g           = BM2(G2_2312_2372,G2_2412_2472),
1509           },
1510 
1511           {.regDmnEnum                  = ETSIA,
1512            .conformanceTestLimit        = NO_CTL,
1513            .pscan                       = PSCAN_ETSIA,
1514            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1515            .chan11b           = BM1(F1_2457_2472),
1516            .chan11g           = BM1(G1_2457_2472),
1517            .chan11g_turbo               = BM1(T2_2437_2437)
1518           },
1519 
1520           {.regDmnEnum                  = ETSIB,
1521            .conformanceTestLimit        = ETSI,
1522            .pscan                       = PSCAN_ETSIB,
1523            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1524            .chan11b           = BM1(F1_2432_2442),
1525            .chan11g           = BM1(G1_2432_2442),
1526            .chan11g_turbo               = BM1(T2_2437_2437)
1527           },
1528 
1529           {.regDmnEnum                  = ETSIC,
1530            .conformanceTestLimit        = ETSI,
1531            .pscan                       = PSCAN_ETSIC,
1532            .flags                       = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1533            .chan11b           = BM1(F3_2412_2472),
1534            .chan11g           = BM1(G3_2412_2472),
1535            .chan11g_turbo               = BM1(T2_2437_2437)
1536           },
1537 
1538           {.regDmnEnum                  = FCCA,
1539            .conformanceTestLimit        = FCC,
1540            .chan11b           = BM1(F1_2412_2462),
1541            .chan11g           = BM1(G1_2412_2462),
1542            .chan11g_turbo               = BM1(T2_2437_2437),
1543           },
1544 
1545           /* FCCA w/ 1/2 and 1/4 width channels */
1546           {.regDmnEnum                  = FCCB,
1547            .conformanceTestLimit        = FCC,
1548            .chan11b           = BM1(F1_2412_2462),
1549            .chan11g           = BM1(G1_2412_2462),
1550            .chan11g_turbo               = BM1(T2_2437_2437),
1551            .chan11g_half                = BM1(G3_2412_2462),
1552            .chan11g_quarter   = BM1(G4_2412_2462),
1553           },
1554 
1555           {.regDmnEnum                  = MKKA,
1556            .conformanceTestLimit        = MKK,
1557            .pscan                       = PSCAN_MKKA | PSCAN_MKKA_G
1558                                         | PSCAN_MKKA1 | PSCAN_MKKA1_G
1559                                         | PSCAN_MKKA2 | PSCAN_MKKA2_G,
1560            .flags                       = DISALLOW_ADHOC_11A_TURB,
1561            .chan11b           = BM3(F2_2412_2462, F1_2467_2472, F2_2484_2484),
1562            .chan11g           = BM2(G2_2412_2462, G1_2467_2472),
1563            .chan11g_turbo               = BM1(T2_2437_2437)
1564           },
1565 
1566           {.regDmnEnum                  = MKKC,
1567            .conformanceTestLimit        = MKK,
1568            .chan11b           = BM1(F2_2412_2472),
1569            .chan11g           = BM1(G2_2412_2472),
1570            .chan11g_turbo               = BM1(T2_2437_2437)
1571           },
1572 
1573           {.regDmnEnum                  = WORLD,
1574            .conformanceTestLimit        = ETSI,
1575            .chan11b           = BM1(F2_2412_2472),
1576            .chan11g           = BM1(G2_2412_2472),
1577            .chan11g_turbo               = BM1(T2_2437_2437)
1578           },
1579 
1580           {.regDmnEnum                  = WOR0_WORLD,
1581            .conformanceTestLimit        = NO_CTL,
1582            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1583            .pscan                       = PSCAN_WWR,
1584            .flags                       = ADHOC_PER_11D,
1585            .chan11a           = BM5(W1_5260_5320,
1586                                               W1_5180_5240,
1587                                               W1_5170_5230,
1588                                               W1_5745_5825,
1589                                               W1_5500_5700),
1590            .chan11a_turbo               = BM3(WT1_5210_5250,
1591                                               WT1_5290_5290,
1592                                               WT1_5760_5800),
1593            .chan11b           = BM8(W1_2412_2412,
1594                                               W1_2437_2442,
1595                                               W1_2462_2462,
1596                                               W1_2472_2472,
1597                                               W1_2417_2432,
1598                                               W1_2447_2457,
1599                                               W1_2467_2467,
1600                                               W1_2484_2484),
1601            .chan11g           = BM7(WG1_2412_2412,
1602                                               WG1_2437_2442,
1603                                               WG1_2462_2462,
1604                                               WG1_2472_2472,
1605                                               WG1_2417_2432,
1606                                               WG1_2447_2457,
1607                                               WG1_2467_2467),
1608            .chan11g_turbo               = BM1(T3_2437_2437)
1609           },
1610 
1611           {.regDmnEnum                  = WOR01_WORLD,
1612            .conformanceTestLimit        = NO_CTL,
1613            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1614            .pscan                       = PSCAN_WWR,
1615            .flags                       = ADHOC_PER_11D,
1616            .chan11a           = BM5(W1_5260_5320,
1617                                               W1_5180_5240,
1618                                               W1_5170_5230,
1619                                               W1_5745_5825,
1620                                               W1_5500_5700),
1621            .chan11a_turbo               = BM3(WT1_5210_5250,
1622                                               WT1_5290_5290,
1623                                               WT1_5760_5800),
1624            .chan11b           = BM5(W1_2412_2412,
1625                                               W1_2437_2442,
1626                                               W1_2462_2462,
1627                                               W1_2417_2432,
1628                                               W1_2447_2457),
1629            .chan11g           = BM5(WG1_2412_2412,
1630                                               WG1_2437_2442,
1631                                               WG1_2462_2462,
1632                                               WG1_2417_2432,
1633                                               WG1_2447_2457),
1634            .chan11g_turbo               = BM1(T3_2437_2437)},
1635 
1636           {.regDmnEnum                  = WOR02_WORLD,
1637            .conformanceTestLimit        = NO_CTL,
1638            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1639            .pscan                       = PSCAN_WWR,
1640            .flags                       = ADHOC_PER_11D,
1641            .chan11a           = BM5(W1_5260_5320,
1642                                               W1_5180_5240,
1643                                               W1_5170_5230,
1644                                               W1_5745_5825,
1645                                               W1_5500_5700),
1646            .chan11a_turbo               = BM3(WT1_5210_5250,
1647                                               WT1_5290_5290,
1648                                               WT1_5760_5800),
1649            .chan11b           = BM7(W1_2412_2412,
1650                                               W1_2437_2442,
1651                                               W1_2462_2462,
1652                                               W1_2472_2472,
1653                                               W1_2417_2432,
1654                                               W1_2447_2457,
1655                                               W1_2467_2467),
1656            .chan11g           = BM7(WG1_2412_2412,
1657                                               WG1_2437_2442,
1658                                               WG1_2462_2462,
1659                                               WG1_2472_2472,
1660                                               WG1_2417_2432,
1661                                               WG1_2447_2457,
1662                                               WG1_2467_2467),
1663            .chan11g_turbo               = BM1(T3_2437_2437)},
1664 
1665           {.regDmnEnum                  = EU1_WORLD,
1666            .conformanceTestLimit        = NO_CTL,
1667            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1668            .pscan                       = PSCAN_WWR,
1669            .flags                       = ADHOC_PER_11D,
1670            .chan11a           = BM5(W1_5260_5320,
1671                                               W1_5180_5240,
1672                                               W1_5170_5230,
1673                                               W1_5745_5825,
1674                                               W1_5500_5700),
1675            .chan11a_turbo               = BM3(WT1_5210_5250,
1676                                               WT1_5290_5290,
1677                                               WT1_5760_5800),
1678            .chan11b           = BM7(W1_2412_2412,
1679                                               W1_2437_2442,
1680                                               W1_2462_2462,
1681                                               W2_2472_2472,
1682                                               W1_2417_2432,
1683                                               W1_2447_2457,
1684                                               W2_2467_2467),
1685            .chan11g           = BM7(WG1_2412_2412,
1686                                               WG1_2437_2442,
1687                                               WG1_2462_2462,
1688                                               WG2_2472_2472,
1689                                               WG1_2417_2432,
1690                                               WG1_2447_2457,
1691                                               WG2_2467_2467),
1692            .chan11g_turbo               = BM1(T3_2437_2437)},
1693 
1694           {.regDmnEnum                  = WOR1_WORLD,
1695            .conformanceTestLimit        = NO_CTL,
1696            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1697            .pscan                       = PSCAN_WWR,
1698            .flags                       = ADHOC_NO_11A,
1699            .chan11a           = BM5(W1_5260_5320,
1700                                               W1_5180_5240,
1701                                               W1_5170_5230,
1702                                               W1_5745_5825,
1703                                               W1_5500_5700),
1704            .chan11b           = BM8(W1_2412_2412,
1705                                               W1_2437_2442,
1706                                               W1_2462_2462,
1707                                               W1_2472_2472,
1708                                               W1_2417_2432,
1709                                               W1_2447_2457,
1710                                               W1_2467_2467,
1711                                               W1_2484_2484),
1712            .chan11g           = BM7(WG1_2412_2412,
1713                                               WG1_2437_2442,
1714                                               WG1_2462_2462,
1715                                               WG1_2472_2472,
1716                                               WG1_2417_2432,
1717                                               WG1_2447_2457,
1718                                               WG1_2467_2467),
1719            .chan11g_turbo               = BM1(T3_2437_2437)
1720           },
1721 
1722           {.regDmnEnum                  = WOR2_WORLD,
1723            .conformanceTestLimit        = NO_CTL,
1724            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1725            .pscan                       = PSCAN_WWR,
1726            .flags                       = ADHOC_NO_11A,
1727            .chan11a           = BM5(W1_5260_5320,
1728                                               W1_5180_5240,
1729                                               W1_5170_5230,
1730                                               W1_5745_5825,
1731                                               W1_5500_5700),
1732            .chan11a_turbo               = BM3(WT1_5210_5250,
1733                                               WT1_5290_5290,
1734                                               WT1_5760_5800),
1735            .chan11b           = BM8(W1_2412_2412,
1736                                               W1_2437_2442,
1737                                               W1_2462_2462,
1738                                               W1_2472_2472,
1739                                               W1_2417_2432,
1740                                               W1_2447_2457,
1741                                               W1_2467_2467,
1742                                               W1_2484_2484),
1743            .chan11g           = BM7(WG1_2412_2412,
1744                                               WG1_2437_2442,
1745                                               WG1_2462_2462,
1746                                               WG1_2472_2472,
1747                                               WG1_2417_2432,
1748                                               WG1_2447_2457,
1749                                               WG1_2467_2467),
1750            .chan11g_turbo               = BM1(T3_2437_2437)},
1751 
1752           {.regDmnEnum                  = WOR3_WORLD,
1753            .conformanceTestLimit        = NO_CTL,
1754            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1755            .pscan                       = PSCAN_WWR,
1756            .flags                       = ADHOC_PER_11D,
1757            .chan11a           = BM4(W1_5260_5320,
1758                                               W1_5180_5240,
1759                                               W1_5170_5230,
1760                                               W1_5745_5825),
1761            .chan11a_turbo               = BM3(WT1_5210_5250,
1762                                               WT1_5290_5290,
1763                                               WT1_5760_5800),
1764            .chan11b           = BM7(W1_2412_2412,
1765                                               W1_2437_2442,
1766                                               W1_2462_2462,
1767                                               W1_2472_2472,
1768                                               W1_2417_2432,
1769                                               W1_2447_2457,
1770                                               W1_2467_2467),
1771            .chan11g           = BM7(WG1_2412_2412,
1772                                               WG1_2437_2442,
1773                                               WG1_2462_2462,
1774                                               WG1_2472_2472,
1775                                               WG1_2417_2432,
1776                                               WG1_2447_2457,
1777                                               WG1_2467_2467),
1778            .chan11g_turbo               = BM1(T3_2437_2437)},
1779 
1780           {.regDmnEnum                  = WOR4_WORLD,
1781            .conformanceTestLimit        = NO_CTL,
1782            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1783            .pscan                       = PSCAN_WWR,
1784            .flags                       = ADHOC_NO_11A,
1785            .chan11a           = BM4(W2_5260_5320,
1786                                               W2_5180_5240,
1787                                               F2_5745_5805,
1788                                               W2_5825_5825),
1789            .chan11a_turbo               = BM3(WT1_5210_5250,
1790                                               WT1_5290_5290,
1791                                               WT1_5760_5800),
1792            .chan11b           = BM5(W1_2412_2412,
1793                                               W1_2437_2442,
1794                                               W1_2462_2462,
1795                                               W1_2417_2432,
1796                                               W1_2447_2457),
1797            .chan11g           = BM5(WG1_2412_2412,
1798                                               WG1_2437_2442,
1799                                               WG1_2462_2462,
1800                                               WG1_2417_2432,
1801                                               WG1_2447_2457),
1802            .chan11g_turbo               = BM1(T3_2437_2437)},
1803 
1804           {.regDmnEnum                  = WOR5_ETSIC,
1805            .conformanceTestLimit        = NO_CTL,
1806            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1807            .pscan                       = PSCAN_WWR,
1808            .flags                       = ADHOC_NO_11A,
1809            .chan11a           = BM3(W1_5260_5320, W2_5180_5240, F6_5745_5825),
1810            .chan11b           = BM7(W1_2412_2412,
1811                                               W1_2437_2442,
1812                                               W1_2462_2462,
1813                                               W2_2472_2472,
1814                                               W1_2417_2432,
1815                                               W1_2447_2457,
1816                                               W2_2467_2467),
1817            .chan11g           = BM7(WG1_2412_2412,
1818                                               WG1_2437_2442,
1819                                               WG1_2462_2462,
1820                                               WG2_2472_2472,
1821                                               WG1_2417_2432,
1822                                               WG1_2447_2457,
1823                                               WG2_2467_2467),
1824            .chan11g_turbo               = BM1(T3_2437_2437)},
1825 
1826           {.regDmnEnum                  = WOR9_WORLD,
1827            .conformanceTestLimit        = NO_CTL,
1828            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1829            .pscan                       = PSCAN_WWR,
1830            .flags                       = ADHOC_NO_11A,
1831            .chan11a           = BM4(W1_5260_5320,
1832                                               W1_5180_5240,
1833                                               W1_5745_5825,
1834                                               W1_5500_5700),
1835            .chan11a_turbo               = BM3(WT1_5210_5250,
1836                                               WT1_5290_5290,
1837                                               WT1_5760_5800),
1838            .chan11b           = BM5(W1_2412_2412,
1839                                               W1_2437_2442,
1840                                               W1_2462_2462,
1841                                               W1_2417_2432,
1842                                               W1_2447_2457),
1843            .chan11g           = BM5(WG1_2412_2412,
1844                                               WG1_2437_2442,
1845                                               WG1_2462_2462,
1846                                               WG1_2417_2432,
1847                                               WG1_2447_2457),
1848            .chan11g_turbo               = BM1(T3_2437_2437)},
1849 
1850           {.regDmnEnum                  = WORA_WORLD,
1851            .conformanceTestLimit        = NO_CTL,
1852            .dfsMask           = DFS_FCC3 | DFS_ETSI,
1853            .pscan                       = PSCAN_WWR,
1854            .flags                       = ADHOC_NO_11A,
1855            .chan11a           = BM4(W1_5260_5320,
1856                                               W1_5180_5240,
1857                                               W1_5745_5825,
1858                                               W1_5500_5700),
1859            .chan11b           = BM7(W1_2412_2412,
1860                                               W1_2437_2442,
1861                                               W1_2462_2462,
1862                                               W1_2472_2472,
1863                                               W1_2417_2432,
1864                                               W1_2447_2457,
1865                                               W1_2467_2467),
1866            .chan11g           = BM7(WG1_2412_2412,
1867                                               WG1_2437_2442,
1868                                               WG1_2462_2462,
1869                                               WG1_2472_2472,
1870                                               WG1_2417_2432,
1871                                               WG1_2447_2457,
1872                                               WG1_2467_2467),
1873            .chan11g_turbo               = BM1(T3_2437_2437)},
1874 
1875           {.regDmnEnum                  = SR9_WORLD,
1876            .conformanceTestLimit        = NO_CTL,
1877            .pscan                       = PSCAN_FCC | PSCAN_FCC_T,
1878            .chan11g           = BM1(S1_912_917),
1879            .chan11g_half                = BM1(S1_907_922_10),
1880            .chan11g_quarter   = BM1(S1_907_922_5),
1881           },
1882 
1883           {.regDmnEnum                  = XR9_WORLD,
1884            .conformanceTestLimit        = NO_CTL,
1885            .pscan                       = PSCAN_FCC | PSCAN_FCC_T,
1886            .chan11g           = BM1(S2_912_917),
1887            .chan11g_half                = BM1(S2_907_922_10),
1888            .chan11g_quarter   = BM1(S2_907_922_5),
1889           },
1890 
1891           {.regDmnEnum                  = GZ901_WORLD,
1892            .conformanceTestLimit        = NO_CTL,
1893            .pscan                       = PSCAN_FCC | PSCAN_FCC_T,
1894            .chan11g           = BM1(S1_913_918),
1895            .chan11g_half                = BM1(S1_913_918_10),
1896            .chan11g_quarter   = BM1(S1_908_923_5),
1897           },
1898 
1899           {.regDmnEnum                  = NULL1,
1900            .conformanceTestLimit        = NO_CTL,
1901           }
1902 };
1903 
1904 struct cmode {
1905           u_int     mode;
1906           u_int     flags;
1907 };
1908 
1909 static const struct cmode modes[] = {
1910           { HAL_MODE_TURBO,   CHANNEL_ST},        /* NB: 11a Static Turbo */
1911           { HAL_MODE_11A,               CHANNEL_A},
1912           { HAL_MODE_11B,               CHANNEL_B},
1913           { HAL_MODE_11G,               CHANNEL_G},
1914           { HAL_MODE_11G_TURBO,         CHANNEL_108G},
1915           { HAL_MODE_11A_TURBO,         CHANNEL_108A},
1916           { HAL_MODE_11A_QUARTER_RATE,  CHANNEL_A | CHANNEL_QUARTER},
1917           { HAL_MODE_11A_HALF_RATE,     CHANNEL_A | CHANNEL_HALF},
1918           { HAL_MODE_11G_QUARTER_RATE,  CHANNEL_G | CHANNEL_QUARTER},
1919           { HAL_MODE_11G_HALF_RATE,     CHANNEL_G | CHANNEL_HALF},
1920           { HAL_MODE_11NG_HT20,         CHANNEL_G_HT20},
1921           { HAL_MODE_11NG_HT40PLUS,     CHANNEL_G_HT40PLUS},
1922           { HAL_MODE_11NG_HT40MINUS,    CHANNEL_G_HT40MINUS},
1923           { HAL_MODE_11NA_HT20,         CHANNEL_A_HT20},
1924           { HAL_MODE_11NA_HT40PLUS,     CHANNEL_A_HT40PLUS},
1925           { HAL_MODE_11NA_HT40MINUS,    CHANNEL_A_HT40MINUS},
1926 };
1927 
1928 static int
chansort(const void * a,const void * b)1929 chansort(const void *a, const void *b)
1930 {
1931 #define CHAN_FLAGS  (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)
1932           const HAL_CHANNEL_INTERNAL *ca = a;
1933           const HAL_CHANNEL_INTERNAL *cb = b;
1934 
1935           return (ca->channel == cb->channel) ?
1936                     (ca->channelFlags & CHAN_FLAGS) -
1937                               (cb->channelFlags & CHAN_FLAGS) :
1938                     ca->channel - cb->channel;
1939 #undef CHAN_FLAGS
1940 }
1941 typedef int ath_hal_cmp_t(const void *, const void *);
1942 static    void ath_hal_sort(void *a, size_t n, size_t es, ath_hal_cmp_t *cmp);
1943 static COUNTRY_CODE_TO_ENUM_RD* findCountry(HAL_CTRY_CODE countryCode);
1944 static HAL_BOOL getWmRD(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country, uint16_t channelFlag, REG_DOMAIN *rd);
1945 
1946 
1947 static uint16_t
getEepromRD(struct ath_hal * ah)1948 getEepromRD(struct ath_hal *ah)
1949 {
1950           return AH_PRIVATE(ah)->ah_currentRD &~ WORLDWIDE_ROAMING_FLAG;
1951 }
1952 
1953 /*
1954  * Test to see if the bitmask array is all zeros
1955  */
1956 static HAL_BOOL
isChanBitMaskZero(const uint64_t * bitmask)1957 isChanBitMaskZero(const uint64_t *bitmask)
1958 {
1959 #if BMLEN > 2
1960 #error    "add more cases"
1961 #endif
1962 #if BMLEN > 1
1963           if (bitmask[1] != 0)
1964                     return AH_FALSE;
1965 #endif
1966           return (bitmask[0] == 0);
1967 }
1968 
1969 /*
1970  * Return whether or not the regulatory domain/country in EEPROM
1971  * is acceptable.
1972  */
1973 static HAL_BOOL
isEepromValid(struct ath_hal * ah)1974 isEepromValid(struct ath_hal *ah)
1975 {
1976           uint16_t rd = getEepromRD(ah);
1977           int i;
1978 
1979           if (rd & COUNTRY_ERD_FLAG) {
1980                     uint16_t cc = rd &~ COUNTRY_ERD_FLAG;
1981                     for (i = 0; i < N(allCountries); i++)
1982                               if (allCountries[i].countryCode == cc)
1983                                         return AH_TRUE;
1984           } else {
1985                     for (i = 0; i < N(regDomainPairs); i++)
1986                               if (regDomainPairs[i].regDmnEnum == rd)
1987                                         return AH_TRUE;
1988           }
1989           HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1990               "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd);
1991           return AH_FALSE;
1992 }
1993 
1994 /*
1995  * Returns whether or not the specified country code
1996  * is allowed by the EEPROM setting
1997  */
1998 static HAL_BOOL
isCountryCodeValid(struct ath_hal * ah,HAL_CTRY_CODE cc)1999 isCountryCodeValid(struct ath_hal *ah, HAL_CTRY_CODE cc)
2000 {
2001           uint16_t rd;
2002 
2003           /* Default setting requires no checks */
2004           if (cc == CTRY_DEFAULT)
2005                     return AH_TRUE;
2006 #ifdef AH_DEBUG_COUNTRY
2007           if (cc == CTRY_DEBUG)
2008                     return AH_TRUE;
2009 #endif
2010           rd = getEepromRD(ah);
2011           HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: EEPROM regdomain 0x%x\n",
2012               __func__, rd);
2013 
2014           if (rd & COUNTRY_ERD_FLAG) {
2015                     /* EEP setting is a country - config shall match */
2016                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2017                         "%s: EEPROM setting is country code %u\n", __func__,
2018                         rd &~ COUNTRY_ERD_FLAG);
2019                     return (cc == (rd & ~COUNTRY_ERD_FLAG));
2020           } else if (rd == DEBUG_REG_DMN || rd == NO_ENUMRD) {
2021                     /* Set to Debug or AllowAnyCountry mode - allow any setting */
2022                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: rd %d allowed\n",
2023                         __func__, rd);
2024                     return AH_TRUE;
2025 #ifdef AH_SUPPORT_11D
2026           } else    if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) {
2027                     int i;
2028                     for (i=0; i < N(allCountries); i++) {
2029                               if (cc == allCountries[i].countryCode)
2030                                         return AH_TRUE;
2031                     }
2032 #endif
2033           } else {
2034                     int i;
2035                     for (i = 0; i < N(allCountries); i++) {
2036                               if (cc == allCountries[i].countryCode &&
2037                                   allCountries[i].regDmnEnum == rd)
2038                                         return AH_TRUE;
2039                     }
2040           }
2041           return AH_FALSE;
2042 }
2043 
2044 /*
2045  * Return the mask of available modes based on the hardware
2046  * capabilities and the specified country code and reg domain.
2047  */
2048 static u_int
ath_hal_getwmodesnreg(struct ath_hal * ah,const COUNTRY_CODE_TO_ENUM_RD * country,const REG_DOMAIN * rd5GHz)2049 ath_hal_getwmodesnreg(struct ath_hal *ah,
2050     const COUNTRY_CODE_TO_ENUM_RD *country, const REG_DOMAIN *rd5GHz)
2051 {
2052 #define   HAL_MODE_11G_ALL \
2053           (HAL_MODE_11G | HAL_MODE_11G_TURBO | HAL_MODE_11G_QUARTER_RATE | \
2054            HAL_MODE_11G_HALF_RATE)
2055 #define   HAL_MODE_11A_ALL \
2056           (HAL_MODE_11A | HAL_MODE_11A_TURBO | HAL_MODE_TURBO | \
2057            HAL_MODE_11A_QUARTER_RATE | HAL_MODE_11A_HALF_RATE)
2058           u_int modesAvail;
2059 
2060           /* Get modes that HW is capable of */
2061           modesAvail = ath_hal_getWirelessModes(ah);
2062 
2063           HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2064               "%s: wireless modes 0x%x cc %u rd %u\n",
2065               __func__, modesAvail, country->countryCode, country->regDmnEnum);
2066 
2067           /* Check country regulations for allowed modes */
2068           if (!country->allow11g && (modesAvail & HAL_MODE_11G_ALL)) {
2069                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2070                         "%s: disallow all 11g\n", __func__);
2071                     modesAvail &= ~HAL_MODE_11G_ALL;
2072           }
2073           if (isChanBitMaskZero(rd5GHz->chan11a) &&
2074               (modesAvail & HAL_MODE_11A_ALL)) {
2075                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2076                         "%s: disallow all 11a\n", __func__);
2077                     modesAvail &= ~HAL_MODE_11A_ALL;
2078           }
2079           if ((modesAvail & (HAL_MODE_11A_TURBO | HAL_MODE_TURBO)) &&
2080               !country->allow11aTurbo) {
2081                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2082                         "%s: disallow 11aTurbo\n", __func__);
2083                     modesAvail &= ~(HAL_MODE_11A_TURBO | HAL_MODE_TURBO);
2084           }
2085           if ((modesAvail & HAL_MODE_11G_TURBO) && !country->allow11gTurbo) {
2086                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2087                         "%s: disallow 11gTurbo\n", __func__);
2088                     modesAvail &= ~HAL_MODE_11G_TURBO;
2089           }
2090 
2091           /* Check 11n operation */
2092           if ((modesAvail & HAL_MODE_11NG_HT20) && !country->allow11ng20) {
2093                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2094                         "%s: disallow 11g HT20\n", __func__);
2095                     modesAvail &= ~HAL_MODE_11NG_HT20;
2096           }
2097           if ((modesAvail & HAL_MODE_11NA_HT20) && !country->allow11na20) {
2098                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2099                         "%s: disallow 11a HT20\n", __func__);
2100                     modesAvail &= ~HAL_MODE_11NA_HT20;
2101           }
2102           if ((modesAvail & HAL_MODE_11NG_HT40PLUS) && !country->allow11ng40) {
2103                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2104                         "%s: disallow 11g HT40+\n", __func__);
2105                     modesAvail &= ~HAL_MODE_11NG_HT40PLUS;
2106           }
2107           if ((modesAvail & HAL_MODE_11NG_HT40MINUS) && !country->allow11ng40) {
2108                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2109                         "%s: disallow 11g HT40-\n", __func__);
2110                     modesAvail &= ~HAL_MODE_11NG_HT40MINUS;
2111           }
2112           if ((modesAvail & HAL_MODE_11NA_HT40PLUS) && !country->allow11na40) {
2113                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2114                         "%s: disallow 11a HT40+\n", __func__);
2115                     modesAvail &= ~HAL_MODE_11NA_HT40PLUS;
2116           }
2117           if ((modesAvail & HAL_MODE_11NA_HT40MINUS) && !country->allow11na40) {
2118                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2119                         "%s: disallow 11a HT40-\n", __func__);
2120                     modesAvail &= ~HAL_MODE_11NA_HT40MINUS;
2121           }
2122 
2123           return modesAvail;
2124 #undef HAL_MODE_11A_ALL
2125 #undef HAL_MODE_11G_ALL
2126 }
2127 
2128 /*
2129  * Return the mask of available modes based on the hardware
2130  * capabilities and the specified country code.
2131  */
2132 
2133 u_int
ath_hal_getwirelessmodes(struct ath_hal * ah,HAL_CTRY_CODE cc)2134 ath_hal_getwirelessmodes(struct ath_hal *ah, HAL_CTRY_CODE cc)
2135 {
2136           COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL;
2137           u_int mode = 0;
2138           REG_DOMAIN rd;
2139 
2140           country = findCountry(cc);
2141           if (country != AH_NULL) {
2142                     if (getWmRD(ah, country, ~CHANNEL_2GHZ, &rd))
2143                               mode = ath_hal_getwmodesnreg(ah, country, &rd);
2144           }
2145           return mode;
2146 }
2147 
2148 /*
2149  * Return if device is public safety.
2150  */
2151 HAL_BOOL
ath_hal_ispublicsafetysku(struct ath_hal * ah)2152 ath_hal_ispublicsafetysku(struct ath_hal *ah)
2153 {
2154           uint16_t rd = getEepromRD(ah);
2155 
2156           switch (rd) {
2157           case FCC4_FCCA:
2158           case CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG:
2159                     return AH_TRUE;
2160           case DEBUG_REG_DMN:
2161           case NO_ENUMRD:
2162                     if (AH_PRIVATE(ah)->ah_countryCode == CTRY_UNITED_STATES_FCC49)
2163                               return AH_TRUE;
2164                     break;
2165           }
2166           return AH_FALSE;
2167 }
2168 
2169 /*
2170  * Return if device is actually operating in 900 MHz band.
2171  */
2172 HAL_BOOL
ath_hal_isgsmsku(struct ath_hal * ah)2173 ath_hal_isgsmsku(struct ath_hal *ah)
2174 {
2175           uint16_t rd = getEepromRD(ah);
2176 
2177           switch (rd) {
2178           case SR9_WORLD:
2179           case XR9_WORLD:
2180           case GZ901_WORLD:
2181           case CTRY_SR9 | COUNTRY_ERD_FLAG:
2182           case CTRY_XR9 | COUNTRY_ERD_FLAG:
2183           case CTRY_GZ901 | COUNTRY_ERD_FLAG:
2184                     return AH_TRUE;
2185           case DEBUG_REG_DMN:
2186           case NO_ENUMRD:
2187                     return AH_PRIVATE(ah)->ah_countryCode == CTRY_SR9
2188                            || AH_PRIVATE(ah)->ah_countryCode == CTRY_XR9
2189                            || AH_PRIVATE(ah)->ah_countryCode == CTRY_GZ901
2190                            ;
2191           }
2192           return AH_FALSE;
2193 }
2194 
2195 /*
2196  * Find the pointer to the country element in the country table
2197  * corresponding to the country code
2198  */
2199 static COUNTRY_CODE_TO_ENUM_RD*
findCountry(HAL_CTRY_CODE countryCode)2200 findCountry(HAL_CTRY_CODE countryCode)
2201 {
2202           int i;
2203 
2204           for (i = 0; i < N(allCountries); i++) {
2205                     if (allCountries[i].countryCode == countryCode)
2206                               return &allCountries[i];
2207           }
2208           return AH_NULL;               /* Not found */
2209 }
2210 
2211 /*
2212  * Calculate a default country based on the EEPROM setting.
2213  */
2214 static HAL_CTRY_CODE
getDefaultCountry(struct ath_hal * ah)2215 getDefaultCountry(struct ath_hal *ah)
2216 {
2217           uint16_t rd;
2218           int i;
2219 
2220           rd = getEepromRD(ah);
2221           if (rd & COUNTRY_ERD_FLAG) {
2222                     COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL;
2223                     uint16_t cc = rd & ~COUNTRY_ERD_FLAG;
2224 
2225                     country = findCountry(cc);
2226                     if (country != AH_NULL)
2227                               return cc;
2228           }
2229           /*
2230            * Check reg domains that have only one country
2231            */
2232           for (i = 0; i < N(regDomainPairs); i++)
2233                     if (regDomainPairs[i].regDmnEnum == rd) {
2234                               if (regDomainPairs[i].singleCC != 0)
2235                                         return regDomainPairs[i].singleCC;
2236                               else
2237                                         i = N(regDomainPairs);
2238                     }
2239           return CTRY_DEFAULT;
2240 }
2241 
2242 static HAL_BOOL
isValidRegDmn(int regDmn,REG_DOMAIN * rd)2243 isValidRegDmn(int regDmn, REG_DOMAIN *rd)
2244 {
2245           int i;
2246 
2247           for (i = 0; i < N(regDomains); i++) {
2248                     if (regDomains[i].regDmnEnum == regDmn) {
2249                               if (rd != AH_NULL) {
2250                                         OS_MEMCPY(rd, &regDomains[i],
2251                                                     sizeof(REG_DOMAIN));
2252                               }
2253                               return AH_TRUE;
2254                     }
2255           }
2256           return AH_FALSE;
2257 }
2258 
2259 static HAL_BOOL
isValidRegDmnPair(int regDmnPair)2260 isValidRegDmnPair(int regDmnPair)
2261 {
2262           int i;
2263 
2264           if (regDmnPair == NO_ENUMRD)
2265                     return AH_FALSE;
2266           for (i = 0; i < N(regDomainPairs); i++) {
2267                     if (regDomainPairs[i].regDmnEnum == regDmnPair)
2268                               return AH_TRUE;
2269           }
2270           return AH_FALSE;
2271 }
2272 
2273 /*
2274  * Return the Wireless Mode Regulatory Domain based
2275  * on the country code and the wireless mode.
2276  */
2277 static HAL_BOOL
getWmRD(struct ath_hal * ah,COUNTRY_CODE_TO_ENUM_RD * country,uint16_t channelFlag,REG_DOMAIN * rd)2278 getWmRD(struct ath_hal *ah, COUNTRY_CODE_TO_ENUM_RD *country,
2279           uint16_t channelFlag, REG_DOMAIN *rd)
2280 {
2281           int regDmn;
2282           REG_DMN_PAIR_MAPPING *regPair;
2283           uint64_t flags;
2284 
2285           if (country->countryCode == CTRY_DEFAULT) {
2286                     uint16_t rdnum = getEepromRD(ah);
2287 
2288                     if ((rdnum & COUNTRY_ERD_FLAG) == 0) {
2289                               if (isValidRegDmn(rdnum, AH_NULL) ||
2290                                   isValidRegDmnPair(rdnum))
2291                                         regDmn = rdnum;
2292                               else
2293                                         regDmn = country->regDmnEnum;
2294                     } else
2295                               regDmn = country->regDmnEnum;
2296           } else
2297                     regDmn = country->regDmnEnum;
2298           regPair = AH_NULL;
2299           flags = NO_REQ;
2300           if ((regDmn & MULTI_DOMAIN_MASK) == 0) {
2301                     int i;
2302 
2303                     for (i = 0; i < N(regDomainPairs); i++) {
2304                               if (regDomainPairs[i].regDmnEnum == regDmn) {
2305                                         regPair = &regDomainPairs[i];
2306                                         break;
2307                               }
2308                     }
2309                     if (regPair == AH_NULL) {
2310                               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2311                                   "%s: Failed to find reg domain pair %u\n",
2312                                   __func__, regDmn);
2313                               return AH_FALSE;
2314                     }
2315                     if (channelFlag & CHANNEL_2GHZ) {
2316                               regDmn = regPair->regDmn2GHz;
2317                               flags = regPair->flags2GHz;
2318                     } else {
2319                               regDmn = regPair->regDmn5GHz;
2320                               flags = regPair->flags5GHz;
2321                     }
2322           }
2323 
2324           /*
2325            * We either started with a unitary reg domain or we've found the
2326            * unitary reg domain of the pair
2327            */
2328           if (isValidRegDmn(regDmn, rd)) {
2329                     if (regPair != AH_NULL)
2330                               rd->pscan &= regPair->pscanMask;
2331                     if ((country->regDmnEnum & MULTI_DOMAIN_MASK) == 0 &&
2332                         flags != NO_REQ)
2333                               rd->flags = flags;
2334                     return AH_TRUE;
2335           } else {
2336                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2337                         "%s: Failed to find unitary reg domain %u\n", __func__,
2338                         country->regDmnEnum);
2339                     return AH_FALSE;
2340           }
2341 }
2342 
2343 static HAL_BOOL
IS_BIT_SET(int bit,const uint64_t bitmask[])2344 IS_BIT_SET(int bit, const uint64_t bitmask[])
2345 {
2346           int byteOffset, bitnum;
2347           uint64_t val;
2348 
2349           byteOffset = bit/64;
2350           bitnum = bit - byteOffset*64;
2351           val = ((uint64_t) 1) << bitnum;
2352           return (bitmask[byteOffset] & val) != 0;
2353 }
2354 
2355 /* Add given regclassid into regclassids array upto max of maxregids */
2356 static void
ath_add_regclassid(uint8_t * regclassids,u_int maxregids,u_int * nregids,uint8_t regclassid)2357 ath_add_regclassid(uint8_t *regclassids, u_int maxregids,
2358           u_int *nregids, uint8_t regclassid)
2359 {
2360           int i;
2361 
2362           /* Is regclassid valid? */
2363           if (regclassid == 0)
2364                     return;
2365 
2366           for (i = 0; i < maxregids; i++) {
2367                     if (regclassids[i] == regclassid)       /* already present */
2368                               return;
2369                     if (regclassids[i] == 0) {              /* free slot */
2370                               regclassids[i] = regclassid;
2371                               (*nregids)++;
2372                               return;
2373                     }
2374           }
2375 }
2376 
2377 /*
2378  * Setup the channel list based on the information in the EEPROM and
2379  * any supplied country code.  Note that we also do a bunch of EEPROM
2380  * verification here and setup certain regulatory-related access
2381  * control data used later on.
2382  */
2383 
2384 HAL_BOOL
ath_hal_init_channels(struct ath_hal * ah,HAL_CHANNEL * chans,u_int maxchans,u_int * nchans,uint8_t * regclassids,u_int maxregids,u_int * nregids,HAL_CTRY_CODE cc,u_int modeSelect,HAL_BOOL enableOutdoor,HAL_BOOL enableExtendedChannels)2385 ath_hal_init_channels(struct ath_hal *ah,
2386                           HAL_CHANNEL *chans, u_int maxchans, u_int *nchans,
2387                           uint8_t *regclassids, u_int maxregids, u_int *nregids,
2388                           HAL_CTRY_CODE cc, u_int modeSelect,
2389                           HAL_BOOL enableOutdoor, HAL_BOOL enableExtendedChannels)
2390 {
2391 #define CHANNEL_HALF_BW                 10
2392 #define CHANNEL_QUARTER_BW    5
2393           u_int modesAvail;
2394           uint16_t maxChan;
2395           COUNTRY_CODE_TO_ENUM_RD *country = AH_NULL;
2396           REG_DOMAIN rd5GHz, rd2GHz;
2397           const struct cmode *cm;
2398           HAL_CHANNEL_INTERNAL *ichans = &AH_PRIVATE(ah)->ah_channels[0];
2399           int next, b;
2400           uint8_t ctl;
2401 
2402           HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u mode 0x%x%s%s\n",
2403               __func__, cc, modeSelect, enableOutdoor? " Enable outdoor" : " ",
2404               enableExtendedChannels ? " Enable ecm" : "");
2405 
2406           /*
2407            * Validate the EEPROM setting and setup defaults
2408            */
2409           if (!isEepromValid(ah)) {
2410                     /*
2411                      * Don't return any channels if the EEPROM has an
2412                      * invalid regulatory domain/country code setting.
2413                      */
2414                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2415                         "%s: invalid EEPROM contents\n",__func__);
2416                     return AH_FALSE;
2417           }
2418 
2419           AH_PRIVATE(ah)->ah_countryCode = getDefaultCountry(ah);
2420 
2421 #ifndef AH_SUPPORT_11D
2422           if (AH_PRIVATE(ah)->ah_countryCode == CTRY_DEFAULT) {
2423 #endif
2424                     /*
2425                      * We now have enough state to validate any country code
2426                      * passed in by the caller.
2427                      */
2428                     if (!isCountryCodeValid(ah, cc)) {
2429                               /* NB: Atheros silently ignores invalid country codes */
2430                               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2431                                   "%s: invalid country code %d\n", __func__, cc);
2432                               return AH_FALSE;
2433                     }
2434                     AH_PRIVATE(ah)->ah_countryCode = cc & COUNTRY_CODE_MASK;
2435 #ifndef AH_SUPPORT_11D
2436           }
2437 #endif
2438 
2439           /* Get pointers to the country element and the reg domain elements */
2440           country = findCountry(AH_PRIVATE(ah)->ah_countryCode);
2441 
2442           if (country == AH_NULL) {
2443                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "NULL Country!, cc= %d\n",
2444                         AH_PRIVATE(ah)->ah_countryCode);
2445                     return AH_FALSE;
2446           }
2447 
2448           if (!getWmRD(ah, country, ~CHANNEL_2GHZ, &rd5GHz)) {
2449                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2450                         "%s: no unitary 5GHz regdomain for country %u\n",
2451                          __func__, AH_PRIVATE(ah)->ah_countryCode);
2452                     return AH_FALSE;
2453           }
2454           if (!getWmRD(ah, country, CHANNEL_2GHZ, &rd2GHz)) {
2455                     HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2456                         "%s: no unitary 2GHz regdomain for country %u\n",
2457                         __func__, AH_PRIVATE(ah)->ah_countryCode);
2458                     return AH_FALSE;
2459           }
2460 
2461           modesAvail = ath_hal_getwmodesnreg(ah, country, &rd5GHz);
2462           maxChan = !enableOutdoor ? country->outdoorChanStart : 7000;
2463 
2464           if (maxchans > N(AH_PRIVATE(ah)->ah_channels))
2465                     maxchans = N(AH_PRIVATE(ah)->ah_channels);
2466           next = 0;
2467           for (cm = modes; cm < &modes[N(modes)]; cm++) {
2468                     uint16_t c, c_hi, c_lo;
2469                     uint64_t *channelBM = AH_NULL;
2470                     REG_DOMAIN *rd = AH_NULL;
2471                     REG_DMN_FREQ_BAND *fband = AH_NULL,*freqs;
2472                     int low_adj, hi_adj, channelSep, lastc;
2473 
2474                     if ((cm->mode & modeSelect) == 0) {
2475                               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2476                                   "%s: skip mode 0x%x flags 0x%x\n",
2477                                   __func__, cm->mode, cm->flags);
2478                               continue;
2479                     }
2480                     if ((cm->mode & modesAvail) == 0) {
2481                               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2482                                   "%s: !avail mode 0x%x (0x%x) flags 0x%x\n",
2483                                   __func__, modesAvail, cm->mode, cm->flags);
2484                               continue;
2485                     }
2486                     if (!ath_hal_getChannelEdges(ah, cm->flags, &c_lo, &c_hi)) {
2487                               /* channel not supported by hardware, skip it */
2488                               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2489                                   "%s: channels 0x%x not supported by hardware\n",
2490                                   __func__,cm->flags);
2491                               continue;
2492                     }
2493                     switch (cm->mode) {
2494                     case HAL_MODE_TURBO:
2495                               rd = &rd5GHz;
2496                               channelBM = rd->chan11a_turbo;
2497                               freqs = &regDmn5GhzTurboFreq[0];
2498                               ctl = rd->conformanceTestLimit | CTL_TURBO;
2499                               break;
2500                     case HAL_MODE_11A:
2501                     case HAL_MODE_11A_HALF_RATE:
2502                     case HAL_MODE_11A_QUARTER_RATE:
2503                     case HAL_MODE_11NA_HT20:
2504                     case HAL_MODE_11NA_HT40PLUS:
2505                     case HAL_MODE_11NA_HT40MINUS:
2506                               rd = &rd5GHz;
2507                               if (cm->mode == HAL_MODE_11A_HALF_RATE)
2508                                         channelBM = rd->chan11a_half;
2509                               else if (cm->mode == HAL_MODE_11A_QUARTER_RATE)
2510                                         channelBM = rd->chan11a_quarter;
2511                               else
2512                                         channelBM = rd->chan11a;
2513                               freqs = &regDmn5GhzFreq[0];
2514                               ctl = rd->conformanceTestLimit;
2515                               break;
2516                     case HAL_MODE_11B:
2517                               rd = &rd2GHz;
2518                               channelBM = rd->chan11b;
2519                               freqs = &regDmn2GhzFreq[0];
2520                               ctl = rd->conformanceTestLimit | CTL_11B;
2521                               break;
2522                     case HAL_MODE_11G:
2523                     case HAL_MODE_11G_HALF_RATE:
2524                     case HAL_MODE_11G_QUARTER_RATE:
2525                     case HAL_MODE_11NG_HT20:
2526                     case HAL_MODE_11NG_HT40PLUS:
2527                     case HAL_MODE_11NG_HT40MINUS:
2528                               rd = &rd2GHz;
2529                               if (cm->mode == HAL_MODE_11G_HALF_RATE)
2530                                         channelBM = rd->chan11g_half;
2531                               else if (cm->mode == HAL_MODE_11G_QUARTER_RATE)
2532                                         channelBM = rd->chan11g_quarter;
2533                               else
2534                                         channelBM = rd->chan11g;
2535                               freqs = &regDmn2Ghz11gFreq[0];
2536                               ctl = rd->conformanceTestLimit | CTL_11G;
2537                               break;
2538                     case HAL_MODE_11G_TURBO:
2539                               rd = &rd2GHz;
2540                               channelBM = rd->chan11g_turbo;
2541                               freqs = &regDmn2Ghz11gTurboFreq[0];
2542                               ctl = rd->conformanceTestLimit | CTL_108G;
2543                               break;
2544                     case HAL_MODE_11A_TURBO:
2545                               rd = &rd5GHz;
2546                               channelBM = rd->chan11a_dyn_turbo;
2547                               freqs = &regDmn5GhzTurboFreq[0];
2548                               ctl = rd->conformanceTestLimit | CTL_108G;
2549                               break;
2550                     default:
2551                               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2552                                   "%s: Unkonwn HAL mode 0x%x\n", __func__, cm->mode);
2553                               continue;
2554                     }
2555                     if (isChanBitMaskZero(channelBM))
2556                               continue;
2557                     /*
2558                      * Setup special handling for HT40 channels; e.g.
2559                      * 5G HT40 channels require 40Mhz channel separation.
2560                      */
2561                     hi_adj = (cm->mode == HAL_MODE_11NA_HT40PLUS ||
2562                         cm->mode == HAL_MODE_11NG_HT40PLUS) ? -20 : 0;
2563                     low_adj = (cm->mode == HAL_MODE_11NA_HT40MINUS ||
2564                         cm->mode == HAL_MODE_11NG_HT40MINUS) ? 20 : 0;
2565                     channelSep = (cm->mode == HAL_MODE_11NA_HT40PLUS ||
2566                         cm->mode == HAL_MODE_11NA_HT40MINUS) ? 40 : 0;
2567 
2568                     for (b = 0; b < 64*BMLEN; b++) {
2569                               if (!IS_BIT_SET(b, channelBM))
2570                                         continue;
2571                               fband = &freqs[b];
2572                               lastc = 0;
2573 
2574                               ath_add_regclassid(regclassids, maxregids,
2575                                                   nregids, fband->regClassId);
2576 
2577                               for (c = fband->lowChannel + low_adj;
2578                                    c <= fband->highChannel + hi_adj;
2579                                    c += fband->channelSep) {
2580                                         HAL_CHANNEL_INTERNAL icv;
2581 
2582                                         if (!(c_lo <= c && c <= c_hi)) {
2583                                                   HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2584                                                       "%s: c %u out of range [%u..%u]\n",
2585                                                       __func__, c, c_lo, c_hi);
2586                                                   continue;
2587                                         }
2588                                         if (((c+fband->channelSep)/2) > (maxChan+HALF_MAXCHANBW)) {
2589                                                   HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2590                                                       "%s: c %u > maxChan %u\n",
2591                                                       __func__, c, maxChan);
2592                                                   continue;
2593                                         }
2594                                         if (next >= maxchans){
2595                                                   HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2596                                                       "%s: too many channels for channel table\n",
2597                                                       __func__);
2598                                                   goto done;
2599                                         }
2600                                         if ((fband->usePassScan & IS_ECM_CHAN) &&
2601                                             !enableExtendedChannels) {
2602                                                   HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2603                                                       "Skipping ecm channel\n");
2604                                                   continue;
2605                                         }
2606                                         /* XXX needs to be in ath_hal_checkchannel */
2607                                         if ((rd->flags & NO_HOSTAP) &&
2608                                             (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP)) {
2609                                                   HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2610                                                       "Skipping HOSTAP channel\n");
2611                                                   continue;
2612                                         }
2613                                         /*
2614                                          * Make sure that channel separation
2615                                          * meets the requirement.
2616                                          */
2617                                         if (lastc && channelSep &&
2618                                             (c-lastc) < channelSep)
2619                                                   continue;
2620 
2621                                         OS_MEMZERO(&icv, sizeof(icv));
2622                                         icv.channel = c;
2623                                         icv.channelFlags = cm->flags;
2624                                         icv.maxRegTxPower = fband->powerDfs;
2625                                         icv.antennaMax = fband->antennaMax;
2626                                         icv.regDmnFlags = rd->flags;
2627                                         icv.conformanceTestLimit = ctl;
2628                                         if (fband->usePassScan & rd->pscan)
2629                                                   icv.channelFlags |= CHANNEL_PASSIVE;
2630                                         else
2631                                                   icv.channelFlags &= ~CHANNEL_PASSIVE;
2632                                         lastc = c;
2633                                         if (fband->useDfs & rd->dfsMask) {
2634                                                   /* DFS and HT40 don't mix */
2635                                                   if (cm->mode == HAL_MODE_11NA_HT40PLUS ||
2636                                                       cm->mode == HAL_MODE_11NA_HT40MINUS)
2637                                                             continue;
2638                                                   icv.privFlags = CHANNEL_DFS;
2639                                         } else
2640                                                   icv.privFlags = 0;
2641                                         if (rd->flags & LIMIT_FRAME_4MS)
2642                                                   icv.privFlags |= CHANNEL_4MS_LIMIT;
2643 
2644                                         ichans[next++] = icv;
2645                               }
2646                     }
2647           }
2648 done:
2649           if (next != 0) {
2650                     int i;
2651 
2652                     /* XXX maxchans set above so this cannot happen? */
2653                     if (next > N(AH_PRIVATE(ah)->ah_channels)) {
2654                               HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2655                                   "%s: too many channels %u; truncating to %u\n",
2656                                   __func__, next,
2657                                   (int) N(AH_PRIVATE(ah)->ah_channels));
2658                               next = N(AH_PRIVATE(ah)->ah_channels);
2659                     }
2660 
2661                     /*
2662                      * Keep a private copy of the channel list so we can
2663                      * constrain future requests to only these channels
2664                      */
2665                     ath_hal_sort(ichans, next, sizeof(HAL_CHANNEL_INTERNAL),
2666                         chansort);
2667                     AH_PRIVATE(ah)->ah_nchan = next;
2668 
2669                     /*
2670                      * Copy the channel list to the public channel list
2671                      */
2672                     for (i = 0; i < next; i++) {
2673                               chans[i].channel = ichans[i].channel;
2674                               chans[i].channelFlags = ichans[i].channelFlags;
2675                               chans[i].privFlags = ichans[i].privFlags;
2676                               chans[i].maxRegTxPower = ichans[i].maxRegTxPower;
2677                     }
2678                     /*
2679                      * Retrieve power limits.
2680                      */
2681                     ath_hal_getpowerlimits(ah, chans, next);
2682                     for (i = 0; i < next; i++) {
2683                               ichans[i].maxTxPower = chans[i].maxTxPower;
2684                               ichans[i].minTxPower = chans[i].minTxPower;
2685                     }
2686           }
2687           *nchans = next;
2688           /* XXX copy private setting to public area */
2689           ah->ah_countryCode = AH_PRIVATE(ah)->ah_countryCode;
2690           return (next != 0);
2691 #undef CHANNEL_HALF_BW
2692 #undef CHANNEL_QUARTER_BW
2693 }
2694 
2695 /*
2696  * Return whether or not the specified channel is ok to use
2697  * based on the current regulatory domain constraints and
2698  * DFS interference.
2699  */
2700 HAL_CHANNEL_INTERNAL *
ath_hal_checkchannel(struct ath_hal * ah,const HAL_CHANNEL * c)2701 ath_hal_checkchannel(struct ath_hal *ah, const HAL_CHANNEL *c)
2702 {
2703 #define CHAN_FLAGS  (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)
2704           HAL_CHANNEL_INTERNAL *base, *cc;
2705           /* NB: be wary of user-specified channel flags */
2706           int flags = c->channelFlags & CHAN_FLAGS;
2707           int n, lim, d;
2708 
2709           /*
2710            * Check current channel to avoid the lookup.
2711            */
2712           cc = AH_PRIVATE(ah)->ah_curchan;
2713           if (cc != AH_NULL && cc->channel == c->channel &&
2714               (cc->channelFlags & CHAN_FLAGS) == flags) {
2715                     if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
2716                         (cc->channelFlags & CHANNEL_DFS))
2717                               return AH_NULL;
2718                     else
2719                               return cc;
2720           }
2721 
2722           /* binary search based on known sorting order */
2723           base = AH_PRIVATE(ah)->ah_channels;
2724           n = AH_PRIVATE(ah)->ah_nchan;
2725           /* binary search based on known sorting order */
2726           for (lim = n; lim != 0; lim >>= 1) {
2727                     cc = &base[lim>>1];
2728                     d = c->channel - cc->channel;
2729                     if (d == 0) {
2730                               if ((cc->channelFlags & CHAN_FLAGS) == flags) {
2731                                         if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
2732                                             (cc->channelFlags & CHANNEL_DFS))
2733                                                   return AH_NULL;
2734                                         else
2735                                                   return cc;
2736                               }
2737                               d = flags - (cc->channelFlags & CHAN_FLAGS);
2738                     }
2739                     if (d > 0) {
2740                               base = cc + 1;
2741                               lim--;
2742                     }
2743           }
2744           HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: no match for %u/0x%x\n",
2745              __func__, c->channel, c->channelFlags);
2746           return AH_NULL;
2747 #undef CHAN_FLAGS
2748 }
2749 
2750 /*
2751  * Return the max allowed antenna gain and apply any regulatory
2752  * domain specific changes.
2753  *
2754  * NOTE: a negative reduction is possible in RD's that only
2755  * measure radiated power (e.g., ETSI) which would increase
2756  * that actual conducted output power (though never beyond
2757  * the calibrated target power).
2758  */
2759 u_int
ath_hal_getantennareduction(struct ath_hal * ah,HAL_CHANNEL * chan,u_int twiceGain)2760 ath_hal_getantennareduction(struct ath_hal *ah, HAL_CHANNEL *chan, u_int twiceGain)
2761 {
2762           HAL_CHANNEL_INTERNAL *ichan=AH_NULL;
2763           int8_t antennaMax;
2764 
2765           if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL) {
2766                     antennaMax = twiceGain - ichan->antennaMax*2;
2767                     return (antennaMax < 0) ? 0 : antennaMax;
2768           } else {
2769                     /* Failed to find the correct index - may be a debug channel */
2770                     return 0;
2771           }
2772 }
2773 
2774 
2775 /* XXX - maybe move ctl decision into channel set area or
2776  into the tables so no decision is needed in the code */
2777 
2778 #define isWwrSKU(_ah) \
2779           ((getEepromRD((_ah)) & WORLD_SKU_MASK) == WORLD_SKU_PREFIX || \
2780             getEepromRD(_ah) == WORLD)
2781 
2782 
2783 /*
2784  * Return the test group from the specified channel from
2785  * the regulatory table.
2786  *
2787  * TODO: CTL for 11B CommonMode when regulatory domain is unknown
2788  */
2789 u_int
ath_hal_getctl(struct ath_hal * ah,HAL_CHANNEL * chan)2790 ath_hal_getctl(struct ath_hal *ah, HAL_CHANNEL *chan)
2791 {
2792           u_int ctl = NO_CTL;
2793           HAL_CHANNEL_INTERNAL *ichan;
2794 
2795           /* Special CTL to signify WWR SKU without a known country */
2796           if (AH_PRIVATE(ah)->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)) {
2797                     if (IS_CHAN_B(chan)) {
2798                               ctl = SD_NO_CTL | CTL_11B;
2799                     } else if (IS_CHAN_G(chan)) {
2800                               ctl = SD_NO_CTL | CTL_11G;
2801                     } else if (IS_CHAN_108G(chan)) {
2802                               ctl = SD_NO_CTL | CTL_108G;
2803                     } else if (IS_CHAN_T(chan)) {
2804                               ctl = SD_NO_CTL | CTL_TURBO;
2805                     } else {
2806                               ctl = SD_NO_CTL | CTL_11A;
2807                     }
2808           } else {
2809                     if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL) {
2810                               ctl = ichan->conformanceTestLimit;
2811                               /* limit 11G OFDM power */
2812                               if (IS_CHAN_PUREG(chan) &&
2813                                   (ctl & CTL_MODE_M) == CTL_11B)
2814                                         ctl = (ctl &~ CTL_MODE_M) | CTL_11G;
2815                     }
2816           }
2817           return ctl;
2818 }
2819 
2820 /*
2821  * Return whether or not a noise floor check is required in
2822  * the current regulatory domain for the specified channel.
2823  */
2824 HAL_BOOL
ath_hal_getnfcheckrequired(struct ath_hal * ah,HAL_CHANNEL * chan)2825 ath_hal_getnfcheckrequired(struct ath_hal *ah, HAL_CHANNEL *chan)
2826 {
2827           HAL_CHANNEL_INTERNAL *ichan;
2828 
2829           if ((ichan = ath_hal_checkchannel(ah, chan)) != AH_NULL)
2830                     return ((ichan->regDmnFlags & NEED_NFC) ? AH_TRUE : AH_FALSE);
2831           return AH_FALSE;
2832 }
2833 
2834 /*
2835  * Insertion sort.
2836  */
2837 #define swap(_a, _b, _size) {                     \
2838           uint8_t *s = _b;                        \
2839           int i = _size;                                    \
2840           do {                                              \
2841                     uint8_t tmp = *_a;            \
2842                     *_a++ = *s;                             \
2843                     *s++ = tmp;                             \
2844           } while (--i);                                    \
2845           _a -= _size;                                      \
2846 }
2847 
2848 static void
ath_hal_sort(void * a,size_t n,size_t size,ath_hal_cmp_t * cmp)2849 ath_hal_sort(void *a, size_t n, size_t size, ath_hal_cmp_t *cmp)
2850 {
2851           uint8_t *aa = a;
2852           uint8_t *ai, *t;
2853 
2854           for (ai = aa+size; --n >= 1; ai += size)
2855                     for (t = ai; t > aa; t -= size) {
2856                               uint8_t *u = t - size;
2857                               if (cmp(u, t) <= 0)
2858                                         break;
2859                               swap(u, t, size);
2860                     }
2861 }
2862