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