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