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