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