]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/ath/ath_hal/ah_regdomain.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / dev / ath / ath_hal / ah_regdomain.c
1 /*
2  * Copyright (c) 2002-2009 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  * $FreeBSD$
19  */
20 #include "opt_ah.h"
21
22 #include "ah.h"
23
24 #include <net80211/_ieee80211.h>
25 #include <net80211/ieee80211_regdomain.h>
26
27 #include "ah_internal.h"
28 #include "ah_eeprom.h"
29 #include "ah_devid.h"
30
31 /*
32  * XXX this code needs a audit+review
33  */
34
35 /* used throughout this file... */
36 #define N(a)    (sizeof (a) / sizeof (a[0]))
37
38 #define HAL_MODE_11A_TURBO      HAL_MODE_108A
39 #define HAL_MODE_11G_TURBO      HAL_MODE_108G
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 #define BM9(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi)        \
78         { W0(_fa) | W0(_fb) | W0(_fc) | W0(_fd) | W0(_fe) | W0(_ff) |   \
79           W0(_fg) | W0(_fh) | W0(_fi) , \
80           W1(_fa) | W1(_fb) | W1(_fc) | W1(_fd) | W1(_fe) | W1(_ff) |   \
81           W1(_fg) | W1(_fh) | W1(_fi) }
82
83 /*
84  * Mask to check whether a domain is a multidomain or a single domain
85  */
86 #define MULTI_DOMAIN_MASK 0xFF00
87
88 /*
89  * Enumerated Regulatory Domain Information 8 bit values indicate that
90  * the regdomain is really a pair of unitary regdomains.  12 bit values
91  * are the real unitary regdomains and are the only ones which have the
92  * frequency bitmasks and flags set.
93  */
94 enum {
95         /*
96          * The following regulatory domain definitions are
97          * found in the EEPROM. Each regulatory domain
98          * can operate in either a 5GHz or 2.4GHz wireless mode or
99          * both 5GHz and 2.4GHz wireless modes.
100          * In general, the value holds no special
101          * meaning and is used to decode into either specific
102          * 2.4GHz or 5GHz wireless mode for that particular
103          * regulatory domain.
104          */
105         NO_ENUMRD       = 0x00,
106         NULL1_WORLD     = 0x03,         /* For 11b-only countries (no 11a allowed) */
107         NULL1_ETSIB     = 0x07,         /* Israel */
108         NULL1_ETSIC     = 0x08,
109         FCC1_FCCA       = 0x10,         /* USA */
110         FCC1_WORLD      = 0x11,         /* Hong Kong */
111         FCC4_FCCA       = 0x12,         /* USA - Public Safety */
112         FCC5_FCCB       = 0x13,         /* USA w/ 1/2 and 1/4 width channels */
113
114         FCC2_FCCA       = 0x20,         /* Canada */
115         FCC2_WORLD      = 0x21,         /* Australia & HK */
116         FCC2_ETSIC      = 0x22,
117         FRANCE_RES      = 0x31,         /* Legacy France for OEM */
118         FCC3_FCCA       = 0x3A,         /* USA & Canada w/5470 band, 11h, DFS enabled */
119         FCC3_WORLD      = 0x3B,         /* USA & Canada w/5470 band, 11h, DFS enabled */
120
121         ETSI1_WORLD     = 0x37,
122         ETSI3_ETSIA     = 0x32,         /* France (optional) */
123         ETSI2_WORLD     = 0x35,         /* Hungary & others */
124         ETSI3_WORLD     = 0x36,         /* France & others */
125         ETSI4_WORLD     = 0x30,
126         ETSI4_ETSIC     = 0x38,
127         ETSI5_WORLD     = 0x39,
128         ETSI6_WORLD     = 0x34,         /* Bulgaria */
129         ETSI_RESERVED   = 0x33,         /* Reserved (Do not used) */
130
131         MKK1_MKKA       = 0x40,         /* Japan (JP1) */
132         MKK1_MKKB       = 0x41,         /* Japan (JP0) */
133         APL4_WORLD      = 0x42,         /* Singapore */
134         MKK2_MKKA       = 0x43,         /* Japan with 4.9G channels */
135         APL_RESERVED    = 0x44,         /* Reserved (Do not used)  */
136         APL2_WORLD      = 0x45,         /* Korea */
137         APL2_APLC       = 0x46,
138         APL3_WORLD      = 0x47,
139         MKK1_FCCA       = 0x48,         /* Japan (JP1-1) */
140         APL2_APLD       = 0x49,         /* Korea with 2.3G channels */
141         MKK1_MKKA1      = 0x4A,         /* Japan (JE1) */
142         MKK1_MKKA2      = 0x4B,         /* Japan (JE2) */
143         MKK1_MKKC       = 0x4C,         /* Japan (MKK1_MKKA,except Ch14) */
144
145         APL3_FCCA       = 0x50,
146         APL1_WORLD      = 0x52,         /* Latin America */
147         APL1_FCCA       = 0x53,
148         APL1_APLA       = 0x54,
149         APL1_ETSIC      = 0x55,
150         APL2_ETSIC      = 0x56,         /* Venezuela */
151         APL5_WORLD      = 0x58,         /* Chile */
152         APL6_WORLD      = 0x5B,         /* Singapore */
153         APL7_FCCA       = 0x5C,         /* Taiwan 5.47 Band */
154         APL8_WORLD      = 0x5D,         /* Malaysia 5GHz */
155         APL9_WORLD      = 0x5E,         /* Korea 5GHz */
156
157         /*
158          * World mode SKUs
159          */
160         WOR0_WORLD      = 0x60,         /* World0 (WO0 SKU) */
161         WOR1_WORLD      = 0x61,         /* World1 (WO1 SKU) */
162         WOR2_WORLD      = 0x62,         /* World2 (WO2 SKU) */
163         WOR3_WORLD      = 0x63,         /* World3 (WO3 SKU) */
164         WOR4_WORLD      = 0x64,         /* World4 (WO4 SKU) */  
165         WOR5_ETSIC      = 0x65,         /* World5 (WO5 SKU) */    
166
167         WOR01_WORLD     = 0x66,         /* World0-1 (WW0-1 SKU) */
168         WOR02_WORLD     = 0x67,         /* World0-2 (WW0-2 SKU) */
169         EU1_WORLD       = 0x68,         /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */
170
171         WOR9_WORLD      = 0x69,         /* World9 (WO9 SKU) */  
172         WORA_WORLD      = 0x6A,         /* WorldA (WOA SKU) */  
173         WORB_WORLD      = 0x6B,         /* WorldB (WOB SKU) */
174
175         MKK3_MKKB       = 0x80,         /* Japan UNI-1 even + MKKB */
176         MKK3_MKKA2      = 0x81,         /* Japan UNI-1 even + MKKA2 */
177         MKK3_MKKC       = 0x82,         /* Japan UNI-1 even + MKKC */
178
179         MKK4_MKKB       = 0x83,         /* Japan UNI-1 even + UNI-2 + MKKB */
180         MKK4_MKKA2      = 0x84,         /* Japan UNI-1 even + UNI-2 + MKKA2 */
181         MKK4_MKKC       = 0x85,         /* Japan UNI-1 even + UNI-2 + MKKC */
182
183         MKK5_MKKB       = 0x86,         /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */
184         MKK5_MKKA2      = 0x87,         /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */
185         MKK5_MKKC       = 0x88,         /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */
186
187         MKK6_MKKB       = 0x89,         /* Japan UNI-1 even + UNI-1 odd MKKB */
188         MKK6_MKKA2      = 0x8A,         /* Japan UNI-1 even + UNI-1 odd + MKKA2 */
189         MKK6_MKKC       = 0x8B,         /* Japan UNI-1 even + UNI-1 odd + MKKC */
190
191         MKK7_MKKB       = 0x8C,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */
192         MKK7_MKKA2      = 0x8D,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */
193         MKK7_MKKC       = 0x8E,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */
194
195         MKK8_MKKB       = 0x8F,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */
196         MKK8_MKKA2      = 0x90,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */
197         MKK8_MKKC       = 0x91,         /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */
198
199         /* Following definitions are used only by s/w to map old
200          * Japan SKUs.
201          */
202         MKK3_MKKA       = 0xF0,         /* Japan UNI-1 even + MKKA */
203         MKK3_MKKA1      = 0xF1,         /* Japan UNI-1 even + MKKA1 */
204         MKK3_FCCA       = 0xF2,         /* Japan UNI-1 even + FCCA */
205         MKK4_MKKA       = 0xF3,         /* Japan UNI-1 even + UNI-2 + MKKA */
206         MKK4_MKKA1      = 0xF4,         /* Japan UNI-1 even + UNI-2 + MKKA1 */
207         MKK4_FCCA       = 0xF5,         /* Japan UNI-1 even + UNI-2 + FCCA */
208         MKK9_MKKA       = 0xF6,         /* Japan UNI-1 even + 4.9GHz */
209         MKK10_MKKA      = 0xF7,         /* Japan UNI-1 even + UNI-2 + 4.9GHz */
210
211         /*
212          * Regulator domains ending in a number (e.g. APL1,
213          * MK1, ETSI4, etc) apply to 5GHz channel and power
214          * information.  Regulator domains ending in a letter
215          * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and
216          * power information.
217          */
218         APL1            = 0x0150,       /* LAT & Asia */
219         APL2            = 0x0250,       /* LAT & Asia */
220         APL3            = 0x0350,       /* Taiwan */
221         APL4            = 0x0450,       /* Jordan */
222         APL5            = 0x0550,       /* Chile */
223         APL6            = 0x0650,       /* Singapore */
224         APL8            = 0x0850,       /* Malaysia */
225         APL9            = 0x0950,       /* Korea (South) ROC 3 */
226
227         ETSI1           = 0x0130,       /* Europe & others */
228         ETSI2           = 0x0230,       /* Europe & others */
229         ETSI3           = 0x0330,       /* Europe & others */
230         ETSI4           = 0x0430,       /* Europe & others */
231         ETSI5           = 0x0530,       /* Europe & others */
232         ETSI6           = 0x0630,       /* Europe & others */
233         ETSIA           = 0x0A30,       /* France */
234         ETSIB           = 0x0B30,       /* Israel */
235         ETSIC           = 0x0C30,       /* Latin America */
236
237         FCC1            = 0x0110,       /* US & others */
238         FCC2            = 0x0120,       /* Canada, Australia & New Zealand */
239         FCC3            = 0x0160,       /* US w/new middle band & DFS */    
240         FCC4            = 0x0165,       /* US Public Safety */
241         FCC5            = 0x0166,       /* US w/ 1/2 and 1/4 width channels */
242         FCCA            = 0x0A10,        
243         FCCB            = 0x0A11,       /* US w/ 1/2 and 1/4 width channels */
244
245         APLD            = 0x0D50,       /* South Korea */
246
247         MKK1            = 0x0140,       /* Japan (UNI-1 odd)*/
248         MKK2            = 0x0240,       /* Japan (4.9 GHz + UNI-1 odd) */
249         MKK3            = 0x0340,       /* Japan (UNI-1 even) */
250         MKK4            = 0x0440,       /* Japan (UNI-1 even + UNI-2) */
251         MKK5            = 0x0540,       /* Japan (UNI-1 even + UNI-2 + mid-band) */
252         MKK6            = 0x0640,       /* Japan (UNI-1 odd + UNI-1 even) */
253         MKK7            = 0x0740,       /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */
254         MKK8            = 0x0840,       /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */
255         MKK9            = 0x0940,       /* Japan (UNI-1 even + 4.9 GHZ) */
256         MKK10           = 0x0B40,       /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
257         MKKA            = 0x0A40,       /* Japan */
258         MKKC            = 0x0A50,
259
260         NULL1           = 0x0198,
261         WORLD           = 0x0199,
262         DEBUG_REG_DMN   = 0x01ff,
263 };
264
265 #define WORLD_SKU_MASK          0x00F0
266 #define WORLD_SKU_PREFIX        0x0060
267
268 enum {                                  /* conformance test limits */
269         FCC     = 0x10,
270         MKK     = 0x40,
271         ETSI    = 0x30,
272 };
273
274 /*
275  * The following are flags for different requirements per reg domain.
276  * These requirements are either inhereted from the reg domain pair or
277  * from the unitary reg domain if the reg domain pair flags value is 0
278  */
279 enum {
280         NO_REQ                  = 0x00000000,   /* NB: must be zero */
281         DISALLOW_ADHOC_11A      = 0x00000001,   /* adhoc not allowed in 5GHz */
282         DISALLOW_ADHOC_11A_TURB = 0x00000002,   /* not allowed w/ 5GHz turbo */
283         NEED_NFC                = 0x00000004,   /* need noise floor check */
284         ADHOC_PER_11D           = 0x00000008,   /* must receive 11d beacon */
285         LIMIT_FRAME_4MS         = 0x00000020,   /* 4msec tx burst limit */
286         NO_HOSTAP               = 0x00000040,   /* No HOSTAP mode opereation */
287 };
288
289 /*
290  * The following describe the bit masks for different passive scan
291  * capability/requirements per regdomain.
292  */
293 #define NO_PSCAN        0x0ULL                  /* NB: must be zero */
294 #define PSCAN_FCC       0x0000000000000001ULL
295 #define PSCAN_FCC_T     0x0000000000000002ULL
296 #define PSCAN_ETSI      0x0000000000000004ULL
297 #define PSCAN_MKK1      0x0000000000000008ULL
298 #define PSCAN_MKK2      0x0000000000000010ULL
299 #define PSCAN_MKKA      0x0000000000000020ULL
300 #define PSCAN_MKKA_G    0x0000000000000040ULL
301 #define PSCAN_ETSIA     0x0000000000000080ULL
302 #define PSCAN_ETSIB     0x0000000000000100ULL
303 #define PSCAN_ETSIC     0x0000000000000200ULL
304 #define PSCAN_WWR       0x0000000000000400ULL
305 #define PSCAN_MKKA1     0x0000000000000800ULL
306 #define PSCAN_MKKA1_G   0x0000000000001000ULL
307 #define PSCAN_MKKA2     0x0000000000002000ULL
308 #define PSCAN_MKKA2_G   0x0000000000004000ULL
309 #define PSCAN_MKK3      0x0000000000008000ULL
310 #define PSCAN_DEFER     0x7FFFFFFFFFFFFFFFULL
311 #define IS_ECM_CHAN     0x8000000000000000ULL
312
313 /*
314  * THE following table is the mapping of regdomain pairs specified by
315  * an 8 bit regdomain value to the individual unitary reg domains
316  */
317 typedef struct regDomainPair {
318         HAL_REG_DOMAIN regDmnEnum;      /* 16 bit reg domain pair */
319         HAL_REG_DOMAIN regDmn5GHz;      /* 5GHz reg domain */
320         HAL_REG_DOMAIN regDmn2GHz;      /* 2GHz reg domain */
321         uint32_t flags5GHz;             /* Requirements flags (AdHoc
322                                            disallow, noise floor cal needed,
323                                            etc) */
324         uint32_t flags2GHz;             /* Requirements flags (AdHoc
325                                            disallow, noise floor cal needed,
326                                            etc) */
327         uint64_t pscanMask;             /* Passive Scan flags which
328                                            can override unitary domain
329                                            passive scan flags.  This
330                                            value is used as a mask on
331                                            the unitary flags*/
332         uint16_t singleCC;              /* Country code of single country if
333                                            a one-on-one mapping exists */
334 }  REG_DMN_PAIR_MAPPING;
335
336 static REG_DMN_PAIR_MAPPING regDomainPairs[] = {
337         {NO_ENUMRD,     DEBUG_REG_DMN,  DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
338         {NULL1_WORLD,   NULL1,          WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
339         {NULL1_ETSIB,   NULL1,          ETSIB,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
340         {NULL1_ETSIC,   NULL1,          ETSIC,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
341
342         {FCC2_FCCA,     FCC2,           FCCA,           NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
343         {FCC2_WORLD,    FCC2,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
344         {FCC2_ETSIC,    FCC2,           ETSIC,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
345         {FCC3_FCCA,     FCC3,           FCCA,           NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
346         {FCC3_WORLD,    FCC3,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
347         {FCC4_FCCA,     FCC4,           FCCA,           DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
348         {FCC5_FCCB,     FCC5,           FCCB,           NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
349
350         {ETSI1_WORLD,   ETSI1,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
351         {ETSI2_WORLD,   ETSI2,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
352         {ETSI3_WORLD,   ETSI3,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
353         {ETSI4_WORLD,   ETSI4,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
354         {ETSI5_WORLD,   ETSI5,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
355         {ETSI6_WORLD,   ETSI6,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
356
357         {ETSI3_ETSIA,   ETSI3,          WORLD,          DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
358         {FRANCE_RES,    ETSI3,          WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
359
360         {FCC1_WORLD,    FCC1,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
361         {FCC1_FCCA,     FCC1,           FCCA,           NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
362         {APL1_WORLD,    APL1,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
363         {APL2_WORLD,    APL2,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
364         {APL3_WORLD,    APL3,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
365         {APL4_WORLD,    APL4,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
366         {APL5_WORLD,    APL5,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
367         {APL6_WORLD,    APL6,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
368         {APL8_WORLD,    APL8,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
369         {APL9_WORLD,    APL9,           WORLD,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
370
371         {APL3_FCCA,     APL3,           FCCA,           NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
372         {APL1_ETSIC,    APL1,           ETSIC,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
373         {APL2_ETSIC,    APL2,           ETSIC,          NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
374         {APL2_APLD,     APL2,           APLD,           NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
375
376         {MKK1_MKKA,     MKK1,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN },
377         {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 },
378         {MKK1_FCCA,     MKK1,           FCCA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 },
379         {MKK1_MKKA1,    MKK1,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 },
380         {MKK1_MKKA2,    MKK1,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 },
381         {MKK1_MKKC,     MKK1,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 },
382
383         /* MKK2 */
384         {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 },
385
386         /* MKK3 */
387         {MKK3_MKKA,     MKK3,   MKKA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, CTRY_DEFAULT },
388         {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 },
389         {MKK3_MKKA1,    MKK3,   MKKA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_DEFAULT },
390         {MKK3_MKKA2,MKK3,               MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 },
391         {MKK3_MKKC,     MKK3,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 },
392         {MKK3_FCCA,     MKK3,   FCCA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_DEFAULT },
393
394         /* MKK4 */
395         {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 },
396         {MKK4_MKKA1,    MKK4,   MKKA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_DEFAULT },
397         {MKK4_MKKA2,    MKK4,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 },
398         {MKK4_MKKC,     MKK4,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 },
399         {MKK4_FCCA,     MKK4,   FCCA,   DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_DEFAULT },
400
401         /* MKK5 */
402         {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 },
403         {MKK5_MKKA2,MKK5,               MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 },
404         {MKK5_MKKC,     MKK5,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 },
405
406         /* MKK6 */
407         {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 },
408         {MKK6_MKKA2,    MKK6,           MKKA,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 },
409         {MKK6_MKKC,     MKK6,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 },
410
411         /* MKK7 */
412         {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 },
413         {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 },
414         {MKK7_MKKC,     MKK7,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 },
415
416         /* MKK8 */
417         {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 },
418         {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 },
419         {MKK8_MKKC,     MKK8,           MKKC,           DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 },
420
421         {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, CTRY_DEFAULT },
422         {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, CTRY_DEFAULT },
423
424                 /* These are super domains */
425         {WOR0_WORLD,    WOR0_WORLD,     WOR0_WORLD,     NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
426         {WOR1_WORLD,    WOR1_WORLD,     WOR1_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
427         {WOR2_WORLD,    WOR2_WORLD,     WOR2_WORLD,     DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
428         {WOR3_WORLD,    WOR3_WORLD,     WOR3_WORLD,     NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
429         {WOR4_WORLD,    WOR4_WORLD,     WOR4_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
430         {WOR5_ETSIC,    WOR5_ETSIC,     WOR5_ETSIC,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
431         {WOR01_WORLD,   WOR01_WORLD,    WOR01_WORLD,    NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
432         {WOR02_WORLD,   WOR02_WORLD,    WOR02_WORLD,    NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
433         {EU1_WORLD,     EU1_WORLD,      EU1_WORLD,      NO_REQ, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
434         {WOR9_WORLD,    WOR9_WORLD,     WOR9_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
435         {WORA_WORLD,    WORA_WORLD,     WORA_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
436         {WORB_WORLD,    WORB_WORLD,     WORB_WORLD,     DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, CTRY_DEFAULT },
437 };
438
439 /* 
440  * The following tables are the master list for all different freqeuncy
441  * bands with the complete matrix of all possible flags and settings
442  * for each band if it is used in ANY reg domain.
443  */
444
445 #define DEF_REGDMN              FCC1_FCCA
446 #define COUNTRY_ERD_FLAG        0x8000
447 #define WORLDWIDE_ROAMING_FLAG  0x4000
448
449 typedef struct {
450         HAL_CTRY_CODE           countryCode;       
451         HAL_REG_DOMAIN          regDmnEnum;
452 } COUNTRY_CODE_TO_ENUM_RD;
453
454 static COUNTRY_CODE_TO_ENUM_RD allCountries[] = {
455         { CTRY_DEBUG,       NO_ENUMRD },
456         { CTRY_DEFAULT,     DEF_REGDMN },
457         { CTRY_ALBANIA,     NULL1_WORLD },
458         { CTRY_ALGERIA,     NULL1_WORLD },
459         { CTRY_ARGENTINA,   APL3_WORLD },
460         { CTRY_ARMENIA,     ETSI4_WORLD },
461         { CTRY_AUSTRALIA,   FCC2_WORLD },
462         { CTRY_AUSTRIA,     ETSI1_WORLD },
463         { CTRY_AZERBAIJAN,  ETSI4_WORLD },
464         { CTRY_BAHRAIN,     APL6_WORLD },
465         { CTRY_BELARUS,     NULL1_WORLD },
466         { CTRY_BELGIUM,     ETSI1_WORLD },
467         { CTRY_BELIZE,      APL1_ETSIC },
468         { CTRY_BOLIVIA,     APL1_ETSIC },
469         { CTRY_BRAZIL,      FCC3_WORLD },
470         { CTRY_BRUNEI_DARUSSALAM,APL1_WORLD },
471         { CTRY_BULGARIA,    ETSI6_WORLD },
472         { CTRY_CANADA,      FCC2_FCCA },
473         { CTRY_CHILE,       APL6_WORLD },
474         { CTRY_CHINA,       APL1_WORLD },
475         { CTRY_COLOMBIA,    FCC1_FCCA },
476         { CTRY_COSTA_RICA,  NULL1_WORLD },
477         { CTRY_CROATIA,     ETSI3_WORLD },
478         { CTRY_CYPRUS,      ETSI1_WORLD },
479         { CTRY_CZECH,       ETSI1_WORLD },
480         { CTRY_DENMARK,     ETSI1_WORLD },
481         { CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA },
482         { CTRY_ECUADOR,     NULL1_WORLD },
483         { CTRY_EGYPT,       ETSI3_WORLD },
484         { CTRY_EL_SALVADOR, NULL1_WORLD },
485         { CTRY_ESTONIA,     ETSI1_WORLD },
486         { CTRY_FINLAND,     ETSI1_WORLD },
487         { CTRY_FRANCE,      ETSI1_WORLD },
488         { CTRY_FRANCE2,     ETSI3_WORLD },
489         { CTRY_GEORGIA,     ETSI4_WORLD },
490         { CTRY_GERMANY,     ETSI1_WORLD },
491         { CTRY_GREECE,      ETSI1_WORLD },
492         { CTRY_GUATEMALA,   FCC1_FCCA },
493         { CTRY_HONDURAS,    NULL1_WORLD },
494         { CTRY_HONG_KONG,   FCC2_WORLD },
495         { CTRY_HUNGARY,     ETSI1_WORLD },
496         { CTRY_ICELAND,     ETSI1_WORLD },
497         { CTRY_INDIA,       APL6_WORLD },
498         { CTRY_INDONESIA,   APL1_WORLD },
499         { CTRY_IRAN,        APL1_WORLD },
500         { CTRY_IRELAND,     ETSI1_WORLD },
501         { CTRY_ISRAEL,      NULL1_WORLD },
502         { CTRY_ITALY,       ETSI1_WORLD },
503         { CTRY_JAPAN,       MKK1_MKKA },
504         { CTRY_JAPAN1,      MKK1_MKKB },
505         { CTRY_JAPAN2,      MKK1_FCCA },
506         { CTRY_JAPAN3,      MKK2_MKKA },
507         { CTRY_JAPAN4,      MKK1_MKKA1 },
508         { CTRY_JAPAN5,      MKK1_MKKA2 },
509         { CTRY_JAPAN6,      MKK1_MKKC },
510
511         { CTRY_JAPAN7,      MKK3_MKKB },
512         { CTRY_JAPAN8,      MKK3_MKKA2 },
513         { CTRY_JAPAN9,      MKK3_MKKC },
514
515         { CTRY_JAPAN10,     MKK4_MKKB },
516         { CTRY_JAPAN11,     MKK4_MKKA2 },
517         { CTRY_JAPAN12,     MKK4_MKKC },
518
519         { CTRY_JAPAN13,     MKK5_MKKB },
520         { CTRY_JAPAN14,     MKK5_MKKA2 },
521         { CTRY_JAPAN15,     MKK5_MKKC },
522
523         { CTRY_JAPAN16,     MKK6_MKKB },
524         { CTRY_JAPAN17,     MKK6_MKKA2 },
525         { CTRY_JAPAN18,     MKK6_MKKC },
526
527         { CTRY_JAPAN19,     MKK7_MKKB },
528         { CTRY_JAPAN20,     MKK7_MKKA2 },
529         { CTRY_JAPAN21,     MKK7_MKKC },
530
531         { CTRY_JAPAN22,     MKK8_MKKB },
532         { CTRY_JAPAN23,     MKK8_MKKA2 },
533         { CTRY_JAPAN24,     MKK8_MKKC },
534
535         { CTRY_JORDAN,      APL4_WORLD },
536         { CTRY_KAZAKHSTAN,  NULL1_WORLD },
537         { CTRY_KOREA_NORTH, APL2_WORLD },
538         { CTRY_KOREA_ROC,   APL2_WORLD },
539         { CTRY_KOREA_ROC2,  APL2_WORLD },
540         { CTRY_KOREA_ROC3,  APL9_WORLD },
541         { CTRY_KUWAIT,      NULL1_WORLD },
542         { CTRY_LATVIA,      ETSI1_WORLD },
543         { CTRY_LEBANON,     NULL1_WORLD },
544         { CTRY_LIECHTENSTEIN,ETSI1_WORLD },
545         { CTRY_LITHUANIA,   ETSI1_WORLD },
546         { CTRY_LUXEMBOURG,  ETSI1_WORLD },
547         { CTRY_MACAU,       FCC2_WORLD },
548         { CTRY_MACEDONIA,   NULL1_WORLD },
549         { CTRY_MALAYSIA,    APL8_WORLD },
550         { CTRY_MALTA,       ETSI1_WORLD },
551         { CTRY_MEXICO,      FCC1_FCCA },
552         { CTRY_MONACO,      ETSI4_WORLD },
553         { CTRY_MOROCCO,     NULL1_WORLD },
554         { CTRY_NETHERLANDS, ETSI1_WORLD },
555         { CTRY_NEW_ZEALAND, FCC2_ETSIC },
556         { CTRY_NORWAY,      ETSI1_WORLD },
557         { CTRY_OMAN,        APL6_WORLD },
558         { CTRY_PAKISTAN,    NULL1_WORLD },
559         { CTRY_PANAMA,      FCC1_FCCA },
560         { CTRY_PERU,        APL1_WORLD },
561         { CTRY_PHILIPPINES, FCC3_WORLD },
562         { CTRY_POLAND,      ETSI1_WORLD },
563         { CTRY_PORTUGAL,    ETSI1_WORLD },
564         { CTRY_PUERTO_RICO, FCC1_FCCA },
565         { CTRY_QATAR,       NULL1_WORLD },
566         { CTRY_ROMANIA,     NULL1_WORLD },
567         { CTRY_RUSSIA,      NULL1_WORLD },
568         { CTRY_SAUDI_ARABIA,FCC2_WORLD },
569         { CTRY_SINGAPORE,   APL6_WORLD },
570         { CTRY_SLOVAKIA,    ETSI1_WORLD },
571         { CTRY_SLOVENIA,    ETSI1_WORLD },
572         { CTRY_SOUTH_AFRICA,FCC3_WORLD },
573         { CTRY_SPAIN,       ETSI1_WORLD },
574         { CTRY_SWEDEN,      ETSI1_WORLD },
575         { CTRY_SWITZERLAND, ETSI1_WORLD },
576         { CTRY_SYRIA,       NULL1_WORLD },
577         { CTRY_TAIWAN,      APL3_FCCA },
578         { CTRY_THAILAND,    NULL1_WORLD },
579         { CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD },
580         { CTRY_TUNISIA,     ETSI3_WORLD },
581         { CTRY_TURKEY,      ETSI3_WORLD },
582         { CTRY_UKRAINE,     NULL1_WORLD },
583         { CTRY_UAE,         NULL1_WORLD },
584         { CTRY_UNITED_KINGDOM, ETSI1_WORLD },
585         { CTRY_UNITED_STATES, FCC1_FCCA },
586         { CTRY_UNITED_STATES_FCC49,FCC4_FCCA },
587         { CTRY_URUGUAY,     FCC1_WORLD },
588         { CTRY_UZBEKISTAN,  FCC3_FCCA },
589         { CTRY_VENEZUELA,   APL2_ETSIC },
590         { CTRY_VIET_NAM,    NULL1_WORLD },
591         { CTRY_ZIMBABWE,    NULL1_WORLD }
592 };
593
594 /* Bit masks for DFS per regdomain */
595 enum {
596         NO_DFS   = 0x0000000000000000ULL,       /* NB: must be zero */
597         DFS_FCC3 = 0x0000000000000001ULL,
598         DFS_ETSI = 0x0000000000000002ULL,
599         DFS_MKK4 = 0x0000000000000004ULL,
600 };
601
602 #define AFTER(x)        ((x)+1)
603
604 /*
605  * Frequency band collections are defined using bitmasks.  Each bit
606  * in a mask is the index of an entry in one of the following tables.
607  * Bitmasks are BMLEN*64 bits so if a table grows beyond that the bit
608  * vectors must be enlarged or the tables split somehow (e.g. split
609  * 1/2 and 1/4 rate channels into a separate table).
610  *
611  * Beware of ordering; the indices are defined relative to the preceding
612  * entry so if things get off there will be confusion.  A good way to
613  * check the indices is to collect them in a switch statement in a stub
614  * function so the compiler checks for duplicates.
615  */
616
617 typedef struct {
618         uint16_t        lowChannel;     /* Low channel center in MHz */
619         uint16_t        highChannel;    /* High Channel center in MHz */
620         uint8_t         powerDfs;       /* Max power (dBm) for channel
621                                            range when using DFS */
622         uint8_t         antennaMax;     /* Max allowed antenna gain */
623         uint8_t         channelBW;      /* Bandwidth of the channel */
624         uint8_t         channelSep;     /* Channel separation within
625                                            the band */
626         uint64_t        useDfs;         /* Use DFS in the RegDomain
627                                            if corresponding bit is set */
628         uint64_t        usePassScan;    /* Use Passive Scan in the RegDomain
629                                            if corresponding bit is set */
630 } REG_DMN_FREQ_BAND;
631
632 /*
633  * 5GHz 11A channel tags
634  */
635 static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = {
636         { 4915, 4925, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2 },
637 #define F1_4915_4925    0
638         { 4935, 4945, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2 },
639 #define F1_4935_4945    AFTER(F1_4915_4925)
640         { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2 },
641 #define F1_4920_4980    AFTER(F1_4935_4945)
642         { 4942, 4987, 27, 6,  5,  5, NO_DFS, PSCAN_FCC },
643 #define F1_4942_4987    AFTER(F1_4920_4980)
644         { 4945, 4985, 30, 6, 10,  5, NO_DFS, PSCAN_FCC },
645 #define F1_4945_4985    AFTER(F1_4942_4987)
646         { 4950, 4980, 33, 6, 20,  5, NO_DFS, PSCAN_FCC },
647 #define F1_4950_4980    AFTER(F1_4945_4985)
648         { 5035, 5040, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2 },
649 #define F1_5035_5040    AFTER(F1_4950_4980)
650         { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2 },
651 #define F1_5040_5080    AFTER(F1_5035_5040)
652         { 5055, 5055, 23, 0, 10,  5, NO_DFS, PSCAN_MKK2 },
653 #define F1_5055_5055    AFTER(F1_5040_5080)
654
655         { 5120, 5240, 5,  6, 20, 20, NO_DFS, NO_PSCAN },
656 #define F1_5120_5240    AFTER(F1_5055_5055)
657         { 5120, 5240, 5,  6, 10, 10, NO_DFS, NO_PSCAN },
658 #define F2_5120_5240    AFTER(F1_5120_5240)
659         { 5120, 5240, 5,  6,  5,  5, NO_DFS, NO_PSCAN },
660 #define F3_5120_5240    AFTER(F2_5120_5240)
661
662         { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2 },
663 #define F1_5170_5230    AFTER(F3_5120_5240)
664         { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2 },
665 #define F2_5170_5230    AFTER(F1_5170_5230)
666
667         { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI },
668 #define F1_5180_5240    AFTER(F2_5170_5230)
669         { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC },
670 #define F2_5180_5240    AFTER(F1_5180_5240)
671         { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI },
672 #define F3_5180_5240    AFTER(F2_5180_5240)
673         { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI },
674 #define F4_5180_5240    AFTER(F3_5180_5240)
675         { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI },
676 #define F5_5180_5240    AFTER(F4_5180_5240)
677         { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC },
678 #define F6_5180_5240    AFTER(F5_5180_5240)
679         { 5180, 5240, 17, 6, 20, 10, NO_DFS, PSCAN_FCC },
680 #define F7_5180_5240    AFTER(F6_5180_5240)
681         { 5180, 5240, 17, 6, 20,  5, NO_DFS, PSCAN_FCC },
682 #define F8_5180_5240    AFTER(F7_5180_5240)
683         { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI },
684
685 #define F1_5180_5320    AFTER(F8_5180_5240)
686         { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI },
687
688 #define F1_5240_5280    AFTER(F1_5180_5320)
689         { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI },
690
691 #define F1_5260_5280    AFTER(F1_5240_5280)
692         { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI },
693
694 #define F1_5260_5320    AFTER(F1_5260_5280)
695         { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3  },
696 #define F2_5260_5320    AFTER(F1_5260_5320)
697
698         { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC },
699 #define F3_5260_5320    AFTER(F2_5260_5320)
700         { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC },
701 #define F4_5260_5320    AFTER(F3_5260_5320)
702         { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC },
703 #define F5_5260_5320    AFTER(F4_5260_5320)
704         { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN },
705 #define F6_5260_5320    AFTER(F5_5260_5320)
706         { 5260, 5320, 23, 6, 20, 10, DFS_FCC3 | DFS_ETSI, PSCAN_FCC },
707 #define F7_5260_5320    AFTER(F6_5260_5320)
708         { 5260, 5320, 23, 6, 20,  5, DFS_FCC3 | DFS_ETSI, PSCAN_FCC },
709 #define F8_5260_5320    AFTER(F7_5260_5320)
710
711         { 5260, 5700, 5,  6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN },
712 #define F1_5260_5700    AFTER(F8_5260_5320)
713         { 5260, 5700, 5,  6, 10, 10, DFS_FCC3 | DFS_ETSI, NO_PSCAN },
714 #define F2_5260_5700    AFTER(F1_5260_5700)
715         { 5260, 5700, 5,  6,  5,  5, DFS_FCC3 | DFS_ETSI, NO_PSCAN },
716 #define F3_5260_5700    AFTER(F2_5260_5700)
717
718         { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC },
719 #define F1_5280_5320    AFTER(F3_5260_5700)
720
721         { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI },
722 #define F1_5500_5620    AFTER(F1_5280_5320)
723
724         { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC },
725 #define F1_5500_5700    AFTER(F1_5500_5620)
726         { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI },
727 #define F2_5500_5700    AFTER(F1_5500_5700)
728         { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI },
729 #define F3_5500_5700    AFTER(F2_5500_5700)
730         { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC },
731 #define F4_5500_5700    AFTER(F3_5500_5700)
732
733         { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN },
734 #define F1_5745_5805    AFTER(F4_5500_5700)
735         { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN },
736 #define F2_5745_5805    AFTER(F1_5745_5805)
737         { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI },
738 #define F3_5745_5805    AFTER(F2_5745_5805)
739         { 5745, 5825, 5,  6, 20, 20, NO_DFS, NO_PSCAN },
740 #define F1_5745_5825    AFTER(F3_5745_5805)
741         { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN },
742 #define F2_5745_5825    AFTER(F1_5745_5825)
743         { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN },
744 #define F3_5745_5825    AFTER(F2_5745_5825)
745         { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN },
746 #define F4_5745_5825    AFTER(F3_5745_5825)
747         { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN },
748 #define F5_5745_5825    AFTER(F4_5745_5825)
749         { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN },
750 #define F6_5745_5825    AFTER(F5_5745_5825)
751         { 5745, 5825, 5,  6, 10, 10, NO_DFS, NO_PSCAN },
752 #define F7_5745_5825    AFTER(F6_5745_5825)
753         { 5745, 5825, 5,  6,  5,  5, NO_DFS, NO_PSCAN },
754 #define F8_5745_5825    AFTER(F7_5745_5825)
755         { 5745, 5825, 30, 6, 20, 10, NO_DFS, NO_PSCAN },
756 #define F9_5745_5825    AFTER(F8_5745_5825)
757         { 5745, 5825, 30, 6, 20,  5, NO_DFS, NO_PSCAN },
758 #define F10_5745_5825   AFTER(F9_5745_5825)
759
760         /*
761          * Below are the world roaming channels
762          * All WWR domains have no power limit, instead use the card's CTL
763          * or max power settings.
764          */
765         { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR },
766 #define W1_4920_4980    AFTER(F10_5745_5825)
767         { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR },
768 #define W1_5040_5080    AFTER(W1_4920_4980)
769         { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR },
770 #define W1_5170_5230    AFTER(W1_5040_5080)
771         { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR },
772 #define W1_5180_5240    AFTER(W1_5170_5230)
773         { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR },
774 #define W1_5260_5320    AFTER(W1_5180_5240)
775         { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR },
776 #define W1_5745_5825    AFTER(W1_5260_5320)
777         { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR },
778 #define W1_5500_5700    AFTER(W1_5745_5825)
779         { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN },
780 #define W2_5260_5320    AFTER(W1_5500_5700)
781         { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN },
782 #define W2_5180_5240    AFTER(W2_5260_5320)
783         { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR },
784 #define W2_5825_5825    AFTER(W2_5180_5240)
785 };
786
787 /*
788  * 5GHz Turbo (dynamic & static) tags
789  */
790 static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = {
791         { 5130, 5210, 5,  6, 40, 40, NO_DFS, NO_PSCAN },
792 #define T1_5130_5210    0
793         { 5250, 5330, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN },
794 #define T1_5250_5330    AFTER(T1_5130_5210)
795         { 5370, 5490, 5,  6, 40, 40, NO_DFS, NO_PSCAN },
796 #define T1_5370_5490    AFTER(T1_5250_5330)
797         { 5530, 5650, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN },
798 #define T1_5530_5650    AFTER(T1_5370_5490)
799
800         { 5150, 5190, 5,  6, 40, 40, NO_DFS, NO_PSCAN },
801 #define T1_5150_5190    AFTER(T1_5530_5650)
802         { 5230, 5310, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN },
803 #define T1_5230_5310    AFTER(T1_5150_5190)
804         { 5350, 5470, 5,  6, 40, 40, NO_DFS, NO_PSCAN },
805 #define T1_5350_5470    AFTER(T1_5230_5310)
806         { 5510, 5670, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN },
807 #define T1_5510_5670    AFTER(T1_5350_5470)
808
809         { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN },
810 #define T1_5200_5240    AFTER(T1_5510_5670)
811         { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN },
812 #define T2_5200_5240    AFTER(T1_5200_5240)
813         { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN },
814 #define T1_5210_5210    AFTER(T2_5200_5240)
815         { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN },
816 #define T2_5210_5210    AFTER(T1_5210_5210)
817
818         { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T },
819 #define T1_5280_5280    AFTER(T2_5210_5210)
820         { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T },
821 #define T2_5280_5280    AFTER(T1_5280_5280)
822         { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T },
823 #define T1_5250_5250    AFTER(T2_5280_5280)
824         { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T },
825 #define T1_5290_5290    AFTER(T1_5250_5250)
826         { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T },
827 #define T1_5250_5290    AFTER(T1_5290_5290)
828         { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T },
829 #define T2_5250_5290    AFTER(T1_5250_5290)
830
831         { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T },
832 #define T1_5540_5660    AFTER(T2_5250_5290)
833         { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN },
834 #define T1_5760_5800    AFTER(T1_5540_5660)
835         { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN },
836 #define T2_5760_5800    AFTER(T1_5760_5800)
837
838         { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN },
839 #define T1_5765_5805    AFTER(T2_5760_5800)
840
841         /*
842          * Below are the WWR frequencies
843          */
844         { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR },
845 #define WT1_5210_5250   AFTER(T1_5765_5805)
846         { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR },
847 #define WT1_5290_5290   AFTER(WT1_5210_5250)
848         { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR },
849 #define WT1_5540_5660   AFTER(WT1_5290_5290)
850         { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR },
851 #define WT1_5760_5800   AFTER(WT1_5540_5660)
852 };
853
854 /*
855  * 2GHz 11b channel tags
856  */
857 static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = {
858         { 2312, 2372, 5,  6, 20, 5, NO_DFS, NO_PSCAN },
859 #define F1_2312_2372    0
860         { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
861 #define F2_2312_2372    AFTER(F1_2312_2372)
862
863         { 2412, 2472, 5,  6, 20, 5, NO_DFS, NO_PSCAN },
864 #define F1_2412_2472    AFTER(F2_2312_2372)
865         { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA },
866 #define F2_2412_2472    AFTER(F1_2412_2472)
867         { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN },
868 #define F3_2412_2472    AFTER(F2_2412_2472)
869
870         { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN },
871 #define F1_2412_2462    AFTER(F3_2412_2472)
872         { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA },
873 #define F2_2412_2462    AFTER(F1_2412_2462)
874
875         { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
876 #define F1_2432_2442    AFTER(F2_2412_2462)
877
878         { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
879 #define F1_2457_2472    AFTER(F1_2432_2442)
880
881         { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA },
882 #define F1_2467_2472    AFTER(F1_2457_2472)
883
884         { 2484, 2484, 5,  6, 20, 5, NO_DFS, NO_PSCAN },
885 #define F1_2484_2484    AFTER(F1_2467_2472)
886         { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2 },
887 #define F2_2484_2484    AFTER(F1_2484_2484)
888
889         { 2512, 2732, 5,  6, 20, 5, NO_DFS, NO_PSCAN },
890 #define F1_2512_2732    AFTER(F2_2484_2484)
891
892         /*
893          * WWR have powers opened up to 20dBm.
894          * Limits should often come from CTL/Max powers
895          */
896         { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
897 #define W1_2312_2372    AFTER(F1_2512_2732)
898         { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
899 #define W1_2412_2412    AFTER(W1_2312_2372)
900         { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
901 #define W1_2417_2432    AFTER(W1_2412_2412)
902         { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
903 #define W1_2437_2442    AFTER(W1_2417_2432)
904         { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
905 #define W1_2447_2457    AFTER(W1_2437_2442)
906         { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
907 #define W1_2462_2462    AFTER(W1_2447_2457)
908         { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN },
909 #define W1_2467_2467    AFTER(W1_2462_2462)
910         { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN },
911 #define W2_2467_2467    AFTER(W1_2467_2467)
912         { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN },
913 #define W1_2472_2472    AFTER(W2_2467_2467)
914         { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN },
915 #define W2_2472_2472    AFTER(W1_2472_2472)
916         { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN },
917 #define W1_2484_2484    AFTER(W2_2472_2472)
918         { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN },
919 #define W2_2484_2484    AFTER(W1_2484_2484)
920 };
921
922 /*
923  * 2GHz 11g channel tags
924  */
925 static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = {
926         { 2312, 2372, 5,  6, 20, 5, NO_DFS, NO_PSCAN },
927 #define G1_2312_2372    0
928         { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
929 #define G2_2312_2372    AFTER(G1_2312_2372)
930         { 2312, 2372, 5,  6, 10, 5, NO_DFS, NO_PSCAN },
931 #define G3_2312_2372    AFTER(G2_2312_2372)
932         { 2312, 2372, 5,  6,  5, 5, NO_DFS, NO_PSCAN },
933 #define G4_2312_2372    AFTER(G3_2312_2372)
934
935         { 2412, 2472, 5,  6, 20, 5, NO_DFS, NO_PSCAN },
936 #define G1_2412_2472    AFTER(G4_2312_2372)
937         { 2412, 2472, 20, 0, 20, 5,  NO_DFS, PSCAN_MKKA_G },
938 #define G2_2412_2472    AFTER(G1_2412_2472)
939         { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN },
940 #define G3_2412_2472    AFTER(G2_2412_2472)
941         { 2412, 2472, 5,  6, 10, 5, NO_DFS, NO_PSCAN },
942 #define G4_2412_2472    AFTER(G3_2412_2472)
943         { 2412, 2472, 5,  6,  5, 5, NO_DFS, NO_PSCAN },
944 #define G5_2412_2472    AFTER(G4_2412_2472)
945
946         { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN },
947 #define G1_2412_2462    AFTER(G5_2412_2472)
948         { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G },
949 #define G2_2412_2462    AFTER(G1_2412_2462)
950         { 2412, 2462, 27, 6, 10, 5, NO_DFS, NO_PSCAN },
951 #define G3_2412_2462    AFTER(G2_2412_2462)
952         { 2412, 2462, 27, 6,  5, 5, NO_DFS, NO_PSCAN },
953 #define G4_2412_2462    AFTER(G3_2412_2462)
954         
955         { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
956 #define G1_2432_2442    AFTER(G4_2412_2462)
957
958         { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
959 #define G1_2457_2472    AFTER(G1_2432_2442)
960
961         { 2512, 2732, 5,  6, 20, 5, NO_DFS, NO_PSCAN },
962 #define G1_2512_2732    AFTER(G1_2457_2472)
963         { 2512, 2732, 5,  6, 10, 5, NO_DFS, NO_PSCAN },
964 #define G2_2512_2732    AFTER(G1_2512_2732)
965         { 2512, 2732, 5,  6,  5, 5, NO_DFS, NO_PSCAN },
966 #define G3_2512_2732    AFTER(G2_2512_2732)
967
968         { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA },
969 #define G1_2467_2472    AFTER(G3_2512_2732)
970
971         /*
972          * WWR open up the power to 20dBm
973          */
974         { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
975 #define WG1_2312_2372   AFTER(G1_2467_2472)
976         { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
977 #define WG1_2412_2412   AFTER(WG1_2312_2372)
978         { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
979 #define WG1_2417_2432   AFTER(WG1_2412_2412)
980         { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
981 #define WG1_2437_2442   AFTER(WG1_2417_2432)
982         { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
983 #define WG1_2447_2457   AFTER(WG1_2437_2442)
984         { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN },
985 #define WG1_2462_2462   AFTER(WG1_2447_2457)
986         { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN },
987 #define WG1_2467_2467   AFTER(WG1_2462_2462)
988         { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN },
989 #define WG2_2467_2467   AFTER(WG1_2467_2467)
990         { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN },
991 #define WG1_2472_2472   AFTER(WG2_2467_2467)
992         { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN },
993 #define WG2_2472_2472   AFTER(WG1_2472_2472)
994 };
995
996 /*
997  * 2GHz Dynamic turbo tags
998  */
999 static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = {
1000         { 2312, 2372, 5,  6, 40, 40, NO_DFS, NO_PSCAN },
1001 #define T1_2312_2372    0
1002         { 2437, 2437, 5,  6, 40, 40, NO_DFS, NO_PSCAN },
1003 #define T1_2437_2437    AFTER(T1_2312_2372)
1004         { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN },
1005 #define T2_2437_2437    AFTER(T1_2437_2437)
1006         { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR },
1007 #define T3_2437_2437    AFTER(T2_2437_2437)
1008         { 2512, 2732, 5,  6, 40, 40, NO_DFS, NO_PSCAN },
1009 #define T1_2512_2732    AFTER(T3_2437_2437)
1010 };
1011
1012 typedef struct regDomain {
1013         uint16_t regDmnEnum;            /* value from EnumRd table */
1014         uint8_t conformanceTestLimit;
1015         uint32_t flags;                 /* Requirement flags (AdHoc disallow,
1016                                            noise floor cal needed, etc) */
1017         uint64_t dfsMask;               /* DFS bitmask for 5Ghz tables */
1018         uint64_t pscan;                 /* Bitmask for passive scan */
1019         chanbmask_t chan11a;            /* 11a channels */
1020         chanbmask_t chan11a_turbo;      /* 11a static turbo channels */
1021         chanbmask_t chan11a_dyn_turbo;  /* 11a dynamic turbo channels */
1022         chanbmask_t chan11a_half;       /* 11a 1/2 width channels */
1023         chanbmask_t chan11a_quarter;    /* 11a 1/4 width channels */
1024         chanbmask_t chan11b;            /* 11b channels */
1025         chanbmask_t chan11g;            /* 11g channels */
1026         chanbmask_t chan11g_turbo;      /* 11g dynamic turbo channels */
1027         chanbmask_t chan11g_half;       /* 11g 1/2 width channels */
1028         chanbmask_t chan11g_quarter;    /* 11g 1/4 width channels */
1029 } REG_DOMAIN;
1030
1031 static REG_DOMAIN regDomains[] = {
1032
1033         {.regDmnEnum            = DEBUG_REG_DMN,
1034          .conformanceTestLimit  = FCC,
1035          .dfsMask               = DFS_FCC3,
1036          .chan11a               = BM4(F1_4950_4980,
1037                                       F1_5120_5240,
1038                                       F1_5260_5700,
1039                                       F1_5745_5825),
1040          .chan11a_half          = BM4(F1_4945_4985,
1041                                       F2_5120_5240,
1042                                       F2_5260_5700,
1043                                       F7_5745_5825),
1044          .chan11a_quarter       = BM4(F1_4942_4987,
1045                                       F3_5120_5240,
1046                                       F3_5260_5700,
1047                                       F8_5745_5825),
1048          .chan11a_turbo         = BM8(T1_5130_5210,
1049                                       T1_5250_5330,
1050                                       T1_5370_5490,
1051                                       T1_5530_5650,
1052                                       T1_5150_5190,
1053                                       T1_5230_5310,
1054                                       T1_5350_5470,
1055                                       T1_5510_5670),
1056          .chan11a_dyn_turbo     = BM4(T1_5200_5240,
1057                                       T1_5280_5280,
1058                                       T1_5540_5660,
1059                                       T1_5765_5805),
1060          .chan11b               = BM4(F1_2312_2372,
1061                                       F1_2412_2472,
1062                                       F1_2484_2484,
1063                                       F1_2512_2732),
1064          .chan11g               = BM3(G1_2312_2372, G1_2412_2472, G1_2512_2732),
1065          .chan11g_turbo         = BM3(T1_2312_2372, T1_2437_2437, T1_2512_2732),
1066          .chan11g_half          = BM3(G2_2312_2372, G4_2412_2472, G2_2512_2732),
1067          .chan11g_quarter       = BM3(G3_2312_2372, G5_2412_2472, G3_2512_2732),
1068         },
1069
1070         {.regDmnEnum            = APL1,
1071          .conformanceTestLimit  = FCC,
1072          .chan11a               = BM1(F4_5745_5825),
1073         },
1074
1075         {.regDmnEnum            = APL2,
1076          .conformanceTestLimit  = FCC,
1077          .chan11a               = BM1(F1_5745_5805),
1078         },
1079
1080         {.regDmnEnum            = APL3,
1081          .conformanceTestLimit  = FCC,
1082          .chan11a               = BM2(F1_5280_5320, F2_5745_5805),
1083         },
1084
1085         {.regDmnEnum            = APL4,
1086          .conformanceTestLimit  = FCC,
1087          .chan11a               = BM2(F4_5180_5240, F3_5745_5825),
1088         },
1089
1090         {.regDmnEnum            = APL5,
1091          .conformanceTestLimit  = FCC,
1092          .chan11a               = BM1(F2_5745_5825),
1093         },
1094
1095         {.regDmnEnum            = APL6,
1096          .conformanceTestLimit  = ETSI,
1097          .dfsMask               = DFS_ETSI,
1098          .pscan                 = PSCAN_FCC_T | PSCAN_FCC,
1099          .chan11a               = BM3(F4_5180_5240, F2_5260_5320, F3_5745_5825),
1100          .chan11a_turbo         = BM3(T2_5210_5210, T1_5250_5290, T1_5760_5800),
1101         },
1102
1103         {.regDmnEnum            = APL8,
1104          .conformanceTestLimit  = ETSI,
1105          .flags                 = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
1106          .chan11a               = BM2(F6_5260_5320, F4_5745_5825),
1107         },
1108
1109         {.regDmnEnum            = APL9,
1110          .conformanceTestLimit  = ETSI,
1111          .dfsMask               = DFS_ETSI,
1112          .pscan                 = PSCAN_ETSI,
1113          .flags                 = DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
1114          .chan11a               = BM3(F1_5180_5320, F1_5500_5620, F3_5745_5805),
1115         },
1116
1117         {.regDmnEnum            = ETSI1,
1118          .conformanceTestLimit  = ETSI,
1119          .dfsMask               = DFS_ETSI,
1120          .pscan                 = PSCAN_ETSI,
1121          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1122          .chan11a               = BM3(W2_5180_5240, F2_5260_5320, F2_5500_5700),
1123         },
1124
1125         {.regDmnEnum            = ETSI2,
1126          .conformanceTestLimit  = ETSI,
1127          .dfsMask               = DFS_ETSI,
1128          .pscan                 = PSCAN_ETSI,
1129          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1130          .chan11a               = BM1(F3_5180_5240),
1131         },
1132
1133         {.regDmnEnum            = ETSI3,
1134          .conformanceTestLimit  = ETSI,
1135          .dfsMask               = DFS_ETSI,
1136          .pscan                 = PSCAN_ETSI,
1137          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1138          .chan11a               = BM2(W2_5180_5240, F2_5260_5320),
1139         },
1140
1141         {.regDmnEnum            = ETSI4,
1142          .conformanceTestLimit  = ETSI,
1143          .dfsMask               = DFS_ETSI,
1144          .pscan                 = PSCAN_ETSI,
1145          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1146          .chan11a               = BM2(F3_5180_5240, F1_5260_5320),
1147         },
1148
1149         {.regDmnEnum            = ETSI5,
1150          .conformanceTestLimit  = ETSI,
1151          .dfsMask               = DFS_ETSI,
1152          .pscan                 = PSCAN_ETSI,
1153          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1154          .chan11a               = BM1(F1_5180_5240),
1155         },
1156
1157         {.regDmnEnum            = ETSI6,
1158          .conformanceTestLimit  = ETSI,
1159          .dfsMask               = DFS_ETSI,
1160          .pscan                 = PSCAN_ETSI,
1161          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1162          .chan11a               = BM3(F5_5180_5240, F1_5260_5280, F3_5500_5700),
1163         },
1164
1165         {.regDmnEnum            = FCC1,
1166          .conformanceTestLimit  = FCC,
1167          .chan11a               = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825),
1168          .chan11a_turbo         = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800),
1169          .chan11a_dyn_turbo     = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805),
1170         },
1171
1172         {.regDmnEnum            = FCC2,
1173          .conformanceTestLimit  = FCC,
1174          .chan11a               = BM3(F6_5180_5240, F5_5260_5320, F6_5745_5825),
1175          .chan11a_dyn_turbo     = BM3(T2_5200_5240, T1_5280_5280, T1_5765_5805),
1176         },
1177
1178         {.regDmnEnum            = FCC3,
1179          .conformanceTestLimit  = FCC,
1180          .dfsMask               = DFS_FCC3,
1181          .pscan                 = PSCAN_FCC | PSCAN_FCC_T,
1182          .chan11a               = BM4(F2_5180_5240,
1183                                       F3_5260_5320,
1184                                       F1_5500_5700,
1185                                       F5_5745_5825),
1186          .chan11a_turbo         = BM4(T1_5210_5210,
1187                                       T1_5250_5250,
1188                                       T1_5290_5290,
1189                                       T2_5760_5800),
1190          .chan11a_dyn_turbo     = BM3(T1_5200_5240, T2_5280_5280, T1_5540_5660),
1191         },
1192
1193         {.regDmnEnum            = FCC4,
1194          .conformanceTestLimit  = FCC,
1195          .dfsMask               = DFS_FCC3,
1196          .pscan                 = PSCAN_FCC | PSCAN_FCC_T,
1197          .chan11a               = BM1(F1_4950_4980),
1198          .chan11a_half          = BM1(F1_4945_4985),
1199          .chan11a_quarter       = BM1(F1_4942_4987),
1200         },
1201
1202         /* FCC1 w/ 1/2 and 1/4 width channels */
1203         {.regDmnEnum            = FCC5,
1204          .conformanceTestLimit  = FCC,
1205          .chan11a               = BM3(F2_5180_5240, F4_5260_5320, F5_5745_5825),
1206          .chan11a_turbo         = BM3(T1_5210_5210, T2_5250_5290, T2_5760_5800),
1207          .chan11a_dyn_turbo     = BM3(T1_5200_5240, T1_5280_5280, T1_5765_5805),
1208          .chan11a_half          = BM3(F7_5180_5240, F7_5260_5320, F9_5745_5825),
1209          .chan11a_quarter       = BM3(F8_5180_5240, F8_5260_5320,F10_5745_5825),
1210         },
1211
1212         {.regDmnEnum            = MKK1,
1213          .conformanceTestLimit  = MKK,
1214          .pscan                 = PSCAN_MKK1,
1215          .flags                 = DISALLOW_ADHOC_11A_TURB,
1216          .chan11a               = BM1(F1_5170_5230),
1217         },
1218
1219         {.regDmnEnum            = MKK2,
1220          .conformanceTestLimit  = MKK,
1221          .pscan                 = PSCAN_MKK2,
1222          .flags                 = DISALLOW_ADHOC_11A_TURB,
1223          .chan11a               = BM3(F1_4920_4980, F1_5040_5080, F1_5170_5230),
1224          .chan11a_half          = BM4(F1_4915_4925,
1225                                       F1_4935_4945,
1226                                       F1_5035_5040,
1227                                       F1_5055_5055),
1228         },
1229
1230         /* UNI-1 even */
1231         {.regDmnEnum            = MKK3,
1232          .conformanceTestLimit  = MKK,
1233          .pscan                 = PSCAN_MKK3,
1234          .flags                 = DISALLOW_ADHOC_11A_TURB,
1235          .chan11a               = BM1(F4_5180_5240),
1236         },
1237
1238         /* UNI-1 even + UNI-2 */
1239         {.regDmnEnum            = MKK4,
1240          .conformanceTestLimit  = MKK,
1241          .dfsMask               = DFS_MKK4,
1242          .pscan                 = PSCAN_MKK3,
1243          .flags                 = DISALLOW_ADHOC_11A_TURB,
1244          .chan11a               = BM2(F4_5180_5240, F2_5260_5320),
1245         },
1246
1247         /* UNI-1 even + UNI-2 + mid-band */
1248         {.regDmnEnum            = MKK5,
1249          .conformanceTestLimit  = MKK,
1250          .dfsMask               = DFS_MKK4,
1251          .pscan                 = PSCAN_MKK3,
1252          .flags                 = DISALLOW_ADHOC_11A_TURB,
1253          .chan11a               = BM3(F4_5180_5240, F2_5260_5320, F4_5500_5700),
1254         },
1255
1256         /* UNI-1 odd + even */
1257         {.regDmnEnum            = MKK6,
1258          .conformanceTestLimit  = MKK,
1259          .pscan                 = PSCAN_MKK1,
1260          .flags                 = DISALLOW_ADHOC_11A_TURB,
1261          .chan11a               = BM2(F2_5170_5230, F4_5180_5240),
1262         },
1263
1264         /* UNI-1 odd + UNI-1 even + UNI-2 */
1265         {.regDmnEnum            = MKK7,
1266          .conformanceTestLimit  = MKK,
1267          .dfsMask               = DFS_MKK4,
1268          .pscan                 = PSCAN_MKK1 | PSCAN_MKK3,
1269          .flags                 = DISALLOW_ADHOC_11A_TURB,
1270          .chan11a               = BM3(F1_5170_5230, F4_5180_5240, F2_5260_5320),
1271         },
1272
1273         /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */
1274         {.regDmnEnum            = MKK8,
1275          .conformanceTestLimit  = MKK,
1276          .dfsMask               = DFS_MKK4,
1277          .pscan                 = PSCAN_MKK1 | PSCAN_MKK3,
1278          .flags                 = DISALLOW_ADHOC_11A_TURB,
1279          .chan11a               = BM4(F1_5170_5230,
1280                                       F4_5180_5240,
1281                                       F2_5260_5320,
1282                                       F4_5500_5700),
1283         },
1284
1285         /* UNI-1 even + 4.9 GHZ */
1286         {.regDmnEnum            = MKK9,
1287          .conformanceTestLimit  = MKK,
1288          .pscan                 = PSCAN_MKK3,
1289          .flags                 = DISALLOW_ADHOC_11A_TURB,
1290          .chan11a               = BM7(F1_4915_4925,
1291                                       F1_4935_4945,
1292                                       F1_4920_4980,
1293                                       F1_5035_5040,
1294                                       F1_5055_5055,
1295                                       F1_5040_5080,
1296                                       F4_5180_5240),
1297         },
1298
1299         /* UNI-1 even + UNI-2 + 4.9 GHZ */
1300         {.regDmnEnum            = MKK10,
1301          .conformanceTestLimit  = MKK,
1302          .dfsMask               = DFS_MKK4,
1303          .pscan                 = PSCAN_MKK3,
1304          .flags                 = DISALLOW_ADHOC_11A_TURB,
1305          .chan11a               = BM8(F1_4915_4925,
1306                                       F1_4935_4945,
1307                                       F1_4920_4980,
1308                                       F1_5035_5040,
1309                                       F1_5055_5055,
1310                                       F1_5040_5080,
1311                                       F4_5180_5240,
1312                                       F2_5260_5320),
1313         },
1314
1315         /* Defined here to use when 2G channels are authorised for country K2 */
1316         {.regDmnEnum            = APLD,
1317          .conformanceTestLimit  = NO_CTL,
1318          .chan11b               = BM2(F2_2312_2372,F2_2412_2472),
1319          .chan11g               = BM2(G2_2312_2372,G2_2412_2472),
1320         },
1321
1322         {.regDmnEnum            = ETSIA,
1323          .conformanceTestLimit  = NO_CTL,
1324          .pscan                 = PSCAN_ETSIA,
1325          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1326          .chan11b               = BM1(F1_2457_2472),
1327          .chan11g               = BM1(G1_2457_2472),
1328          .chan11g_turbo         = BM1(T2_2437_2437)
1329         },
1330
1331         {.regDmnEnum            = ETSIB,
1332          .conformanceTestLimit  = ETSI,
1333          .pscan                 = PSCAN_ETSIB,
1334          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1335          .chan11b               = BM1(F1_2432_2442),
1336          .chan11g               = BM1(G1_2432_2442),
1337          .chan11g_turbo         = BM1(T2_2437_2437)
1338         },
1339
1340         {.regDmnEnum            = ETSIC,
1341          .conformanceTestLimit  = ETSI,
1342          .pscan                 = PSCAN_ETSIC,
1343          .flags                 = DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
1344          .chan11b               = BM1(F3_2412_2472),
1345          .chan11g               = BM1(G3_2412_2472),
1346          .chan11g_turbo         = BM1(T2_2437_2437)
1347         },
1348
1349         {.regDmnEnum            = FCCA,
1350          .conformanceTestLimit  = FCC,
1351          .chan11b               = BM1(F1_2412_2462),
1352          .chan11g               = BM1(G1_2412_2462),
1353          .chan11g_turbo         = BM1(T2_2437_2437),
1354         },
1355
1356         /* FCCA w/ 1/2 and 1/4 width channels */
1357         {.regDmnEnum            = FCCB,
1358          .conformanceTestLimit  = FCC,
1359          .chan11b               = BM1(F1_2412_2462),
1360          .chan11g               = BM1(G1_2412_2462),
1361          .chan11g_turbo         = BM1(T2_2437_2437),
1362          .chan11g_half          = BM1(G3_2412_2462),
1363          .chan11g_quarter       = BM1(G4_2412_2462),
1364         },
1365
1366         {.regDmnEnum            = MKKA,
1367          .conformanceTestLimit  = MKK,
1368          .pscan                 = PSCAN_MKKA | PSCAN_MKKA_G
1369                                 | PSCAN_MKKA1 | PSCAN_MKKA1_G
1370                                 | PSCAN_MKKA2 | PSCAN_MKKA2_G,
1371          .flags                 = DISALLOW_ADHOC_11A_TURB,
1372          .chan11b               = BM3(F2_2412_2462, F1_2467_2472, F2_2484_2484),
1373          .chan11g               = BM2(G2_2412_2462, G1_2467_2472),
1374          .chan11g_turbo         = BM1(T2_2437_2437)
1375         },
1376
1377         {.regDmnEnum            = MKKC,
1378          .conformanceTestLimit  = MKK,
1379          .chan11b               = BM1(F2_2412_2472),
1380          .chan11g               = BM1(G2_2412_2472),
1381          .chan11g_turbo         = BM1(T2_2437_2437)
1382         },
1383
1384         {.regDmnEnum            = WORLD,
1385          .conformanceTestLimit  = ETSI,
1386          .chan11b               = BM1(F2_2412_2472),
1387          .chan11g               = BM1(G2_2412_2472),
1388          .chan11g_turbo         = BM1(T2_2437_2437)
1389         },
1390
1391         {.regDmnEnum            = WOR0_WORLD,
1392          .conformanceTestLimit  = NO_CTL,
1393          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1394          .pscan                 = PSCAN_WWR,
1395          .flags                 = ADHOC_PER_11D,
1396          .chan11a               = BM5(W1_5260_5320,
1397                                       W1_5180_5240,
1398                                       W1_5170_5230,
1399                                       W1_5745_5825,
1400                                       W1_5500_5700),
1401          .chan11a_turbo         = BM3(WT1_5210_5250,
1402                                       WT1_5290_5290,
1403                                       WT1_5760_5800),
1404          .chan11b               = BM8(W1_2412_2412,
1405                                       W1_2437_2442,
1406                                       W1_2462_2462,
1407                                       W1_2472_2472,
1408                                       W1_2417_2432,
1409                                       W1_2447_2457,
1410                                       W1_2467_2467,
1411                                       W1_2484_2484),
1412          .chan11g               = BM7(WG1_2412_2412,
1413                                       WG1_2437_2442,
1414                                       WG1_2462_2462,
1415                                       WG1_2472_2472,
1416                                       WG1_2417_2432,
1417                                       WG1_2447_2457,
1418                                       WG1_2467_2467),
1419          .chan11g_turbo         = BM1(T3_2437_2437)
1420         },
1421
1422         {.regDmnEnum            = WOR01_WORLD,
1423          .conformanceTestLimit  = NO_CTL,
1424          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1425          .pscan                 = PSCAN_WWR,
1426          .flags                 = ADHOC_PER_11D,
1427          .chan11a               = BM5(W1_5260_5320,
1428                                       W1_5180_5240,
1429                                       W1_5170_5230,
1430                                       W1_5745_5825,
1431                                       W1_5500_5700),
1432          .chan11a_turbo         = BM3(WT1_5210_5250,
1433                                       WT1_5290_5290,
1434                                       WT1_5760_5800),
1435          .chan11b               = BM5(W1_2412_2412,
1436                                       W1_2437_2442,
1437                                       W1_2462_2462,
1438                                       W1_2417_2432,
1439                                       W1_2447_2457),
1440          .chan11g               = BM5(WG1_2412_2412,
1441                                       WG1_2437_2442,
1442                                       WG1_2462_2462,
1443                                       WG1_2417_2432,
1444                                       WG1_2447_2457),
1445          .chan11g_turbo         = BM1(T3_2437_2437)},
1446
1447         {.regDmnEnum            = WOR02_WORLD,
1448          .conformanceTestLimit  = NO_CTL,
1449          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1450          .pscan                 = PSCAN_WWR,
1451          .flags                 = ADHOC_PER_11D,
1452          .chan11a               = BM5(W1_5260_5320,
1453                                       W1_5180_5240,
1454                                       W1_5170_5230,
1455                                       W1_5745_5825,
1456                                       W1_5500_5700),
1457          .chan11a_turbo         = BM3(WT1_5210_5250,
1458                                       WT1_5290_5290,
1459                                       WT1_5760_5800),
1460          .chan11b               = BM7(W1_2412_2412,
1461                                       W1_2437_2442,
1462                                       W1_2462_2462,
1463                                       W1_2472_2472,
1464                                       W1_2417_2432,
1465                                       W1_2447_2457,
1466                                       W1_2467_2467),
1467          .chan11g               = BM7(WG1_2412_2412,
1468                                       WG1_2437_2442,
1469                                       WG1_2462_2462,
1470                                       WG1_2472_2472,
1471                                       WG1_2417_2432,
1472                                       WG1_2447_2457,
1473                                       WG1_2467_2467),
1474          .chan11g_turbo         = BM1(T3_2437_2437)},
1475
1476         {.regDmnEnum            = EU1_WORLD,
1477          .conformanceTestLimit  = NO_CTL,
1478          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1479          .pscan                 = PSCAN_WWR,
1480          .flags                 = ADHOC_PER_11D,
1481          .chan11a               = BM5(W1_5260_5320,
1482                                       W1_5180_5240,
1483                                       W1_5170_5230,
1484                                       W1_5745_5825,
1485                                       W1_5500_5700),
1486          .chan11a_turbo         = BM3(WT1_5210_5250,
1487                                       WT1_5290_5290,
1488                                       WT1_5760_5800),
1489          .chan11b               = BM7(W1_2412_2412,
1490                                       W1_2437_2442,
1491                                       W1_2462_2462,
1492                                       W2_2472_2472,
1493                                       W1_2417_2432,
1494                                       W1_2447_2457,
1495                                       W2_2467_2467),
1496          .chan11g               = BM7(WG1_2412_2412,
1497                                       WG1_2437_2442,
1498                                       WG1_2462_2462,
1499                                       WG2_2472_2472,
1500                                       WG1_2417_2432,
1501                                       WG1_2447_2457,
1502                                       WG2_2467_2467),
1503          .chan11g_turbo         = BM1(T3_2437_2437)},
1504
1505         {.regDmnEnum            = WOR1_WORLD,
1506          .conformanceTestLimit  = NO_CTL,
1507          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1508          .pscan                 = PSCAN_WWR,
1509          .flags                 = DISALLOW_ADHOC_11A,
1510          .chan11a               = BM5(W1_5260_5320,
1511                                       W1_5180_5240,
1512                                       W1_5170_5230,
1513                                       W1_5745_5825,
1514                                       W1_5500_5700),
1515          .chan11b               = BM8(W1_2412_2412,
1516                                       W1_2437_2442,
1517                                       W1_2462_2462,
1518                                       W1_2472_2472,
1519                                       W1_2417_2432,
1520                                       W1_2447_2457,
1521                                       W1_2467_2467,
1522                                       W1_2484_2484),
1523          .chan11g               = BM7(WG1_2412_2412,
1524                                       WG1_2437_2442,
1525                                       WG1_2462_2462,
1526                                       WG1_2472_2472,
1527                                       WG1_2417_2432,
1528                                       WG1_2447_2457,
1529                                       WG1_2467_2467),
1530          .chan11g_turbo         = BM1(T3_2437_2437)
1531         },
1532
1533         {.regDmnEnum            = WOR2_WORLD,
1534          .conformanceTestLimit  = NO_CTL,
1535          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1536          .pscan                 = PSCAN_WWR,
1537          .flags                 = DISALLOW_ADHOC_11A,
1538          .chan11a               = BM5(W1_5260_5320,
1539                                       W1_5180_5240,
1540                                       W1_5170_5230,
1541                                       W1_5745_5825,
1542                                       W1_5500_5700),
1543          .chan11a_turbo         = BM3(WT1_5210_5250,
1544                                       WT1_5290_5290,
1545                                       WT1_5760_5800),
1546          .chan11b               = BM8(W1_2412_2412,
1547                                       W1_2437_2442,
1548                                       W1_2462_2462,
1549                                       W1_2472_2472,
1550                                       W1_2417_2432,
1551                                       W1_2447_2457,
1552                                       W1_2467_2467,
1553                                       W1_2484_2484),
1554          .chan11g               = BM7(WG1_2412_2412,
1555                                       WG1_2437_2442,
1556                                       WG1_2462_2462,
1557                                       WG1_2472_2472,
1558                                       WG1_2417_2432,
1559                                       WG1_2447_2457,
1560                                       WG1_2467_2467),
1561          .chan11g_turbo         = BM1(T3_2437_2437)},
1562
1563         {.regDmnEnum            = WOR3_WORLD,
1564          .conformanceTestLimit  = NO_CTL,
1565          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1566          .pscan                 = PSCAN_WWR,
1567          .flags                 = ADHOC_PER_11D,
1568          .chan11a               = BM4(W1_5260_5320,
1569                                       W1_5180_5240,
1570                                       W1_5170_5230,
1571                                       W1_5745_5825),
1572          .chan11a_turbo         = BM3(WT1_5210_5250,
1573                                       WT1_5290_5290,
1574                                       WT1_5760_5800),
1575          .chan11b               = BM7(W1_2412_2412,
1576                                       W1_2437_2442,
1577                                       W1_2462_2462,
1578                                       W1_2472_2472,
1579                                       W1_2417_2432,
1580                                       W1_2447_2457,
1581                                       W1_2467_2467),
1582          .chan11g               = BM7(WG1_2412_2412,
1583                                       WG1_2437_2442,
1584                                       WG1_2462_2462,
1585                                       WG1_2472_2472,
1586                                       WG1_2417_2432,
1587                                       WG1_2447_2457,
1588                                       WG1_2467_2467),
1589          .chan11g_turbo         = BM1(T3_2437_2437)},
1590
1591         {.regDmnEnum            = WOR4_WORLD,
1592          .conformanceTestLimit  = NO_CTL,
1593          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1594          .pscan                 = PSCAN_WWR,
1595          .flags                 = DISALLOW_ADHOC_11A,
1596          .chan11a               = BM4(W2_5260_5320,
1597                                       W2_5180_5240,
1598                                       F2_5745_5805,
1599                                       W2_5825_5825),
1600          .chan11a_turbo         = BM3(WT1_5210_5250,
1601                                       WT1_5290_5290,
1602                                       WT1_5760_5800),
1603          .chan11b               = BM5(W1_2412_2412,
1604                                       W1_2437_2442,
1605                                       W1_2462_2462,
1606                                       W1_2417_2432,
1607                                       W1_2447_2457),
1608          .chan11g               = BM5(WG1_2412_2412,
1609                                       WG1_2437_2442,
1610                                       WG1_2462_2462,
1611                                       WG1_2417_2432,
1612                                       WG1_2447_2457),
1613          .chan11g_turbo         = BM1(T3_2437_2437)},
1614
1615         {.regDmnEnum            = WOR5_ETSIC,
1616          .conformanceTestLimit  = NO_CTL,
1617          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1618          .pscan                 = PSCAN_WWR,
1619          .flags                 = DISALLOW_ADHOC_11A,
1620          .chan11a               = BM3(W1_5260_5320, W2_5180_5240, F6_5745_5825),
1621          .chan11b               = BM7(W1_2412_2412,
1622                                       W1_2437_2442,
1623                                       W1_2462_2462,
1624                                       W2_2472_2472,
1625                                       W1_2417_2432,
1626                                       W1_2447_2457,
1627                                       W2_2467_2467),
1628          .chan11g               = BM7(WG1_2412_2412,
1629                                       WG1_2437_2442,
1630                                       WG1_2462_2462,
1631                                       WG2_2472_2472,
1632                                       WG1_2417_2432,
1633                                       WG1_2447_2457,
1634                                       WG2_2467_2467),
1635          .chan11g_turbo         = BM1(T3_2437_2437)},
1636
1637         {.regDmnEnum            = WOR9_WORLD,
1638          .conformanceTestLimit  = NO_CTL,
1639          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1640          .pscan                 = PSCAN_WWR,
1641          .flags                 = DISALLOW_ADHOC_11A,
1642          .chan11a               = BM4(W1_5260_5320,
1643                                       W1_5180_5240,
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               = BM5(W1_2412_2412,
1650                                       W1_2437_2442,
1651                                       W1_2462_2462,
1652                                       W1_2417_2432,
1653                                       W1_2447_2457),
1654          .chan11g               = BM5(WG1_2412_2412,
1655                                       WG1_2437_2442,
1656                                       WG1_2462_2462,
1657                                       WG1_2417_2432,
1658                                       WG1_2447_2457),
1659          .chan11g_turbo         = BM1(T3_2437_2437)},
1660
1661         {.regDmnEnum            = WORA_WORLD,
1662          .conformanceTestLimit  = NO_CTL,
1663          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1664          .pscan                 = PSCAN_WWR,
1665          .flags                 = DISALLOW_ADHOC_11A,
1666          .chan11a               = BM4(W1_5260_5320,
1667                                       W1_5180_5240,
1668                                       W1_5745_5825,
1669                                       W1_5500_5700),
1670          .chan11b               = BM7(W1_2412_2412,
1671                                       W1_2437_2442,
1672                                       W1_2462_2462,
1673                                       W1_2472_2472,
1674                                       W1_2417_2432,
1675                                       W1_2447_2457,
1676                                       W1_2467_2467),
1677          .chan11g               = BM7(WG1_2412_2412,
1678                                       WG1_2437_2442,
1679                                       WG1_2462_2462,
1680                                       WG1_2472_2472,
1681                                       WG1_2417_2432,
1682                                       WG1_2447_2457,
1683                                       WG1_2467_2467),
1684          .chan11g_turbo         = BM1(T3_2437_2437)},
1685
1686         {.regDmnEnum            = WORB_WORLD,
1687          .conformanceTestLimit  = NO_CTL,
1688          .dfsMask               = DFS_FCC3 | DFS_ETSI,
1689          .pscan                 = PSCAN_WWR,
1690          .flags                 = DISALLOW_ADHOC_11A,
1691          .chan11a               = BM4(W1_5260_5320,
1692                                       W1_5180_5240,
1693                                       W1_5745_5825,
1694                                       W1_5500_5700),
1695          .chan11b               = BM7(W1_2412_2412,
1696                                       W1_2437_2442,
1697                                       W1_2462_2462,
1698                                       W1_2472_2472,
1699                                       W1_2417_2432,
1700                                       W1_2447_2457,
1701                                       W1_2467_2467),
1702          .chan11g               = BM7(WG1_2412_2412,
1703                                       WG1_2437_2442,
1704                                       WG1_2462_2462,
1705                                       WG1_2472_2472,
1706                                       WG1_2417_2432,
1707                                       WG1_2447_2457,
1708                                       WG1_2467_2467),
1709          .chan11g_turbo         = BM1(T3_2437_2437)},
1710
1711         {.regDmnEnum            = NULL1,
1712          .conformanceTestLimit  = NO_CTL,
1713         }
1714 };
1715
1716 struct cmode {
1717         u_int   mode;
1718         u_int   flags;
1719 };
1720
1721 static const struct cmode modes[] = {
1722         { HAL_MODE_TURBO,       IEEE80211_CHAN_ST },
1723         { HAL_MODE_11A,         IEEE80211_CHAN_A },
1724         { HAL_MODE_11B,         IEEE80211_CHAN_B },
1725         { HAL_MODE_11G,         IEEE80211_CHAN_G },
1726         { HAL_MODE_11G_TURBO,   IEEE80211_CHAN_108G },
1727         { HAL_MODE_11A_TURBO,   IEEE80211_CHAN_108A },
1728         { HAL_MODE_11A_QUARTER_RATE,
1729           IEEE80211_CHAN_A | IEEE80211_CHAN_QUARTER },
1730         { HAL_MODE_11A_HALF_RATE,
1731           IEEE80211_CHAN_A | IEEE80211_CHAN_HALF },
1732         { HAL_MODE_11G_QUARTER_RATE,
1733           IEEE80211_CHAN_G | IEEE80211_CHAN_QUARTER },
1734         { HAL_MODE_11G_HALF_RATE,
1735           IEEE80211_CHAN_G | IEEE80211_CHAN_HALF },
1736         { HAL_MODE_11NG_HT20,   IEEE80211_CHAN_G | IEEE80211_CHAN_HT20 },
1737         { HAL_MODE_11NG_HT40PLUS,
1738           IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U },
1739         { HAL_MODE_11NG_HT40MINUS,
1740           IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D },
1741         { HAL_MODE_11NA_HT20,   IEEE80211_CHAN_A | IEEE80211_CHAN_HT20 },
1742         { HAL_MODE_11NA_HT40PLUS,
1743           IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U },
1744         { HAL_MODE_11NA_HT40MINUS,
1745           IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D },
1746 };
1747
1748 static OS_INLINE uint16_t
1749 getEepromRD(struct ath_hal *ah)
1750 {
1751         return AH_PRIVATE(ah)->ah_currentRD &~ WORLDWIDE_ROAMING_FLAG;
1752 }
1753
1754 /*
1755  * Test to see if the bitmask array is all zeros
1756  */
1757 static HAL_BOOL
1758 isChanBitMaskZero(const uint64_t *bitmask)
1759 {
1760 #if BMLEN > 2
1761 #error  "add more cases"
1762 #endif
1763 #if BMLEN > 1
1764         if (bitmask[1] != 0)
1765                 return AH_FALSE;
1766 #endif
1767         return (bitmask[0] == 0);
1768 }
1769
1770 /*
1771  * Return whether or not the regulatory domain/country in EEPROM
1772  * is acceptable.
1773  */
1774 static HAL_BOOL
1775 isEepromValid(struct ath_hal *ah)
1776 {
1777         uint16_t rd = getEepromRD(ah);
1778         int i;
1779
1780         if (rd & COUNTRY_ERD_FLAG) {
1781                 uint16_t cc = rd &~ COUNTRY_ERD_FLAG;
1782                 for (i = 0; i < N(allCountries); i++)
1783                         if (allCountries[i].countryCode == cc)
1784                                 return AH_TRUE;
1785         } else {
1786                 for (i = 0; i < N(regDomainPairs); i++)
1787                         if (regDomainPairs[i].regDmnEnum == rd)
1788                                 return AH_TRUE;
1789         }
1790         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1791             "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd);
1792         return AH_FALSE;
1793 }
1794
1795 /*
1796  * Find the pointer to the country element in the country table
1797  * corresponding to the country code
1798  */
1799 static COUNTRY_CODE_TO_ENUM_RD*
1800 findCountry(HAL_CTRY_CODE countryCode)
1801 {
1802         int i;
1803
1804         for (i = 0; i < N(allCountries); i++) {
1805                 if (allCountries[i].countryCode == countryCode)
1806                         return &allCountries[i];
1807         }
1808         return AH_NULL;
1809 }
1810
1811 static REG_DOMAIN *
1812 findRegDmn(int regDmn)
1813 {
1814         int i;
1815
1816         for (i = 0; i < N(regDomains); i++) {
1817                 if (regDomains[i].regDmnEnum == regDmn)
1818                         return &regDomains[i];
1819         }
1820         return AH_NULL;
1821 }
1822
1823 static REG_DMN_PAIR_MAPPING *
1824 findRegDmnPair(int regDmnPair)
1825 {
1826         int i;
1827
1828         if (regDmnPair != NO_ENUMRD) {
1829                 for (i = 0; i < N(regDomainPairs); i++) {
1830                         if (regDomainPairs[i].regDmnEnum == regDmnPair)
1831                                 return &regDomainPairs[i];
1832                 }
1833         }
1834         return AH_NULL;
1835 }
1836
1837 /*
1838  * Calculate a default country based on the EEPROM setting.
1839  */
1840 static HAL_CTRY_CODE
1841 getDefaultCountry(struct ath_hal *ah)
1842 {
1843         REG_DMN_PAIR_MAPPING *regpair;
1844         uint16_t rd;
1845
1846         rd = getEepromRD(ah);
1847         if (rd & COUNTRY_ERD_FLAG) {
1848                 COUNTRY_CODE_TO_ENUM_RD *country;
1849                 uint16_t cc = rd & ~COUNTRY_ERD_FLAG;
1850                 country = findCountry(cc);
1851                 if (country != AH_NULL)
1852                         return cc;
1853         }
1854         /*
1855          * Check reg domains that have only one country
1856          */
1857         regpair = findRegDmnPair(rd);
1858         return (regpair != AH_NULL) ? regpair->singleCC : CTRY_DEFAULT;
1859 }
1860
1861 static HAL_BOOL
1862 IS_BIT_SET(int bit, const uint64_t bitmask[])
1863 {
1864         int byteOffset, bitnum;
1865         uint64_t val;
1866
1867         byteOffset = bit/64;
1868         bitnum = bit - byteOffset*64;
1869         val = ((uint64_t) 1) << bitnum;
1870         return (bitmask[byteOffset] & val) != 0;
1871 }
1872
1873 static HAL_STATUS
1874 getregstate(struct ath_hal *ah, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn,
1875     COUNTRY_CODE_TO_ENUM_RD **pcountry,
1876     REG_DOMAIN **prd2GHz, REG_DOMAIN **prd5GHz)
1877 {
1878         COUNTRY_CODE_TO_ENUM_RD *country;
1879         REG_DOMAIN *rd5GHz, *rd2GHz;
1880
1881         if (cc == CTRY_DEFAULT && regDmn == SKU_NONE) {
1882                 /*
1883                  * Validate the EEPROM setting and setup defaults
1884                  */
1885                 if (!isEepromValid(ah)) {
1886                         /*
1887                          * Don't return any channels if the EEPROM has an
1888                          * invalid regulatory domain/country code setting.
1889                          */
1890                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1891                             "%s: invalid EEPROM contents\n",__func__);
1892                         return HAL_EEBADREG;
1893                 }
1894
1895                 cc = getDefaultCountry(ah);
1896                 country = findCountry(cc);
1897                 if (country == AH_NULL) {
1898                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1899                             "NULL Country!, cc %d\n", cc);
1900                         return HAL_EEBADCC;
1901                 }
1902                 regDmn = country->regDmnEnum;
1903                 HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: EEPROM cc %u rd 0x%x\n",
1904                     __func__, cc, regDmn);
1905
1906                 if (country->countryCode == CTRY_DEFAULT) {
1907                         /*
1908                          * Check EEPROM; SKU may be for a country, single
1909                          * domain, or multiple domains (WWR).
1910                          */
1911                         uint16_t rdnum = getEepromRD(ah);
1912                         if ((rdnum & COUNTRY_ERD_FLAG) == 0 &&
1913                             (findRegDmn(rdnum) != AH_NULL ||
1914                              findRegDmnPair(rdnum) != AH_NULL)) {
1915                                 regDmn = rdnum;
1916                                 HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1917                                     "%s: EEPROM rd 0x%x\n", __func__, rdnum);
1918                         }
1919                 }
1920         } else {
1921                 country = findCountry(cc);
1922                 if (country == AH_NULL) {
1923                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1924                             "unknown country, cc %d\n", cc);
1925                         return HAL_EINVAL;
1926                 }
1927                 if (regDmn == SKU_NONE)
1928                         regDmn = country->regDmnEnum;
1929                 HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u rd 0x%x\n",
1930                     __func__, cc, regDmn);
1931         }
1932
1933         /*
1934          * Setup per-band state.
1935          */
1936         if ((regDmn & MULTI_DOMAIN_MASK) == 0) {
1937                 REG_DMN_PAIR_MAPPING *regpair = findRegDmnPair(regDmn);
1938                 if (regpair == AH_NULL) {
1939                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1940                             "%s: no reg domain pair %u for country %u\n",
1941                             __func__, regDmn, country->countryCode);
1942                         return HAL_EINVAL;
1943                 }
1944                 rd5GHz = findRegDmn(regpair->regDmn5GHz);
1945                 if (rd5GHz == AH_NULL) {
1946                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1947                             "%s: no 5GHz reg domain %u for country %u\n",
1948                             __func__, regpair->regDmn5GHz, country->countryCode);
1949                         return HAL_EINVAL;
1950                 }
1951                 rd2GHz = findRegDmn(regpair->regDmn2GHz);
1952                 if (rd2GHz == AH_NULL) {
1953                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1954                             "%s: no 2GHz reg domain %u for country %u\n",
1955                             __func__, regpair->regDmn2GHz, country->countryCode);
1956                         return HAL_EINVAL;
1957                 }
1958         } else {
1959                 rd5GHz = rd2GHz = findRegDmn(regDmn);
1960                 if (rd2GHz == AH_NULL) {
1961                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
1962                             "%s: no unitary reg domain %u for country %u\n",
1963                             __func__, regDmn, country->countryCode);
1964                         return HAL_EINVAL;
1965                 }
1966         }
1967         if (pcountry != AH_NULL)
1968                 *pcountry = country;
1969         *prd2GHz = rd2GHz;
1970         *prd5GHz = rd5GHz;
1971         return HAL_OK;
1972 }
1973
1974 /*
1975  * Construct the channel list for the specified regulatory config.
1976  */
1977 static HAL_STATUS
1978 getchannels(struct ath_hal *ah,
1979     struct ieee80211_channel chans[], u_int maxchans, int *nchans,
1980     u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn,
1981     HAL_BOOL enableExtendedChannels,
1982     COUNTRY_CODE_TO_ENUM_RD **pcountry,
1983     REG_DOMAIN **prd2GHz, REG_DOMAIN **prd5GHz)
1984 {
1985 #define CHANNEL_HALF_BW         10
1986 #define CHANNEL_QUARTER_BW      5
1987 #define HAL_MODE_11A_ALL \
1988         (HAL_MODE_11A | HAL_MODE_11A_TURBO | HAL_MODE_TURBO | \
1989          HAL_MODE_11A_QUARTER_RATE | HAL_MODE_11A_HALF_RATE)
1990         REG_DOMAIN *rd5GHz, *rd2GHz;
1991         u_int modesAvail;
1992         const struct cmode *cm;
1993         struct ieee80211_channel *ic;
1994         int next, b;
1995         HAL_STATUS status;
1996
1997         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u regDmn 0x%x mode 0x%x%s\n",
1998             __func__, cc, regDmn, modeSelect, 
1999             enableExtendedChannels ? " ecm" : "");
2000
2001         status = getregstate(ah, cc, regDmn, pcountry, &rd2GHz, &rd5GHz);
2002         if (status != HAL_OK)
2003                 return status;
2004
2005         /* get modes that HW is capable of */
2006         modesAvail = ath_hal_getWirelessModes(ah);
2007         /* optimize work below if no 11a channels */
2008         if (isChanBitMaskZero(rd5GHz->chan11a) &&
2009             (modesAvail & HAL_MODE_11A_ALL)) {
2010                 HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2011                     "%s: disallow all 11a\n", __func__);
2012                 modesAvail &= ~HAL_MODE_11A_ALL;
2013         }
2014
2015         next = 0;
2016         ic = &chans[0];
2017         for (cm = modes; cm < &modes[N(modes)]; cm++) {
2018                 uint16_t c, c_hi, c_lo;
2019                 uint64_t *channelBM = AH_NULL;
2020                 REG_DMN_FREQ_BAND *fband = AH_NULL,*freqs;
2021                 int low_adj, hi_adj, channelSep, lastc;
2022                 uint32_t rdflags;
2023                 uint64_t dfsMask;
2024                 uint64_t pscan;
2025
2026                 if ((cm->mode & modeSelect) == 0) {
2027                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2028                             "%s: skip mode 0x%x flags 0x%x\n",
2029                             __func__, cm->mode, cm->flags);
2030                         continue;
2031                 }
2032                 if ((cm->mode & modesAvail) == 0) {
2033                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2034                             "%s: !avail mode 0x%x (0x%x) flags 0x%x\n",
2035                             __func__, modesAvail, cm->mode, cm->flags);
2036                         continue;
2037                 }
2038                 if (!ath_hal_getChannelEdges(ah, cm->flags, &c_lo, &c_hi)) {
2039                         /* channel not supported by hardware, skip it */
2040                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2041                             "%s: channels 0x%x not supported by hardware\n",
2042                             __func__,cm->flags);
2043                         continue;
2044                 }
2045                 switch (cm->mode) {
2046                 case HAL_MODE_TURBO:
2047                 case HAL_MODE_11A_TURBO:
2048                         rdflags = rd5GHz->flags;
2049                         dfsMask = rd5GHz->dfsMask;
2050                         pscan = rd5GHz->pscan;
2051                         if (cm->mode == HAL_MODE_TURBO)
2052                                 channelBM = rd5GHz->chan11a_turbo;
2053                         else
2054                                 channelBM = rd5GHz->chan11a_dyn_turbo;
2055                         freqs = &regDmn5GhzTurboFreq[0];
2056                         break;
2057                 case HAL_MODE_11G_TURBO:
2058                         rdflags = rd2GHz->flags;
2059                         dfsMask = rd2GHz->dfsMask;
2060                         pscan = rd2GHz->pscan;
2061                         channelBM = rd2GHz->chan11g_turbo;
2062                         freqs = &regDmn2Ghz11gTurboFreq[0];
2063                         break;
2064                 case HAL_MODE_11A:
2065                 case HAL_MODE_11A_HALF_RATE:
2066                 case HAL_MODE_11A_QUARTER_RATE:
2067                 case HAL_MODE_11NA_HT20:
2068                 case HAL_MODE_11NA_HT40PLUS:
2069                 case HAL_MODE_11NA_HT40MINUS:
2070                         rdflags = rd5GHz->flags;
2071                         dfsMask = rd5GHz->dfsMask;
2072                         pscan = rd5GHz->pscan;
2073                         if (cm->mode == HAL_MODE_11A_HALF_RATE)
2074                                 channelBM = rd5GHz->chan11a_half;
2075                         else if (cm->mode == HAL_MODE_11A_QUARTER_RATE)
2076                                 channelBM = rd5GHz->chan11a_quarter;
2077                         else
2078                                 channelBM = rd5GHz->chan11a;
2079                         freqs = &regDmn5GhzFreq[0];
2080                         break;
2081                 case HAL_MODE_11B:
2082                 case HAL_MODE_11G:
2083                 case HAL_MODE_11G_HALF_RATE:
2084                 case HAL_MODE_11G_QUARTER_RATE:
2085                 case HAL_MODE_11NG_HT20:
2086                 case HAL_MODE_11NG_HT40PLUS:
2087                 case HAL_MODE_11NG_HT40MINUS:
2088                         rdflags = rd2GHz->flags;
2089                         dfsMask = rd2GHz->dfsMask;
2090                         pscan = rd2GHz->pscan;
2091                         if (cm->mode == HAL_MODE_11G_HALF_RATE)
2092                                 channelBM = rd2GHz->chan11g_half;
2093                         else if (cm->mode == HAL_MODE_11G_QUARTER_RATE)
2094                                 channelBM = rd2GHz->chan11g_quarter;
2095                         else if (cm->mode == HAL_MODE_11B)
2096                                 channelBM = rd2GHz->chan11b;
2097                         else
2098                                 channelBM = rd2GHz->chan11g;
2099                         if (cm->mode == HAL_MODE_11B)
2100                                 freqs = &regDmn2GhzFreq[0];
2101                         else
2102                                 freqs = &regDmn2Ghz11gFreq[0];
2103                         break;
2104                 default:
2105                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2106                             "%s: Unkonwn HAL mode 0x%x\n", __func__, cm->mode);
2107                         continue;
2108                 }
2109                 if (isChanBitMaskZero(channelBM))
2110                         continue;
2111                 /*
2112                  * Setup special handling for HT40 channels; e.g.
2113                  * 5G HT40 channels require 40Mhz channel separation.
2114                  */
2115                 hi_adj = (cm->mode == HAL_MODE_11NA_HT40PLUS ||
2116                     cm->mode == HAL_MODE_11NG_HT40PLUS) ? -20 : 0;
2117                 low_adj = (cm->mode == HAL_MODE_11NA_HT40MINUS || 
2118                     cm->mode == HAL_MODE_11NG_HT40MINUS) ? 20 : 0;
2119                 channelSep = (cm->mode == HAL_MODE_11NA_HT40PLUS ||
2120                     cm->mode == HAL_MODE_11NA_HT40MINUS) ? 40 : 0;
2121
2122                 for (b = 0; b < 64*BMLEN; b++) {
2123                         if (!IS_BIT_SET(b, channelBM))
2124                                 continue;
2125                         fband = &freqs[b];
2126                         lastc = 0;
2127
2128                         for (c = fband->lowChannel + low_adj;
2129                              c <= fband->highChannel + hi_adj;
2130                              c += fband->channelSep) {
2131                                 if (!(c_lo <= c && c <= c_hi)) {
2132                                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2133                                             "%s: c %u out of range [%u..%u]\n",
2134                                             __func__, c, c_lo, c_hi);
2135                                         continue;
2136                                 }
2137                                 if (next >= maxchans){
2138                                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2139                                             "%s: too many channels for channel table\n",
2140                                             __func__);
2141                                         goto done;
2142                                 }
2143                                 if ((fband->usePassScan & IS_ECM_CHAN) &&
2144                                     !enableExtendedChannels) {
2145                                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2146                                             "skip ecm channel\n");
2147                                         continue;
2148                                 }
2149                                 if ((fband->useDfs & dfsMask) && 
2150                                     (cm->flags & IEEE80211_CHAN_HT40)) {
2151                                         /* NB: DFS and HT40 don't mix */
2152                                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2153                                             "skip HT40 chan, DFS required\n");
2154                                         continue;
2155                                 }
2156                                 /*
2157                                  * Make sure that channel separation
2158                                  * meets the requirement.
2159                                  */
2160                                 if (lastc && channelSep &&
2161                                     (c-lastc) < channelSep)
2162                                         continue;
2163                                 lastc = c;
2164
2165                                 OS_MEMZERO(ic, sizeof(*ic));
2166                                 ic->ic_freq = c;
2167                                 ic->ic_flags = cm->flags;
2168                                 ic->ic_maxregpower = fband->powerDfs;
2169                                 ath_hal_getpowerlimits(ah, ic);
2170                                 ic->ic_maxantgain = fband->antennaMax;
2171                                 if (fband->usePassScan & pscan)
2172                                         ic->ic_flags |= IEEE80211_CHAN_PASSIVE;
2173                                 if (fband->useDfs & dfsMask)
2174                                         ic->ic_flags |= IEEE80211_CHAN_DFS;
2175                                 if (IEEE80211_IS_CHAN_5GHZ(ic) &&
2176                                     (rdflags & DISALLOW_ADHOC_11A))
2177                                         ic->ic_flags |= IEEE80211_CHAN_NOADHOC;
2178                                 if (IEEE80211_IS_CHAN_TURBO(ic) &&
2179                                     (rdflags & DISALLOW_ADHOC_11A_TURB))
2180                                         ic->ic_flags |= IEEE80211_CHAN_NOADHOC;
2181                                 if (rdflags & NO_HOSTAP)
2182                                         ic->ic_flags |= IEEE80211_CHAN_NOHOSTAP;
2183                                 if (rdflags & LIMIT_FRAME_4MS)
2184                                         ic->ic_flags |= IEEE80211_CHAN_4MSXMIT;
2185                                 if (rdflags & NEED_NFC)
2186                                         ic->ic_flags |= CHANNEL_NFCREQUIRED;
2187
2188                                 ic++, next++;
2189                         }
2190                 }
2191         }
2192 done:
2193         *nchans = next;
2194         /* NB: pcountry set above by getregstate */
2195         if (prd2GHz != AH_NULL)
2196                 *prd2GHz = rd2GHz;
2197         if (prd5GHz != AH_NULL)
2198                 *prd5GHz = rd5GHz;
2199         return HAL_OK;
2200 #undef HAL_MODE_11A_ALL
2201 #undef CHANNEL_HALF_BW
2202 #undef CHANNEL_QUARTER_BW
2203 }
2204
2205 /*
2206  * Retrieve a channel list without affecting runtime state.
2207  */
2208 HAL_STATUS
2209 ath_hal_getchannels(struct ath_hal *ah,
2210     struct ieee80211_channel chans[], u_int maxchans, int *nchans,
2211     u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn,
2212     HAL_BOOL enableExtendedChannels)
2213 {
2214         return getchannels(ah, chans, maxchans, nchans, modeSelect,
2215             cc, regDmn, enableExtendedChannels, AH_NULL, AH_NULL, AH_NULL);
2216 }
2217
2218 /*
2219  * Handle frequency mapping from 900Mhz range to 2.4GHz range
2220  * for GSM radios.  This is done when we need the h/w frequency
2221  * and the channel is marked IEEE80211_CHAN_GSM.
2222  */
2223 static int
2224 ath_hal_mapgsm(int sku, int freq)
2225 {
2226         if (sku == SKU_XR9)
2227                 return 1520 + freq;
2228         if (sku == SKU_GZ901)
2229                 return 1544 + freq;
2230         if (sku == SKU_SR9)
2231                 return 3344 - freq;
2232         HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
2233             "%s: cannot map freq %u unknown gsm sku %u\n",
2234             __func__, freq, sku);
2235         return freq;
2236 }
2237
2238 /*
2239  * Setup the internal/private channel state given a table of
2240  * net80211 channels.  We collapse entries for the same frequency
2241  * and record the frequency for doing noise floor processing
2242  * where we don't have net80211 channel context.
2243  */
2244 static HAL_BOOL
2245 assignPrivateChannels(struct ath_hal *ah,
2246         struct ieee80211_channel chans[], int nchans, int sku)
2247 {
2248         HAL_CHANNEL_INTERNAL *ic;
2249         int i, j, next, freq;
2250
2251         next = 0;
2252         for (i = 0; i < nchans; i++) {
2253                 struct ieee80211_channel *c = &chans[i];
2254                 for (j = i-1; j >= 0; j--)
2255                         if (chans[j].ic_freq == c->ic_freq) {
2256                                 c->ic_devdata = chans[j].ic_devdata;
2257                                 break;
2258                         }
2259                 if (j < 0) {
2260                         /* new entry, assign a private channel entry */
2261                         if (next >= N(AH_PRIVATE(ah)->ah_channels)) {
2262                                 HALDEBUG(ah, HAL_DEBUG_ANY,
2263                                     "%s: too many channels, max %zu\n",
2264                                     __func__, N(AH_PRIVATE(ah)->ah_channels));
2265                                 return AH_FALSE;
2266                         }
2267                         /*
2268                          * Handle frequency mapping for 900MHz devices.
2269                          * The hardware uses 2.4GHz frequencies that are
2270                          * down-converted.  The 802.11 layer uses the
2271                          * true frequencies.
2272                          */
2273                         freq = IEEE80211_IS_CHAN_GSM(c) ?
2274                             ath_hal_mapgsm(sku, c->ic_freq) : c->ic_freq;
2275
2276                         HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
2277                             "%s: private[%3u] %u/0x%x -> channel %u\n",
2278                             __func__, next, c->ic_freq, c->ic_flags, freq);
2279
2280                         ic = &AH_PRIVATE(ah)->ah_channels[next];
2281                         /*
2282                          * NB: This clears privFlags which means ancillary
2283                          *     code like ANI and IQ calibration will be
2284                          *     restarted and re-setup any per-channel state.
2285                          */
2286                         OS_MEMZERO(ic, sizeof(*ic));
2287                         ic->channel = freq;
2288                         c->ic_devdata = next;
2289                         next++;
2290                 }
2291         }
2292         AH_PRIVATE(ah)->ah_nchan = next;
2293         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: %u public, %u private channels\n",
2294             __func__, nchans, next);
2295         return AH_TRUE;
2296 }
2297
2298 /*
2299  * Setup the channel list based on the information in the EEPROM.
2300  */
2301 HAL_STATUS
2302 ath_hal_init_channels(struct ath_hal *ah,
2303     struct ieee80211_channel chans[], u_int maxchans, int *nchans,
2304     u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn,
2305     HAL_BOOL enableExtendedChannels)
2306 {
2307         COUNTRY_CODE_TO_ENUM_RD *country;
2308         REG_DOMAIN *rd5GHz, *rd2GHz;
2309         HAL_STATUS status;
2310
2311         status = getchannels(ah, chans, maxchans, nchans, modeSelect,
2312             cc, regDmn, enableExtendedChannels, &country, &rd2GHz, &rd5GHz);
2313         if (status == HAL_OK &&
2314             assignPrivateChannels(ah, chans, *nchans, AH_PRIVATE(ah)->ah_currentRD)) {
2315                 AH_PRIVATE(ah)->ah_rd2GHz = rd2GHz;
2316                 AH_PRIVATE(ah)->ah_rd5GHz = rd5GHz;
2317
2318                 ah->ah_countryCode = country->countryCode;
2319                 HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u\n",
2320                     __func__, ah->ah_countryCode);
2321         } else
2322                 status = HAL_EINVAL;
2323         return status;
2324 }
2325
2326 /*
2327  * Set the channel list.
2328  */
2329 HAL_STATUS
2330 ath_hal_set_channels(struct ath_hal *ah,
2331     struct ieee80211_channel chans[], int nchans,
2332     HAL_CTRY_CODE cc, HAL_REG_DOMAIN rd)
2333 {
2334         COUNTRY_CODE_TO_ENUM_RD *country;
2335         REG_DOMAIN *rd5GHz, *rd2GHz;
2336         HAL_STATUS status;
2337
2338         switch (rd) {
2339         case SKU_SR9:
2340         case SKU_XR9:
2341         case SKU_GZ901:
2342                 /*
2343                  * Map 900MHz sku's.  The frequencies will be mapped
2344                  * according to the sku to compensate for the down-converter.
2345                  * We use the FCC for these sku's as the mapped channel
2346                  * list is known compatible (will need to change if/when
2347                  * vendors do different mapping in different locales).
2348                  */
2349                 status = getregstate(ah, CTRY_DEFAULT, SKU_FCC,
2350                     &country, &rd2GHz, &rd5GHz);
2351                 break;
2352         default:
2353                 status = getregstate(ah, cc, rd,
2354                     &country, &rd2GHz, &rd5GHz);
2355                 rd = AH_PRIVATE(ah)->ah_currentRD;
2356                 break;
2357         }
2358         if (status == HAL_OK && assignPrivateChannels(ah, chans, nchans, rd)) {
2359                 AH_PRIVATE(ah)->ah_rd2GHz = rd2GHz;
2360                 AH_PRIVATE(ah)->ah_rd5GHz = rd5GHz;
2361
2362                 ah->ah_countryCode = country->countryCode;
2363                 HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u\n",
2364                     __func__, ah->ah_countryCode);
2365         } else
2366                 status = HAL_EINVAL;
2367         return status;
2368 }
2369
2370 #ifdef AH_DEBUG
2371 /*
2372  * Return the internal channel corresponding to a public channel.
2373  * NB: normally this routine is inline'd (see ah_internal.h)
2374  */
2375 HAL_CHANNEL_INTERNAL *
2376 ath_hal_checkchannel(struct ath_hal *ah, const struct ieee80211_channel *c)
2377 {
2378         HAL_CHANNEL_INTERNAL *cc = &AH_PRIVATE(ah)->ah_channels[c->ic_devdata];
2379
2380         if (c->ic_devdata < AH_PRIVATE(ah)->ah_nchan &&
2381             (c->ic_freq == cc->channel || IEEE80211_IS_CHAN_GSM(c)))
2382                 return cc;
2383         if (c->ic_devdata >= AH_PRIVATE(ah)->ah_nchan) {
2384                 HALDEBUG(ah, HAL_DEBUG_ANY,
2385                     "%s: bad mapping, devdata %u nchans %u\n",
2386                    __func__, c->ic_devdata, AH_PRIVATE(ah)->ah_nchan);
2387                 HALASSERT(c->ic_devdata < AH_PRIVATE(ah)->ah_nchan);
2388         } else {
2389                 HALDEBUG(ah, HAL_DEBUG_ANY,
2390                     "%s: no match for %u/0x%x devdata %u channel %u\n",
2391                    __func__, c->ic_freq, c->ic_flags, c->ic_devdata,
2392                    cc->channel);
2393                 HALASSERT(c->ic_freq == cc->channel || IEEE80211_IS_CHAN_GSM(c));
2394         }
2395         return AH_NULL;
2396 }
2397 #endif /* AH_DEBUG */
2398
2399 #define isWwrSKU(_ah) \
2400         ((getEepromRD((_ah)) & WORLD_SKU_MASK) == WORLD_SKU_PREFIX || \
2401           getEepromRD(_ah) == WORLD)
2402
2403 /*
2404  * Return the test group for the specific channel based on
2405  * the current regulatory setup.
2406  */
2407 u_int
2408 ath_hal_getctl(struct ath_hal *ah, const struct ieee80211_channel *c)
2409 {
2410         u_int ctl;
2411
2412         if (AH_PRIVATE(ah)->ah_rd2GHz == AH_PRIVATE(ah)->ah_rd5GHz ||
2413             (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)))
2414                 ctl = SD_NO_CTL;
2415         else if (IEEE80211_IS_CHAN_2GHZ(c))
2416                 ctl = AH_PRIVATE(ah)->ah_rd2GHz->conformanceTestLimit;
2417         else
2418                 ctl = AH_PRIVATE(ah)->ah_rd5GHz->conformanceTestLimit;
2419         if (IEEE80211_IS_CHAN_B(c))
2420                 return ctl | CTL_11B;
2421         if (IEEE80211_IS_CHAN_G(c))
2422                 return ctl | CTL_11G;
2423         if (IEEE80211_IS_CHAN_108G(c))
2424                 return ctl | CTL_108G;
2425         if (IEEE80211_IS_CHAN_TURBO(c))
2426                 return ctl | CTL_TURBO;
2427         if (IEEE80211_IS_CHAN_A(c))
2428                 return ctl | CTL_11A;
2429         return ctl;
2430 }
2431
2432 /*
2433  * Return the max allowed antenna gain and apply any regulatory
2434  * domain specific changes.
2435  *
2436  * NOTE: a negative reduction is possible in RD's that only
2437  * measure radiated power (e.g., ETSI) which would increase
2438  * that actual conducted output power (though never beyond
2439  * the calibrated target power).
2440  */
2441 u_int
2442 ath_hal_getantennareduction(struct ath_hal *ah,
2443     const struct ieee80211_channel *chan, u_int twiceGain)
2444 {
2445         int8_t antennaMax = twiceGain - chan->ic_maxantgain*2;
2446         return (antennaMax < 0) ? 0 : antennaMax;
2447 }