xref: /freebsd/tools/tools/ath/athrd/athrd.c (revision b3e76948)
1 /*-
2  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 #include "opt_ah.h"
30 
31 #include "ah.h"
32 
33 #include <sys/param.h>
34 
35 #include <net80211/_ieee80211.h>
36 #include <net80211/ieee80211_regdomain.h>
37 
38 #include "ah_internal.h"
39 #include "ah_eeprom_v3.h"		/* XXX */
40 
41 #include <ctype.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 
48 int		ath_hal_debug = 0;
49 HAL_CTRY_CODE	cc = CTRY_DEFAULT;
50 HAL_REG_DOMAIN	rd = 169;		/* FCC */
51 HAL_BOOL	Amode = 1;
52 HAL_BOOL	Bmode = 1;
53 HAL_BOOL	Gmode = 1;
54 HAL_BOOL	HT20mode = 1;
55 HAL_BOOL	HT40mode = 1;
56 HAL_BOOL	turbo5Disable = AH_FALSE;
57 HAL_BOOL	turbo2Disable = AH_FALSE;
58 
59 u_int16_t	_numCtls = 8;
60 u_int16_t	_ctl[32] =
61 	{ 0x10, 0x13, 0x40, 0x30, 0x11, 0x31, 0x12, 0x32 };
62 RD_EDGES_POWER	_rdEdgesPower[NUM_EDGES*NUM_CTLS] = {
63 	{ 5180, 28, 0 },	/* 0x10 */
64 	{ 5240, 60, 0 },
65 	{ 5260, 36, 0 },
66 	{ 5320, 27, 0 },
67 	{ 5745, 36, 0 },
68 	{ 5765, 36, 0 },
69 	{ 5805, 36, 0 },
70 	{ 5825, 36, 0 },
71 
72 	{ 5210, 28, 0 },	/* 0x13 */
73 	{ 5250, 28, 0 },
74 	{ 5290, 30, 0 },
75 	{ 5760, 36, 0 },
76 	{ 5800, 36, 0 },
77 	{ 0, 0, 0 },
78 	{ 0, 0, 0 },
79 	{ 0, 0, 0 },
80 
81 	{ 5170, 60, 0 },	/* 0x40 */
82 	{ 5230, 60, 0 },
83 	{ 0, 0, 0 },
84 	{ 0, 0, 0 },
85 	{ 0, 0, 0 },
86 	{ 0, 0, 0 },
87 	{ 0, 0, 0 },
88 	{ 0, 0, 0 },
89 
90 	{ 5180, 33, 0 },	/* 0x30 */
91 	{ 5320, 33, 0 },
92 	{ 5500, 34, 0 },
93 	{ 5700, 34, 0 },
94 	{ 5745, 35, 0 },
95 	{ 5765, 35, 0 },
96 	{ 5785, 35, 0 },
97 	{ 5825, 35, 0 },
98 
99 	{ 2412, 36, 0 },	/* 0x11 */
100 	{ 2417, 36, 0 },
101 	{ 2422, 36, 0 },
102 	{ 2432, 36, 0 },
103 	{ 2442, 36, 0 },
104 	{ 2457, 36, 0 },
105 	{ 2467, 36, 0 },
106 	{ 2472, 36, 0 },
107 
108 	{ 2412, 36, 0 },	/* 0x31 */
109 	{ 2417, 36, 0 },
110 	{ 2422, 36, 0 },
111 	{ 2432, 36, 0 },
112 	{ 2442, 36, 0 },
113 	{ 2457, 36, 0 },
114 	{ 2467, 36, 0 },
115 	{ 2472, 36, 0 },
116 
117 	{ 2412, 36, 0 },	/* 0x12 */
118 	{ 2417, 36, 0 },
119 	{ 2422, 36, 0 },
120 	{ 2432, 36, 0 },
121 	{ 2442, 36, 0 },
122 	{ 2457, 36, 0 },
123 	{ 2467, 36, 0 },
124 	{ 2472, 36, 0 },
125 
126 	{ 2412, 28, 0 },	/* 0x32 */
127 	{ 2417, 28, 0 },
128 	{ 2422, 28, 0 },
129 	{ 2432, 28, 0 },
130 	{ 2442, 28, 0 },
131 	{ 2457, 28, 0 },
132 	{ 2467, 28, 0 },
133 	{ 2472, 28, 0 },
134 };
135 
136 u_int16_t	turbo2WMaxPower5 = 32;
137 u_int16_t	turbo2WMaxPower2;
138 int8_t		antennaGainMax[2] = { 0, 0 };	/* XXX */
139 int		eeversion = AR_EEPROM_VER3_1;
140 TRGT_POWER_ALL_MODES tpow = {
141 	8, {
142 	    { 22, 24, 28, 32, 5180 },
143 	    { 22, 24, 28, 32, 5200 },
144 	    { 22, 24, 28, 32, 5320 },
145 	    { 26, 30, 34, 34, 5500 },
146 	    { 26, 30, 34, 34, 5700 },
147 	    { 20, 30, 34, 36, 5745 },
148 	    { 20, 30, 34, 36, 5825 },
149 	    { 20, 30, 34, 36, 5850 },
150 	},
151 	2, {
152 	    { 23, 27, 31, 34, 2412 },
153 	    { 23, 27, 31, 34, 2447 },
154 	},
155 	2, {
156 	    { 36, 36, 36, 36, 2412 },
157 	    { 36, 36, 36, 36, 2484 },
158 	}
159 };
160 #define	numTargetPwr_11a	tpow.numTargetPwr_11a
161 #define	trgtPwr_11a		tpow.trgtPwr_11a
162 #define	numTargetPwr_11g	tpow.numTargetPwr_11g
163 #define	trgtPwr_11g		tpow.trgtPwr_11g
164 #define	numTargetPwr_11b	tpow.numTargetPwr_11b
165 #define	trgtPwr_11b		tpow.trgtPwr_11b
166 
167 static HAL_BOOL
getChannelEdges(struct ath_hal * ah,u_int16_t flags,u_int16_t * low,u_int16_t * high)168 getChannelEdges(struct ath_hal *ah, u_int16_t flags, u_int16_t *low, u_int16_t *high)
169 {
170 	struct ath_hal_private *ahp = AH_PRIVATE(ah);
171 	HAL_CAPABILITIES *pCap = &ahp->ah_caps;
172 
173 	if (flags & IEEE80211_CHAN_5GHZ) {
174 		*low = pCap->halLow5GhzChan;
175 		*high = pCap->halHigh5GhzChan;
176 		return AH_TRUE;
177 	}
178 	if (flags & IEEE80211_CHAN_2GHZ) {
179 		*low = pCap->halLow2GhzChan;
180 		*high = pCap->halHigh2GhzChan;
181 		return AH_TRUE;
182 	}
183 	return AH_FALSE;
184 }
185 
186 static u_int
getWirelessModes(struct ath_hal * ah)187 getWirelessModes(struct ath_hal *ah)
188 {
189 	u_int mode = 0;
190 
191 	if (Amode) {
192 		mode = HAL_MODE_11A;
193 		if (!turbo5Disable)
194 			mode |= HAL_MODE_TURBO;
195 	}
196 	if (Bmode)
197 		mode |= HAL_MODE_11B;
198 	if (Gmode) {
199 		mode |= HAL_MODE_11G;
200 		if (!turbo2Disable)
201 			mode |= HAL_MODE_108G;
202 	}
203 	if (HT20mode)
204 		mode |= HAL_MODE_11NG_HT20|HAL_MODE_11NA_HT20;
205 	if (HT40mode)
206 		mode |= HAL_MODE_11NG_HT40PLUS|HAL_MODE_11NA_HT40PLUS
207 		     |  HAL_MODE_11NG_HT40MINUS|HAL_MODE_11NA_HT40MINUS
208 		     ;
209 	return mode;
210 }
211 
212 /* Enumerated Regulatory Domain Information 8 bit values indicate that
213  * the regdomain is really a pair of unitary regdomains.  12 bit values
214  * are the real unitary regdomains and are the only ones which have the
215  * frequency bitmasks and flags set.
216  */
217 
218 enum EnumRd {
219 	/*
220 	 * The following regulatory domain definitions are
221 	 * found in the EEPROM. Each regulatory domain
222 	 * can operate in either a 5GHz or 2.4GHz wireless mode or
223 	 * both 5GHz and 2.4GHz wireless modes.
224 	 * In general, the value holds no special
225 	 * meaning and is used to decode into either specific
226 	 * 2.4GHz or 5GHz wireless mode for that particular
227 	 * regulatory domain.
228 	 */
229 	NO_ENUMRD	= 0x00,
230 	NULL1_WORLD	= 0x03,		/* For 11b-only countries (no 11a allowed) */
231 	NULL1_ETSIB	= 0x07,		/* Israel */
232 	NULL1_ETSIC	= 0x08,
233 	FCC1_FCCA	= 0x10,		/* USA */
234 	FCC1_WORLD	= 0x11,		/* Hong Kong */
235 	FCC4_FCCA	= 0x12,		/* USA - Public Safety */
236 
237 	FCC2_FCCA	= 0x20,		/* Canada */
238 	FCC2_WORLD	= 0x21,		/* Australia & HK */
239 	FCC2_ETSIC	= 0x22,
240 	FRANCE_RES	= 0x31,		/* Legacy France for OEM */
241 	FCC3_FCCA	= 0x3A,		/* USA & Canada w/5470 band, 11h, DFS enabled */
242 	FCC3_WORLD  = 0x3B,     /* USA & Canada w/5470 band, 11h, DFS enabled */
243 
244 	ETSI1_WORLD	= 0x37,
245 	ETSI3_ETSIA	= 0x32,		/* France (optional) */
246 	ETSI2_WORLD	= 0x35,		/* Hungary & others */
247 	ETSI3_WORLD	= 0x36,		/* France & others */
248 	ETSI4_WORLD	= 0x30,
249 	ETSI4_ETSIC	= 0x38,
250 	ETSI5_WORLD	= 0x39,
251 	ETSI6_WORLD	= 0x34,		/* Bulgaria */
252 	ETSI_RESERVED	= 0x33,		/* Reserved (Do not used) */
253 
254 	MKK1_MKKA	= 0x40,		/* Japan (JP1) */
255 	MKK1_MKKB	= 0x41,		/* Japan (JP0) */
256 	APL4_WORLD	= 0x42,		/* Singapore */
257 	MKK2_MKKA	= 0x43,		/* Japan with 4.9G channels */
258 	APL_RESERVED	= 0x44,		/* Reserved (Do not used)  */
259 	APL2_WORLD	= 0x45,		/* Korea */
260 	APL2_APLC	= 0x46,
261 	APL3_WORLD	= 0x47,
262 	MKK1_FCCA	= 0x48,		/* Japan (JP1-1) */
263 	APL2_APLD	= 0x49,		/* Korea with 2.3G channels */
264 	MKK1_MKKA1	= 0x4A,		/* Japan (JE1) */
265 	MKK1_MKKA2	= 0x4B,		/* Japan (JE2) */
266 	MKK1_MKKC	= 0x4C,		/* Japan (MKK1_MKKA,except Ch14) */
267 
268 	APL3_FCCA   = 0x50,
269 	APL1_WORLD	= 0x52,		/* Latin America */
270 	APL1_FCCA	= 0x53,
271 	APL1_APLA	= 0x54,
272 	APL1_ETSIC	= 0x55,
273 	APL2_ETSIC	= 0x56,		/* Venezuela */
274 	APL5_WORLD	= 0x58,		/* Chile */
275 	APL6_WORLD	= 0x5B,		/* Singapore */
276 	APL7_FCCA   = 0x5C,     /* Taiwan 5.47 Band */
277 	APL8_WORLD  = 0x5D,     /* Malaysia 5GHz */
278 	APL9_WORLD  = 0x5E,     /* Korea 5GHz */
279 
280 	/*
281 	 * World mode SKUs
282 	 */
283 	WOR0_WORLD	= 0x60,		/* World0 (WO0 SKU) */
284 	WOR1_WORLD	= 0x61,		/* World1 (WO1 SKU) */
285 	WOR2_WORLD	= 0x62,		/* World2 (WO2 SKU) */
286 	WOR3_WORLD	= 0x63,		/* World3 (WO3 SKU) */
287 	WOR4_WORLD	= 0x64,		/* World4 (WO4 SKU) */
288 	WOR5_ETSIC	= 0x65,		/* World5 (WO5 SKU) */
289 
290 	WOR01_WORLD	= 0x66,		/* World0-1 (WW0-1 SKU) */
291 	WOR02_WORLD	= 0x67,		/* World0-2 (WW0-2 SKU) */
292 	EU1_WORLD	= 0x68,		/* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */
293 
294 	WOR9_WORLD	= 0x69,		/* World9 (WO9 SKU) */
295 	WORA_WORLD	= 0x6A,		/* WorldA (WOA SKU) */
296 
297 	MKK3_MKKB	= 0x80,		/* Japan UNI-1 even + MKKB */
298 	MKK3_MKKA2	= 0x81,		/* Japan UNI-1 even + MKKA2 */
299 	MKK3_MKKC	= 0x82,		/* Japan UNI-1 even + MKKC */
300 
301 	MKK4_MKKB	= 0x83,		/* Japan UNI-1 even + UNI-2 + MKKB */
302 	MKK4_MKKA2	= 0x84,		/* Japan UNI-1 even + UNI-2 + MKKA2 */
303 	MKK4_MKKC	= 0x85,		/* Japan UNI-1 even + UNI-2 + MKKC */
304 
305 	MKK5_MKKB	= 0x86,		/* Japan UNI-1 even + UNI-2 + mid-band + MKKB */
306 	MKK5_MKKA2	= 0x87,		/* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */
307 	MKK5_MKKC	= 0x88,		/* Japan UNI-1 even + UNI-2 + mid-band + MKKC */
308 
309 	MKK6_MKKB	= 0x89,		/* Japan UNI-1 even + UNI-1 odd MKKB */
310 	MKK6_MKKA2	= 0x8A,		/* Japan UNI-1 even + UNI-1 odd + MKKA2 */
311 	MKK6_MKKC	= 0x8B,		/* Japan UNI-1 even + UNI-1 odd + MKKC */
312 
313 	MKK7_MKKB	= 0x8C,		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */
314 	MKK7_MKKA2	= 0x8D,		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */
315 	MKK7_MKKC	= 0x8E,		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */
316 
317 	MKK8_MKKB	= 0x8F,		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */
318 	MKK8_MKKA2	= 0x90,		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */
319 	MKK8_MKKC	= 0x91,		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */
320 
321 	/* Following definitions are used only by s/w to map old
322  	 * Japan SKUs.
323 	 */
324 	MKK3_MKKA       = 0xF0,         /* Japan UNI-1 even + MKKA */
325 	MKK3_MKKA1      = 0xF1,         /* Japan UNI-1 even + MKKA1 */
326 	MKK3_FCCA       = 0xF2,         /* Japan UNI-1 even + FCCA */
327 	MKK4_MKKA       = 0xF3,         /* Japan UNI-1 even + UNI-2 + MKKA */
328 	MKK4_MKKA1      = 0xF4,         /* Japan UNI-1 even + UNI-2 + MKKA1 */
329 	MKK4_FCCA       = 0xF5,         /* Japan UNI-1 even + UNI-2 + FCCA */
330 	MKK9_MKKA       = 0xF6,         /* Japan UNI-1 even + 4.9GHz */
331 	MKK10_MKKA      = 0xF7,         /* Japan UNI-1 even + UNI-2 + 4.9GHz */
332 
333 	/*
334 	 * Regulator domains ending in a number (e.g. APL1,
335 	 * MK1, ETSI4, etc) apply to 5GHz channel and power
336 	 * information.  Regulator domains ending in a letter
337 	 * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and
338 	 * power information.
339 	 */
340 	APL1		= 0x0150,	/* LAT & Asia */
341 	APL2		= 0x0250,	/* LAT & Asia */
342 	APL3		= 0x0350,	/* Taiwan */
343 	APL4		= 0x0450,	/* Jordan */
344 	APL5		= 0x0550,	/* Chile */
345 	APL6		= 0x0650,	/* Singapore */
346 	APL8		= 0x0850,	/* Malaysia */
347 	APL9		= 0x0950,	/* Korea (South) ROC 3 */
348 
349 	ETSI1		= 0x0130,	/* Europe & others */
350 	ETSI2		= 0x0230,	/* Europe & others */
351 	ETSI3		= 0x0330,	/* Europe & others */
352 	ETSI4		= 0x0430,	/* Europe & others */
353 	ETSI5		= 0x0530,	/* Europe & others */
354 	ETSI6		= 0x0630,	/* Europe & others */
355 	ETSIA		= 0x0A30,	/* France */
356 	ETSIB		= 0x0B30,	/* Israel */
357 	ETSIC		= 0x0C30,	/* Latin America */
358 
359 	FCC1		= 0x0110,	/* US & others */
360 	FCC2		= 0x0120,	/* Canada, Australia & New Zealand */
361 	FCC3		= 0x0160,	/* US w/new middle band & DFS */
362 	FCC4          	= 0x0165,     	/* US Public Safety */
363 	FCCA		= 0x0A10,
364 
365 	APLD		= 0x0D50,	/* South Korea */
366 
367 	MKK1		= 0x0140,	/* Japan (UNI-1 odd)*/
368 	MKK2		= 0x0240,	/* Japan (4.9 GHz + UNI-1 odd) */
369 	MKK3		= 0x0340,	/* Japan (UNI-1 even) */
370 	MKK4		= 0x0440,	/* Japan (UNI-1 even + UNI-2) */
371 	MKK5		= 0x0540,	/* Japan (UNI-1 even + UNI-2 + mid-band) */
372 	MKK6		= 0x0640,	/* Japan (UNI-1 odd + UNI-1 even) */
373 	MKK7		= 0x0740,	/* Japan (UNI-1 odd + UNI-1 even + UNI-2 */
374 	MKK8		= 0x0840,	/* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */
375 	MKK9            = 0x0940,       /* Japan (UNI-1 even + 4.9 GHZ) */
376 	MKK10           = 0x0B40,       /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
377 	MKKA		= 0x0A40,	/* Japan */
378 	MKKC		= 0x0A50,
379 
380 	NULL1		= 0x0198,
381 	WORLD		= 0x0199,
382 	DEBUG_REG_DMN	= 0x01ff,
383 };
384 #define DEF_REGDMN		FCC1_FCCA
385 
386 static struct {
387 	const char *name;
388 	HAL_REG_DOMAIN rd;
389 } domains[] = {
390 #define	D(_x)	{ #_x, _x }
391 	D(NO_ENUMRD),
392 	D(NULL1_WORLD),		/* For 11b-only countries (no 11a allowed) */
393 	D(NULL1_ETSIB),		/* Israel */
394 	D(NULL1_ETSIC),
395 	D(FCC1_FCCA),		/* USA */
396 	D(FCC1_WORLD),		/* Hong Kong */
397 	D(FCC4_FCCA),		/* USA - Public Safety */
398 
399 	D(FCC2_FCCA),		/* Canada */
400 	D(FCC2_WORLD),		/* Australia & HK */
401 	D(FCC2_ETSIC),
402 	D(FRANCE_RES),		/* Legacy France for OEM */
403 	D(FCC3_FCCA),
404 	D(FCC3_WORLD),
405 
406 	D(ETSI1_WORLD),
407 	D(ETSI3_ETSIA),		/* France (optional) */
408 	D(ETSI2_WORLD),		/* Hungary & others */
409 	D(ETSI3_WORLD),		/* France & others */
410 	D(ETSI4_WORLD),
411 	D(ETSI4_ETSIC),
412 	D(ETSI5_WORLD),
413 	D(ETSI6_WORLD),		/* Bulgaria */
414 	D(ETSI_RESERVED),		/* Reserved (Do not used) */
415 
416 	D(MKK1_MKKA),		/* Japan (JP1) */
417 	D(MKK1_MKKB),		/* Japan (JP0) */
418 	D(APL4_WORLD),		/* Singapore */
419 	D(MKK2_MKKA),		/* Japan with 4.9G channels */
420 	D(APL_RESERVED),		/* Reserved (Do not used)  */
421 	D(APL2_WORLD),		/* Korea */
422 	D(APL2_APLC),
423 	D(APL3_WORLD),
424 	D(MKK1_FCCA),		/* Japan (JP1-1) */
425 	D(APL2_APLD),		/* Korea with 2.3G channels */
426 	D(MKK1_MKKA1),		/* Japan (JE1) */
427 	D(MKK1_MKKA2),		/* Japan (JE2) */
428 	D(MKK1_MKKC),
429 
430 	D(APL3_FCCA),
431 	D(APL1_WORLD),		/* Latin America */
432 	D(APL1_FCCA),
433 	D(APL1_APLA),
434 	D(APL1_ETSIC),
435 	D(APL2_ETSIC),		/* Venezuela */
436 	D(APL5_WORLD),		/* Chile */
437 	D(APL6_WORLD),		/* Singapore */
438 	D(APL7_FCCA),     /* Taiwan 5.47 Band */
439 	D(APL8_WORLD),     /* Malaysia 5GHz */
440 	D(APL9_WORLD),     /* Korea 5GHz */
441 
442 	D(WOR0_WORLD),		/* World0 (WO0 SKU) */
443 	D(WOR1_WORLD),		/* World1 (WO1 SKU) */
444 	D(WOR2_WORLD),		/* World2 (WO2 SKU) */
445 	D(WOR3_WORLD),		/* World3 (WO3 SKU) */
446 	D(WOR4_WORLD),		/* World4 (WO4 SKU) */
447 	D(WOR5_ETSIC),		/* World5 (WO5 SKU) */
448 
449 	D(WOR01_WORLD),		/* World0-1 (WW0-1 SKU) */
450 	D(WOR02_WORLD),		/* World0-2 (WW0-2 SKU) */
451 	D(EU1_WORLD),
452 
453 	D(WOR9_WORLD),		/* World9 (WO9 SKU) */
454 	D(WORA_WORLD),		/* WorldA (WOA SKU) */
455 
456 	D(MKK3_MKKB),		/* Japan UNI-1 even + MKKB */
457 	D(MKK3_MKKA2),		/* Japan UNI-1 even + MKKA2 */
458 	D(MKK3_MKKC),		/* Japan UNI-1 even + MKKC */
459 
460 	D(MKK4_MKKB),		/* Japan UNI-1 even + UNI-2 + MKKB */
461 	D(MKK4_MKKA2),		/* Japan UNI-1 even + UNI-2 + MKKA2 */
462 	D(MKK4_MKKC),		/* Japan UNI-1 even + UNI-2 + MKKC */
463 
464 	D(MKK5_MKKB),		/* Japan UNI-1 even + UNI-2 + mid-band + MKKB */
465 	D(MKK5_MKKA2),		/* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */
466 	D(MKK5_MKKC),		/* Japan UNI-1 even + UNI-2 + mid-band + MKKC */
467 
468 	D(MKK6_MKKB),		/* Japan UNI-1 even + UNI-1 odd MKKB */
469 	D(MKK6_MKKA2),		/* Japan UNI-1 even + UNI-1 odd + MKKA2 */
470 	D(MKK6_MKKC),		/* Japan UNI-1 even + UNI-1 odd + MKKC */
471 
472 	D(MKK7_MKKB),		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */
473 	D(MKK7_MKKA2),		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */
474 	D(MKK7_MKKC),		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */
475 
476 	D(MKK8_MKKB),		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */
477 	D(MKK8_MKKA2),		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */
478 	D(MKK8_MKKC),		/* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */
479 
480 	D(MKK3_MKKA),         /* Japan UNI-1 even + MKKA */
481 	D(MKK3_MKKA1),         /* Japan UNI-1 even + MKKA1 */
482 	D(MKK3_FCCA),         /* Japan UNI-1 even + FCCA */
483 	D(MKK4_MKKA),         /* Japan UNI-1 even + UNI-2 + MKKA */
484 	D(MKK4_MKKA1),         /* Japan UNI-1 even + UNI-2 + MKKA1 */
485 	D(MKK4_FCCA),         /* Japan UNI-1 even + UNI-2 + FCCA */
486 	D(MKK9_MKKA),         /* Japan UNI-1 even + 4.9GHz */
487 	D(MKK10_MKKA),         /* Japan UNI-1 even + UNI-2 + 4.9GHz */
488 
489 	D(APL1),	/* LAT & Asia */
490 	D(APL2),	/* LAT & Asia */
491 	D(APL3),	/* Taiwan */
492 	D(APL4),	/* Jordan */
493 	D(APL5),	/* Chile */
494 	D(APL6),	/* Singapore */
495 	D(APL8),	/* Malaysia */
496 	D(APL9),	/* Korea (South) ROC 3 */
497 
498 	D(ETSI1),	/* Europe & others */
499 	D(ETSI2),	/* Europe & others */
500 	D(ETSI3),	/* Europe & others */
501 	D(ETSI4),	/* Europe & others */
502 	D(ETSI5),	/* Europe & others */
503 	D(ETSI6),	/* Europe & others */
504 	D(ETSIA),	/* France */
505 	D(ETSIB),	/* Israel */
506 	D(ETSIC),	/* Latin America */
507 
508 	D(FCC1),	/* US & others */
509 	D(FCC2),
510 	D(FCC3),	/* US w/new middle band & DFS */
511 	D(FCC4),     	/* US Public Safety */
512 	D(FCCA),
513 
514 	D(APLD),	/* South Korea */
515 
516 	D(MKK1),	/* Japan (UNI-1 odd)*/
517 	D(MKK2),	/* Japan (4.9 GHz + UNI-1 odd) */
518 	D(MKK3),	/* Japan (UNI-1 even) */
519 	D(MKK4),	/* Japan (UNI-1 even + UNI-2) */
520 	D(MKK5),	/* Japan (UNI-1 even + UNI-2 + mid-band) */
521 	D(MKK6),	/* Japan (UNI-1 odd + UNI-1 even) */
522 	D(MKK7),	/* Japan (UNI-1 odd + UNI-1 even + UNI-2 */
523 	D(MKK8),	/* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */
524 	D(MKK9),       /* Japan (UNI-1 even + 4.9 GHZ) */
525 	D(MKK10),       /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
526 	D(MKKA),	/* Japan */
527 	D(MKKC),
528 
529 	D(NULL1),
530 	D(WORLD),
531 	D(DEBUG_REG_DMN),
532 #undef D
533 };
534 
535 static HAL_BOOL
rdlookup(const char * name,HAL_REG_DOMAIN * rd)536 rdlookup(const char *name, HAL_REG_DOMAIN *rd)
537 {
538 	int i;
539 
540 	for (i = 0; i < nitems(domains); i++)
541 		if (strcasecmp(domains[i].name, name) == 0) {
542 			*rd = domains[i].rd;
543 			return AH_TRUE;
544 		}
545 	return AH_FALSE;
546 }
547 
548 static const char *
getrdname(HAL_REG_DOMAIN rd)549 getrdname(HAL_REG_DOMAIN rd)
550 {
551 	int i;
552 
553 	for (i = 0; i < nitems(domains); i++)
554 		if (domains[i].rd == rd)
555 			return domains[i].name;
556 	return NULL;
557 }
558 
559 static void
rdlist()560 rdlist()
561 {
562 	int i;
563 
564 	printf("\nRegulatory domains:\n\n");
565 	for (i = 0; i < nitems(domains); i++)
566 		printf("%-15s%s", domains[i].name,
567 			((i+1)%5) == 0 ? "\n" : "");
568 	printf("\n");
569 }
570 
571 typedef struct {
572 	HAL_CTRY_CODE	countryCode;
573 	HAL_REG_DOMAIN	regDmnEnum;
574 	const char*	isoName;
575 	const char*	name;
576 } COUNTRY_CODE_TO_ENUM_RD;
577 
578 /*
579  * Country Code Table to Enumerated RD
580  */
581 static COUNTRY_CODE_TO_ENUM_RD allCountries[] = {
582     {CTRY_DEBUG,       NO_ENUMRD,     "DB", "DEBUG" },
583     {CTRY_DEFAULT,     DEF_REGDMN,    "NA", "NO_COUNTRY_SET" },
584     {CTRY_ALBANIA,     NULL1_WORLD,   "AL", "ALBANIA" },
585     {CTRY_ALGERIA,     NULL1_WORLD,   "DZ", "ALGERIA" },
586     {CTRY_ARGENTINA,   APL3_WORLD,    "AR", "ARGENTINA" },
587     {CTRY_ARMENIA,     ETSI4_WORLD,   "AM", "ARMENIA" },
588     {CTRY_AUSTRALIA,   FCC2_WORLD,    "AU", "AUSTRALIA" },
589     {CTRY_AUSTRIA,     ETSI1_WORLD,   "AT", "AUSTRIA" },
590     {CTRY_AZERBAIJAN,  ETSI4_WORLD,   "AZ", "AZERBAIJAN" },
591     {CTRY_BAHRAIN,     APL6_WORLD,   "BH", "BAHRAIN" },
592     {CTRY_BELARUS,     NULL1_WORLD,   "BY", "BELARUS" },
593     {CTRY_BELGIUM,     ETSI1_WORLD,   "BE", "BELGIUM" },
594     {CTRY_BELIZE,      APL1_ETSIC,    "BZ", "BELIZE" },
595     {CTRY_BOLIVIA,     APL1_ETSIC,    "BO", "BOLVIA" },
596     {CTRY_BRAZIL,      FCC3_WORLD,    "BR", "BRAZIL" },
597     {CTRY_BRUNEI_DARUSSALAM,APL1_WORLD,"BN", "BRUNEI DARUSSALAM" },
598     {CTRY_BULGARIA,    ETSI6_WORLD,   "BG", "BULGARIA" },
599     {CTRY_CANADA,      FCC2_FCCA,     "CA", "CANADA" },
600     {CTRY_CHILE,       APL6_WORLD,    "CL", "CHILE" },
601     {CTRY_CHINA,       APL1_WORLD,    "CN", "CHINA" },
602     {CTRY_COLOMBIA,    FCC1_FCCA,     "CO", "COLOMBIA" },
603     {CTRY_COSTA_RICA,  NULL1_WORLD,   "CR", "COSTA RICA" },
604     {CTRY_CROATIA,     ETSI3_WORLD,   "HR", "CROATIA" },
605     {CTRY_CYPRUS,      ETSI1_WORLD,   "CY", "CYPRUS" },
606     {CTRY_CZECH,       ETSI3_WORLD,   "CZ", "CZECH REPUBLIC" },
607     {CTRY_DENMARK,     ETSI1_WORLD,   "DK", "DENMARK" },
608     {CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA,"DO", "DOMINICAN REPUBLIC" },
609     {CTRY_ECUADOR,     NULL1_WORLD,   "EC", "ECUADOR" },
610     {CTRY_EGYPT,       ETSI3_WORLD,   "EG", "EGYPT" },
611     {CTRY_EL_SALVADOR, NULL1_WORLD,   "SV", "EL SALVADOR" },
612     {CTRY_ESTONIA,     ETSI1_WORLD,   "EE", "ESTONIA" },
613     {CTRY_FINLAND,     ETSI1_WORLD,   "FI", "FINLAND" },
614     {CTRY_FRANCE,      ETSI3_WORLD,   "FR", "FRANCE" },
615     {CTRY_FRANCE2,     ETSI3_WORLD,   "F2", "FRANCE_RES" },
616     {CTRY_GEORGIA,     ETSI4_WORLD,   "GE", "GEORGIA" },
617     {CTRY_GERMANY,     ETSI1_WORLD,   "DE", "GERMANY" },
618     {CTRY_GREECE,      ETSI1_WORLD,   "GR", "GREECE" },
619     {CTRY_GUATEMALA,   FCC1_FCCA,     "GT", "GUATEMALA" },
620     {CTRY_HONDURAS,    NULL1_WORLD,   "HN", "HONDURAS" },
621     {CTRY_HONG_KONG,   FCC2_WORLD,    "HK", "HONG KONG" },
622     {CTRY_HUNGARY,     ETSI1_WORLD,   "HU", "HUNGARY" },
623     {CTRY_ICELAND,     ETSI1_WORLD,   "IS", "ICELAND" },
624     {CTRY_INDIA,       APL6_WORLD,    "IN", "INDIA" },
625     {CTRY_INDONESIA,   APL1_WORLD,    "ID", "INDONESIA" },
626     {CTRY_IRAN,        APL1_WORLD,    "IR", "IRAN" },
627     {CTRY_IRELAND,     ETSI1_WORLD,   "IE", "IRELAND" },
628     {CTRY_ISRAEL,      NULL1_WORLD,   "IL", "ISRAEL" },
629     {CTRY_ITALY,       ETSI1_WORLD,   "IT", "ITALY" },
630     {CTRY_JAPAN,       MKK1_MKKA,     "JP", "JAPAN" },
631     {CTRY_JAPAN1,      MKK1_MKKB,     "JP", "JAPAN1" },
632     {CTRY_JAPAN2,      MKK1_FCCA,     "JP", "JAPAN2" },
633     {CTRY_JAPAN3,      MKK2_MKKA,     "JP", "JAPAN3" },
634     {CTRY_JAPAN4,      MKK1_MKKA1,    "JP", "JAPAN4" },
635     {CTRY_JAPAN5,      MKK1_MKKA2,    "JP", "JAPAN5" },
636     {CTRY_JAPAN6,      MKK1_MKKC,     "JP", "JAPAN6" },
637 
638     {CTRY_JAPAN7,      MKK3_MKKB,     "JP", "JAPAN7" },
639     {CTRY_JAPAN8,      MKK3_MKKA2,    "JP", "JAPAN8" },
640     {CTRY_JAPAN9,      MKK3_MKKC,     "JP", "JAPAN9" },
641 
642     {CTRY_JAPAN10,      MKK4_MKKB,     "JP", "JAPAN10" },
643     {CTRY_JAPAN11,      MKK4_MKKA2,    "JP", "JAPAN11" },
644     {CTRY_JAPAN12,      MKK4_MKKC,     "JP", "JAPAN12" },
645 
646     {CTRY_JAPAN13,      MKK5_MKKB,     "JP", "JAPAN13" },
647     {CTRY_JAPAN14,      MKK5_MKKA2,    "JP", "JAPAN14" },
648     {CTRY_JAPAN15,      MKK5_MKKC,     "JP", "JAPAN15" },
649 
650     {CTRY_JAPAN16,      MKK6_MKKB,     "JP", "JAPAN16" },
651     {CTRY_JAPAN17,      MKK6_MKKA2,    "JP", "JAPAN17" },
652     {CTRY_JAPAN18,      MKK6_MKKC,     "JP", "JAPAN18" },
653 
654     {CTRY_JAPAN19,      MKK7_MKKB,     "JP", "JAPAN19" },
655     {CTRY_JAPAN20,      MKK7_MKKA2,    "JP", "JAPAN20" },
656     {CTRY_JAPAN21,      MKK7_MKKC,     "JP", "JAPAN21" },
657 
658     {CTRY_JAPAN22,      MKK8_MKKB,     "JP", "JAPAN22" },
659     {CTRY_JAPAN23,      MKK8_MKKA2,    "JP", "JAPAN23" },
660     {CTRY_JAPAN24,      MKK8_MKKC,     "JP", "JAPAN24" },
661 
662     {CTRY_JORDAN,      APL4_WORLD,    "JO", "JORDAN" },
663     {CTRY_KAZAKHSTAN,  NULL1_WORLD,   "KZ", "KAZAKHSTAN" },
664     {CTRY_KOREA_NORTH, APL2_WORLD,    "KP", "NORTH KOREA" },
665     {CTRY_KOREA_ROC,   APL2_WORLD,    "KR", "KOREA REPUBLIC" },
666     {CTRY_KOREA_ROC2,  APL2_WORLD,    "K2", "KOREA REPUBLIC2" },
667     {CTRY_KOREA_ROC3,  APL9_WORLD,    "K3", "KOREA REPUBLIC3" },
668     {CTRY_KUWAIT,      NULL1_WORLD,   "KW", "KUWAIT" },
669     {CTRY_LATVIA,      ETSI1_WORLD,   "LV", "LATVIA" },
670     {CTRY_LEBANON,     NULL1_WORLD,   "LB", "LEBANON" },
671     {CTRY_LIECHTENSTEIN,ETSI1_WORLD,  "LI", "LIECHTENSTEIN" },
672     {CTRY_LITHUANIA,   ETSI1_WORLD,   "LT", "LITHUANIA" },
673     {CTRY_LUXEMBOURG,  ETSI1_WORLD,   "LU", "LUXEMBOURG" },
674     {CTRY_MACAU,       FCC2_WORLD,    "MO", "MACAU" },
675     {CTRY_MACEDONIA,   NULL1_WORLD,   "MK", "MACEDONIA" },
676     {CTRY_MALAYSIA,    APL8_WORLD,    "MY", "MALAYSIA" },
677     {CTRY_MALTA,       ETSI1_WORLD,   "MT", "MALTA" },
678     {CTRY_MEXICO,      FCC1_FCCA,     "MX", "MEXICO" },
679     {CTRY_MONACO,      ETSI4_WORLD,   "MC", "MONACO" },
680     {CTRY_MOROCCO,     NULL1_WORLD,   "MA", "MOROCCO" },
681     {CTRY_NETHERLANDS, ETSI1_WORLD,   "NL", "NETHERLANDS" },
682     {CTRY_NEW_ZEALAND, FCC2_ETSIC,    "NZ", "NEW ZEALAND" },
683     {CTRY_NORWAY,      ETSI1_WORLD,   "NO", "NORWAY" },
684     {CTRY_OMAN,        APL6_WORLD,    "OM", "OMAN" },
685     {CTRY_PAKISTAN,    NULL1_WORLD,   "PK", "PAKISTAN" },
686     {CTRY_PANAMA,      FCC1_FCCA,     "PA", "PANAMA" },
687     {CTRY_PERU,        APL1_WORLD,    "PE", "PERU" },
688     {CTRY_PHILIPPINES, APL1_WORLD,    "PH", "PHILIPPINES" },
689     {CTRY_POLAND,      ETSI1_WORLD,   "PL", "POLAND" },
690     {CTRY_PORTUGAL,    ETSI1_WORLD,   "PT", "PORTUGAL" },
691     {CTRY_PUERTO_RICO, FCC1_FCCA,     "PR", "PUERTO RICO" },
692     {CTRY_QATAR,       NULL1_WORLD,   "QA", "QATAR" },
693     {CTRY_ROMANIA,     NULL1_WORLD,   "RO", "ROMANIA" },
694     {CTRY_RUSSIA,      NULL1_WORLD,   "RU", "RUSSIA" },
695     {CTRY_SAUDI_ARABIA,NULL1_WORLD,   "SA", "SAUDI ARABIA" },
696     {CTRY_SINGAPORE,   APL6_WORLD,    "SG", "SINGAPORE" },
697     {CTRY_SLOVAKIA,    ETSI1_WORLD,   "SK", "SLOVAK REPUBLIC" },
698     {CTRY_SLOVENIA,    ETSI1_WORLD,   "SI", "SLOVENIA" },
699     {CTRY_SOUTH_AFRICA,FCC3_WORLD,    "ZA", "SOUTH AFRICA" },
700     {CTRY_SPAIN,       ETSI1_WORLD,   "ES", "SPAIN" },
701     {CTRY_SWEDEN,      ETSI1_WORLD,   "SE", "SWEDEN" },
702     {CTRY_SWITZERLAND, ETSI1_WORLD,   "CH", "SWITZERLAND" },
703     {CTRY_SYRIA,       NULL1_WORLD,   "SY", "SYRIA" },
704     {CTRY_TAIWAN,      APL3_FCCA,    "TW", "TAIWAN" },
705     {CTRY_THAILAND,    NULL1_WORLD,   "TH", "THAILAND" },
706     {CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD,"TT", "TRINIDAD & TOBAGO" },
707     {CTRY_TUNISIA,     ETSI3_WORLD,   "TN", "TUNISIA" },
708     {CTRY_TURKEY,      ETSI3_WORLD,   "TR", "TURKEY" },
709     {CTRY_UKRAINE,     NULL1_WORLD,   "UA", "UKRAINE" },
710     {CTRY_UAE,         NULL1_WORLD,   "AE", "UNITED ARAB EMIRATES" },
711     {CTRY_UNITED_KINGDOM, ETSI1_WORLD,"GB", "UNITED KINGDOM" },
712     {CTRY_UNITED_STATES, FCC1_FCCA,   "US", "UNITED STATES" },
713     {CTRY_UNITED_STATES_FCC49, FCC4_FCCA,   "PS", "UNITED STATES (PUBLIC SAFETY)" },
714     {CTRY_URUGUAY,     APL2_WORLD,    "UY", "URUGUAY" },
715     {CTRY_UZBEKISTAN,  FCC3_FCCA,     "UZ", "UZBEKISTAN" },
716     {CTRY_VENEZUELA,   APL2_ETSIC,    "VE", "VENEZUELA" },
717     {CTRY_VIET_NAM,    NULL1_WORLD,   "VN", "VIET NAM" },
718     {CTRY_YEMEN,       NULL1_WORLD,   "YE", "YEMEN" },
719     {CTRY_ZIMBABWE,    NULL1_WORLD,   "ZW", "ZIMBABWE" }
720 };
721 
722 static HAL_BOOL
cclookup(const char * name,HAL_REG_DOMAIN * rd,HAL_CTRY_CODE * cc)723 cclookup(const char *name, HAL_REG_DOMAIN *rd, HAL_CTRY_CODE *cc)
724 {
725 	int i;
726 
727 	for (i = 0; i < nitems(allCountries); i++)
728 		if (strcasecmp(allCountries[i].isoName, name) == 0 ||
729 		    strcasecmp(allCountries[i].name, name) == 0) {
730 			*rd = allCountries[i].regDmnEnum;
731 			*cc = allCountries[i].countryCode;
732 			return AH_TRUE;
733 		}
734 	return AH_FALSE;
735 }
736 
737 static const char *
getccname(HAL_CTRY_CODE cc)738 getccname(HAL_CTRY_CODE cc)
739 {
740 	int i;
741 
742 	for (i = 0; i < nitems(allCountries); i++)
743 		if (allCountries[i].countryCode == cc)
744 			return allCountries[i].name;
745 	return NULL;
746 }
747 
748 static const char *
getccisoname(HAL_CTRY_CODE cc)749 getccisoname(HAL_CTRY_CODE cc)
750 {
751 	int i;
752 
753 	for (i = 0; i < nitems(allCountries); i++)
754 		if (allCountries[i].countryCode == cc)
755 			return allCountries[i].isoName;
756 	return NULL;
757 }
758 
759 static void
cclist()760 cclist()
761 {
762 	int i;
763 
764 	printf("\nCountry codes:\n");
765 	for (i = 0; i < nitems(allCountries); i++)
766 		printf("%2s %-15.15s%s",
767 			allCountries[i].isoName,
768 			allCountries[i].name,
769 			((i+1)%4) == 0 ? "\n" : " ");
770 	printf("\n");
771 }
772 
773 static HAL_BOOL
774 setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan,
775 		   int16_t tpcScaleReduction, int16_t powerLimit,
776                    int16_t *pMinPower, int16_t *pMaxPower);
777 
778 static void
calctxpower(struct ath_hal * ah,int nchan,const struct ieee80211_channel * chans,int16_t tpcScaleReduction,int16_t powerLimit,int16_t * txpow)779 calctxpower(struct ath_hal *ah,
780 	int nchan, const struct ieee80211_channel *chans,
781 	int16_t tpcScaleReduction, int16_t powerLimit, int16_t *txpow)
782 {
783 	int16_t minpow;
784 	int i;
785 
786 	for (i = 0; i < nchan; i++)
787 		if (!setRateTable(ah, &chans[i],
788 		    tpcScaleReduction, powerLimit, &minpow, &txpow[i])) {
789 			printf("unable to set rate table\n");
790 			exit(-1);
791 		}
792 }
793 
794 int	n = 1;
795 const char *sep = "";
796 int	dopassive = 0;
797 int	showchannels = 0;
798 int	isdfs = 0;
799 int	is4ms = 0;
800 
801 static int
anychan(const struct ieee80211_channel * chans,int nc,int flag)802 anychan(const struct ieee80211_channel *chans, int nc, int flag)
803 {
804 	int i;
805 
806 	for (i = 0; i < nc; i++)
807 		if ((chans[i].ic_flags & flag) != 0)
808 			return 1;
809 	return 0;
810 }
811 
812 static __inline int
mapgsm(u_int freq,u_int flags)813 mapgsm(u_int freq, u_int flags)
814 {
815 	freq *= 10;
816 	if (flags & IEEE80211_CHAN_QUARTER)
817 		freq += 5;
818 	else if (flags & IEEE80211_CHAN_HALF)
819 		freq += 10;
820 	else
821 		freq += 20;
822 	return (freq - 24220) / 5;
823 }
824 
825 static __inline int
mappsb(u_int freq,u_int flags)826 mappsb(u_int freq, u_int flags)
827 {
828 	return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
829 }
830 
831 /*
832  * Convert GHz frequency to IEEE channel number.
833  */
834 int
ath_hal_mhz2ieee(struct ath_hal * ah,u_int freq,u_int flags)835 ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags)
836 {
837 	if (flags & IEEE80211_CHAN_2GHZ) {	/* 2GHz band */
838 		if (freq == 2484)
839 			return 14;
840 		if (freq < 2484)
841 			return ((int)freq - 2407) / 5;
842 		else
843 			return 15 + ((freq - 2512) / 20);
844 	} else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */
845 		if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq))
846 			return mappsb(freq, flags);
847 		else if ((flags & IEEE80211_CHAN_A) && (freq <= 5000))
848 			return (freq - 4000) / 5;
849 		else
850 			return (freq - 5000) / 5;
851 	} else {			/* either, guess */
852 		if (freq == 2484)
853 			return 14;
854 		if (freq < 2484)
855 			return ((int)freq - 2407) / 5;
856 		if (freq < 5000) {
857 			if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq))
858 				return mappsb(freq, flags);
859 			else if (freq > 4900)
860 				return (freq - 4000) / 5;
861 			else
862 				return 15 + ((freq - 2512) / 20);
863 		}
864 		return (freq - 5000) / 5;
865 	}
866 }
867 
868 #define	IEEE80211_IS_CHAN_4MS(_c) \
869 	(((_c)->ic_flags & IEEE80211_CHAN_4MSXMIT) != 0)
870 
871 static void
dumpchannels(struct ath_hal * ah,int nc,const struct ieee80211_channel * chans,int16_t * txpow)872 dumpchannels(struct ath_hal *ah, int nc,
873 	const struct ieee80211_channel *chans, int16_t *txpow)
874 {
875 	int i;
876 
877 	for (i = 0; i < nc; i++) {
878 		const struct ieee80211_channel *c = &chans[i];
879 		int type;
880 
881 		if (showchannels)
882 			printf("%s%3d", sep,
883 			    ath_hal_mhz2ieee(ah, c->ic_freq, c->ic_flags));
884 		else
885 			printf("%s%u", sep, c->ic_freq);
886 		if (IEEE80211_IS_CHAN_HALF(c))
887 			type = 'H';
888 		else if (IEEE80211_IS_CHAN_QUARTER(c))
889 			type = 'Q';
890 		else if (IEEE80211_IS_CHAN_TURBO(c))
891 			type = 'T';
892 		else if (IEEE80211_IS_CHAN_HT(c))
893 			type = 'N';
894 		else if (IEEE80211_IS_CHAN_A(c))
895 			type = 'A';
896 		else if (IEEE80211_IS_CHAN_108G(c))
897 			type = 'T';
898 		else if (IEEE80211_IS_CHAN_G(c))
899 			type = 'G';
900 		else
901 			type = 'B';
902 		if (dopassive && IEEE80211_IS_CHAN_PASSIVE(c))
903 			type = tolower(type);
904 		if (isdfs && is4ms)
905 			printf("%c%c%c %d.%d", type,
906 			    IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ',
907 			    IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ',
908 			    txpow[i]/2, (txpow[i]%2)*5);
909 		else if (isdfs)
910 			printf("%c%c %d.%d", type,
911 			    IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ',
912 			    txpow[i]/2, (txpow[i]%2)*5);
913 		else if (is4ms)
914 			printf("%c%c %d.%d", type,
915 			    IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ',
916 			    txpow[i]/2, (txpow[i]%2)*5);
917 		else
918 			printf("%c %d.%d", type, txpow[i]/2, (txpow[i]%2)*5);
919 		if ((n++ % (showchannels ? 7 : 6)) == 0)
920 			sep = "\n";
921 		else
922 			sep = " ";
923 	}
924 }
925 
926 static void
intersect(struct ieee80211_channel * dst,int16_t * dtxpow,int * nd,const struct ieee80211_channel * src,int16_t * stxpow,int ns)927 intersect(struct ieee80211_channel *dst, int16_t *dtxpow, int *nd,
928     const struct ieee80211_channel *src, int16_t *stxpow, int ns)
929 {
930 	int i = 0, j, k, l;
931 	while (i < *nd) {
932 		for (j = 0; j < ns && dst[i].ic_freq != src[j].ic_freq; j++)
933 			;
934 		if (j < ns && dtxpow[i] == stxpow[j]) {
935 			for (k = i+1, l = i; k < *nd; k++, l++)
936 				dst[l] = dst[k];
937 			(*nd)--;
938 		} else
939 			i++;
940 	}
941 }
942 
943 static void
usage(const char * progname)944 usage(const char *progname)
945 {
946 	printf("usage: %s [-acdefoilpr4ABGT] [-m opmode] [cc | rd]\n", progname);
947 	exit(-1);
948 }
949 
950 static HAL_BOOL
getChipPowerLimits(struct ath_hal * ah,struct ieee80211_channel * chan)951 getChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan)
952 {
953 }
954 
955 static HAL_BOOL
eepromRead(struct ath_hal * ah,u_int off,u_int16_t * data)956 eepromRead(struct ath_hal *ah, u_int off, u_int16_t *data)
957 {
958 	/* emulate enough stuff to handle japan channel shift */
959 	switch (off) {
960 	case AR_EEPROM_VERSION:
961 		*data = eeversion;
962 		return AH_TRUE;
963 	case AR_EEPROM_REG_CAPABILITIES_OFFSET:
964 		*data = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A;
965 		return AH_TRUE;
966 	case AR_EEPROM_REG_CAPABILITIES_OFFSET_PRE4_0:
967 		*data = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0;
968 		return AH_TRUE;
969 	}
970 	return AH_FALSE;
971 }
972 
973 HAL_STATUS
getCapability(struct ath_hal * ah,HAL_CAPABILITY_TYPE type,uint32_t capability,uint32_t * result)974 getCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
975 	uint32_t capability, uint32_t *result)
976 {
977 	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
978 
979 	switch (type) {
980 	case HAL_CAP_REG_DMN:		/* regulatory domain */
981 		*result = AH_PRIVATE(ah)->ah_currentRD;
982 		return HAL_OK;
983 	default:
984 		return HAL_EINVAL;
985 	}
986 }
987 
988 #define HAL_MODE_HT20 \
989 	(HAL_MODE_11NG_HT20 |  HAL_MODE_11NA_HT20)
990 #define	HAL_MODE_HT40 \
991 	(HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \
992 	 HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS)
993 #define	HAL_MODE_HT	(HAL_MODE_HT20 | HAL_MODE_HT40)
994 
995 int
main(int argc,char * argv[])996 main(int argc, char *argv[])
997 {
998 	static const u_int16_t tpcScaleReductionTable[5] =
999 		{ 0, 3, 6, 9, MAX_RATE_POWER };
1000 	struct ath_hal_private ahp;
1001 	struct ieee80211_channel achans[IEEE80211_CHAN_MAX];
1002 	int16_t atxpow[IEEE80211_CHAN_MAX];
1003 	struct ieee80211_channel bchans[IEEE80211_CHAN_MAX];
1004 	int16_t btxpow[IEEE80211_CHAN_MAX];
1005 	struct ieee80211_channel gchans[IEEE80211_CHAN_MAX];
1006 	int16_t gtxpow[IEEE80211_CHAN_MAX];
1007 	struct ieee80211_channel tchans[IEEE80211_CHAN_MAX];
1008 	int16_t ttxpow[IEEE80211_CHAN_MAX];
1009 	struct ieee80211_channel tgchans[IEEE80211_CHAN_MAX];
1010 	int16_t tgtxpow[IEEE80211_CHAN_MAX];
1011 	struct ieee80211_channel nchans[IEEE80211_CHAN_MAX];
1012 	int16_t ntxpow[IEEE80211_CHAN_MAX];
1013 	int i, na, nb, ng, nt, ntg, nn;
1014 	HAL_BOOL showall = AH_FALSE;
1015 	HAL_BOOL extendedChanMode = AH_TRUE;
1016 	int modes = 0;
1017 	int16_t tpcReduction, powerLimit;
1018 	int showdfs = 0;
1019 	int show4ms = 0;
1020 
1021 	memset(&ahp, 0, sizeof(ahp));
1022 	ahp.ah_getChannelEdges = getChannelEdges;
1023 	ahp.ah_getWirelessModes = getWirelessModes;
1024 	ahp.ah_eepromRead = eepromRead;
1025 	ahp.ah_getChipPowerLimits = getChipPowerLimits;
1026 	ahp.ah_caps.halWirelessModes = HAL_MODE_ALL;
1027 	ahp.ah_caps.halLow5GhzChan = 4920;
1028 	ahp.ah_caps.halHigh5GhzChan = 6100;
1029 	ahp.ah_caps.halLow2GhzChan = 2312;
1030 	ahp.ah_caps.halHigh2GhzChan = 2732;
1031 	ahp.ah_caps.halChanHalfRate = AH_TRUE;
1032 	ahp.ah_caps.halChanQuarterRate = AH_TRUE;
1033 	ahp.h.ah_getCapability = getCapability;
1034 	ahp.ah_opmode = HAL_M_STA;
1035 
1036 	tpcReduction = tpcScaleReductionTable[0];
1037 	powerLimit =  MAX_RATE_POWER;
1038 
1039 	while ((i = getopt(argc, argv, "acdeflm:pr4ABGhHNT")) != -1)
1040 		switch (i) {
1041 		case 'a':
1042 			showall = AH_TRUE;
1043 			break;
1044 		case 'c':
1045 			showchannels = AH_TRUE;
1046 			break;
1047 		case 'd':
1048 			ath_hal_debug = HAL_DEBUG_ANY;
1049 			break;
1050 		case 'e':
1051 			extendedChanMode = AH_FALSE;
1052 			break;
1053 		case 'f':
1054 			showchannels = AH_FALSE;
1055 			break;
1056 		case 'l':
1057 			cclist();
1058 			rdlist();
1059 			exit(0);
1060 		case 'm':
1061 			if (strncasecmp(optarg, "sta", 2) == 0)
1062 				ahp.ah_opmode = HAL_M_STA;
1063 			else if (strncasecmp(optarg, "ibss", 2) == 0)
1064 				ahp.ah_opmode = HAL_M_IBSS;
1065 			else if (strncasecmp(optarg, "adhoc", 2) == 0)
1066 				ahp.ah_opmode = HAL_M_IBSS;
1067 			else if (strncasecmp(optarg, "ap", 2) == 0)
1068 				ahp.ah_opmode = HAL_M_HOSTAP;
1069 			else if (strncasecmp(optarg, "hostap", 2) == 0)
1070 				ahp.ah_opmode = HAL_M_HOSTAP;
1071 			else if (strncasecmp(optarg, "monitor", 2) == 0)
1072 				ahp.ah_opmode = HAL_M_MONITOR;
1073 			else
1074 				usage(argv[0]);
1075 			break;
1076 		case 'p':
1077 			dopassive = 1;
1078 			break;
1079 		case 'A':
1080 			modes |= HAL_MODE_11A;
1081 			break;
1082 		case 'B':
1083 			modes |= HAL_MODE_11B;
1084 			break;
1085 		case 'G':
1086 			modes |= HAL_MODE_11G;
1087 			break;
1088 		case 'h':
1089 			modes |= HAL_MODE_HT20;
1090 			break;
1091 		case 'H':
1092 			modes |= HAL_MODE_HT40;
1093 			break;
1094 		case 'N':
1095 			modes |= HAL_MODE_HT;
1096 			break;
1097 		case 'T':
1098 			modes |= HAL_MODE_TURBO | HAL_MODE_108G;
1099 			break;
1100 		case 'r':
1101 			showdfs = 1;
1102 			break;
1103 		case '4':
1104 			show4ms = 1;
1105 			break;
1106 		default:
1107 			usage(argv[0]);
1108 		}
1109 	switch (argc - optind)  {
1110 	case 0:
1111 		if (!cclookup("US", &rd, &cc)) {
1112 			printf("%s: unknown country code\n", "US");
1113 			exit(-1);
1114 		}
1115 		break;
1116 	case 1:			/* cc/regdomain */
1117 		if (!cclookup(argv[optind], &rd, &cc)) {
1118 			if (!rdlookup(argv[optind], &rd)) {
1119 				const char* rdname;
1120 
1121 				rd = strtoul(argv[optind], NULL, 0);
1122 				rdname = getrdname(rd);
1123 				if (rdname == NULL) {
1124 					printf("%s: unknown country/regulatory "
1125 						"domain code\n", argv[optind]);
1126 					exit(-1);
1127 				}
1128 			}
1129 			cc = CTRY_DEFAULT;
1130 		}
1131 		break;
1132 	default:		/* regdomain cc */
1133 		if (!rdlookup(argv[optind], &rd)) {
1134 			const char* rdname;
1135 
1136 			rd = strtoul(argv[optind], NULL, 0);
1137 			rdname = getrdname(rd);
1138 			if (rdname == NULL) {
1139 				printf("%s: unknown country/regulatory "
1140 					"domain code\n", argv[optind]);
1141 				exit(-1);
1142 			}
1143 		}
1144 		if (!cclookup(argv[optind+1], &rd, &cc))
1145 			cc = strtoul(argv[optind+1], NULL, 0);
1146 		break;
1147 	}
1148 	if (cc != CTRY_DEFAULT)
1149 		printf("\n%s (%s, 0x%x, %u) %s (0x%x, %u)\n",
1150 			getccname(cc), getccisoname(cc), cc, cc,
1151 			getrdname(rd), rd, rd);
1152 	else
1153 		printf("\n%s (0x%x, %u)\n",
1154 			getrdname(rd), rd, rd);
1155 
1156 	if (modes == 0) {
1157 		/* NB: no HAL_MODE_HT */
1158 		modes = HAL_MODE_11A | HAL_MODE_11B |
1159 			HAL_MODE_11G | HAL_MODE_TURBO | HAL_MODE_108G;
1160 	}
1161 	na = nb = ng = nt = ntg = nn = 0;
1162 	if (modes & HAL_MODE_11G) {
1163 		ahp.ah_currentRD = rd;
1164 		if (ath_hal_getchannels(&ahp.h, gchans, IEEE80211_CHAN_MAX, &ng,
1165 		    HAL_MODE_11G, cc, rd, extendedChanMode) == HAL_OK) {
1166 			calctxpower(&ahp.h, ng, gchans, tpcReduction, powerLimit, gtxpow);
1167 			if (showdfs)
1168 				isdfs |= anychan(gchans, ng, IEEE80211_CHAN_DFS);
1169 			if (show4ms)
1170 				is4ms |= anychan(gchans, ng, IEEE80211_CHAN_4MSXMIT);
1171 		}
1172 	}
1173 	if (modes & HAL_MODE_11B) {
1174 		ahp.ah_currentRD = rd;
1175 		if (ath_hal_getchannels(&ahp.h, bchans, IEEE80211_CHAN_MAX, &nb,
1176 		    HAL_MODE_11B, cc, rd, extendedChanMode) == HAL_OK) {
1177 			calctxpower(&ahp.h, nb, bchans, tpcReduction, powerLimit, btxpow);
1178 			if (showdfs)
1179 				isdfs |= anychan(bchans, nb, IEEE80211_CHAN_DFS);
1180 			if (show4ms)
1181 				is4ms |= anychan(bchans, nb, IEEE80211_CHAN_4MSXMIT);
1182 		}
1183 	}
1184 	if (modes & HAL_MODE_11A) {
1185 		ahp.ah_currentRD = rd;
1186 		if (ath_hal_getchannels(&ahp.h, achans, IEEE80211_CHAN_MAX, &na,
1187 		    HAL_MODE_11A, cc, rd, extendedChanMode) == HAL_OK) {
1188 			calctxpower(&ahp.h, na, achans, tpcReduction, powerLimit, atxpow);
1189 			if (showdfs)
1190 				isdfs |= anychan(achans, na, IEEE80211_CHAN_DFS);
1191 			if (show4ms)
1192 				is4ms |= anychan(achans, na, IEEE80211_CHAN_4MSXMIT);
1193 		}
1194 	}
1195 	if (modes & HAL_MODE_TURBO) {
1196 		ahp.ah_currentRD = rd;
1197 		if (ath_hal_getchannels(&ahp.h, tchans, IEEE80211_CHAN_MAX, &nt,
1198 		    HAL_MODE_TURBO, cc, rd, extendedChanMode) == HAL_OK) {
1199 			calctxpower(&ahp.h, nt, tchans, tpcReduction, powerLimit, ttxpow);
1200 			if (showdfs)
1201 				isdfs |= anychan(tchans, nt, IEEE80211_CHAN_DFS);
1202 			if (show4ms)
1203 				is4ms |= anychan(tchans, nt, IEEE80211_CHAN_4MSXMIT);
1204 		}
1205 	}
1206 	if (modes & HAL_MODE_108G) {
1207 		ahp.ah_currentRD = rd;
1208 		if (ath_hal_getchannels(&ahp.h, tgchans, IEEE80211_CHAN_MAX, &ntg,
1209 		    HAL_MODE_108G, cc, rd, extendedChanMode) == HAL_OK) {
1210 			calctxpower(&ahp.h, ntg, tgchans, tpcReduction, powerLimit, tgtxpow);
1211 			if (showdfs)
1212 				isdfs |= anychan(tgchans, ntg, IEEE80211_CHAN_DFS);
1213 			if (show4ms)
1214 				is4ms |= anychan(tgchans, ntg, IEEE80211_CHAN_4MSXMIT);
1215 		}
1216 	}
1217 	if (modes & HAL_MODE_HT) {
1218 		ahp.ah_currentRD = rd;
1219 		if (ath_hal_getchannels(&ahp.h, nchans, IEEE80211_CHAN_MAX, &nn,
1220 		    modes & HAL_MODE_HT, cc, rd, extendedChanMode) == HAL_OK) {
1221 			calctxpower(&ahp.h, nn, nchans, tpcReduction, powerLimit, ntxpow);
1222 			if (showdfs)
1223 				isdfs |= anychan(nchans, nn, IEEE80211_CHAN_DFS);
1224 			if (show4ms)
1225 				is4ms |= anychan(nchans, nn, IEEE80211_CHAN_4MSXMIT);
1226 		}
1227 	}
1228 
1229 	if (!showall) {
1230 #define	CHECKMODES(_modes, _m)	((_modes & (_m)) == (_m))
1231 		if (CHECKMODES(modes, HAL_MODE_11B|HAL_MODE_11G)) {
1232 			/* b ^= g */
1233 			intersect(bchans, btxpow, &nb, gchans, gtxpow, ng);
1234 		}
1235 		if (CHECKMODES(modes, HAL_MODE_11A|HAL_MODE_TURBO)) {
1236 			/* t ^= a */
1237 			intersect(tchans, ttxpow, &nt, achans, atxpow, na);
1238 		}
1239 		if (CHECKMODES(modes, HAL_MODE_11G|HAL_MODE_108G)) {
1240 			/* tg ^= g */
1241 			intersect(tgchans, tgtxpow, &ntg, gchans, gtxpow, ng);
1242 		}
1243 		if (CHECKMODES(modes, HAL_MODE_11G|HAL_MODE_HT)) {
1244 			/* g ^= n */
1245 			intersect(gchans, gtxpow, &ng, nchans, ntxpow, nn);
1246 		}
1247 		if (CHECKMODES(modes, HAL_MODE_11A|HAL_MODE_HT)) {
1248 			/* a ^= n */
1249 			intersect(achans, atxpow, &na, nchans, ntxpow, nn);
1250 		}
1251 #undef CHECKMODES
1252 	}
1253 
1254 	if (modes & HAL_MODE_11G)
1255 		dumpchannels(&ahp.h, ng, gchans, gtxpow);
1256 	if (modes & HAL_MODE_11B)
1257 		dumpchannels(&ahp.h, nb, bchans, btxpow);
1258 	if (modes & HAL_MODE_11A)
1259 		dumpchannels(&ahp.h, na, achans, atxpow);
1260 	if (modes & HAL_MODE_108G)
1261 		dumpchannels(&ahp.h, ntg, tgchans, tgtxpow);
1262 	if (modes & HAL_MODE_TURBO)
1263 		dumpchannels(&ahp.h, nt, tchans, ttxpow);
1264 	if (modes & HAL_MODE_HT)
1265 		dumpchannels(&ahp.h, nn, nchans, ntxpow);
1266 	printf("\n");
1267 	return (0);
1268 }
1269 
1270 /*
1271  * Search a list for a specified value v that is within
1272  * EEP_DELTA of the search values.  Return the closest
1273  * values in the list above and below the desired value.
1274  * EEP_DELTA is a factional value; everything is scaled
1275  * so only integer arithmetic is used.
1276  *
1277  * NB: the input list is assumed to be sorted in ascending order
1278  */
1279 static void
ar5212GetLowerUpperValues(u_int16_t v,u_int16_t * lp,u_int16_t listSize,u_int16_t * vlo,u_int16_t * vhi)1280 ar5212GetLowerUpperValues(u_int16_t v, u_int16_t *lp, u_int16_t listSize,
1281                           u_int16_t *vlo, u_int16_t *vhi)
1282 {
1283 	u_int32_t target = v * EEP_SCALE;
1284 	u_int16_t *ep = lp+listSize;
1285 
1286 	/*
1287 	 * Check first and last elements for out-of-bounds conditions.
1288 	 */
1289 	if (target < (u_int32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) {
1290 		*vlo = *vhi = lp[0];
1291 		return;
1292 	}
1293 	if (target > (u_int32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) {
1294 		*vlo = *vhi = ep[-1];
1295 		return;
1296 	}
1297 
1298 	/* look for value being near or between 2 values in list */
1299 	for (; lp < ep; lp++) {
1300 		/*
1301 		 * If value is close to the current value of the list
1302 		 * then target is not between values, it is one of the values
1303 		 */
1304 		if (abs(lp[0] * EEP_SCALE - target) < EEP_DELTA) {
1305 			*vlo = *vhi = lp[0];
1306 			return;
1307 		}
1308 		/*
1309 		 * Look for value being between current value and next value
1310 		 * if so return these 2 values
1311 		 */
1312 		if (target < (u_int32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) {
1313 			*vlo = lp[0];
1314 			*vhi = lp[1];
1315 			return;
1316 		}
1317 	}
1318 }
1319 
1320 /*
1321  * Find the maximum conformance test limit for the given channel and CTL info
1322  */
1323 static u_int16_t
ar5212GetMaxEdgePower(u_int16_t channel,RD_EDGES_POWER * pRdEdgesPower)1324 ar5212GetMaxEdgePower(u_int16_t channel, RD_EDGES_POWER *pRdEdgesPower)
1325 {
1326 	/* temp array for holding edge channels */
1327 	u_int16_t tempChannelList[NUM_EDGES];
1328 	u_int16_t clo, chi, twiceMaxEdgePower;
1329 	int i, numEdges;
1330 
1331 	/* Get the edge power */
1332 	for (i = 0; i < NUM_EDGES; i++) {
1333 		if (pRdEdgesPower[i].rdEdge == 0)
1334 			break;
1335 		tempChannelList[i] = pRdEdgesPower[i].rdEdge;
1336 	}
1337 	numEdges = i;
1338 
1339 	ar5212GetLowerUpperValues(channel, tempChannelList,
1340 		numEdges, &clo, &chi);
1341 	/* Get the index for the lower channel */
1342 	for (i = 0; i < numEdges && clo != tempChannelList[i]; i++)
1343 		;
1344 	/* Is lower channel ever outside the rdEdge? */
1345 	HALASSERT(i != numEdges);
1346 
1347 	if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) {
1348 		/*
1349 		 * If there's an exact channel match or an inband flag set
1350 		 * on the lower channel use the given rdEdgePower
1351 		 */
1352 		twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower;
1353 		HALASSERT(twiceMaxEdgePower > 0);
1354 	} else
1355 		twiceMaxEdgePower = MAX_RATE_POWER;
1356 	return twiceMaxEdgePower;
1357 }
1358 
1359 /*
1360  * Returns interpolated or the scaled up interpolated value
1361  */
1362 static u_int16_t
interpolate(u_int16_t target,u_int16_t srcLeft,u_int16_t srcRight,u_int16_t targetLeft,u_int16_t targetRight)1363 interpolate(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight,
1364 	u_int16_t targetLeft, u_int16_t targetRight)
1365 {
1366 	u_int16_t rv;
1367 	int16_t lRatio;
1368 
1369 	/* to get an accurate ratio, always scale, if want to scale, then don't scale back down */
1370 	if ((targetLeft * targetRight) == 0)
1371 		return 0;
1372 
1373 	if (srcRight != srcLeft) {
1374 		/*
1375 		 * Note the ratio always need to be scaled,
1376 		 * since it will be a fraction.
1377 		 */
1378 		lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft);
1379 		if (lRatio < 0) {
1380 		    /* Return as Left target if value would be negative */
1381 		    rv = targetLeft;
1382 		} else if (lRatio > EEP_SCALE) {
1383 		    /* Return as Right target if Ratio is greater than 100% (SCALE) */
1384 		    rv = targetRight;
1385 		} else {
1386 			rv = (lRatio * targetRight + (EEP_SCALE - lRatio) *
1387 					targetLeft) / EEP_SCALE;
1388 		}
1389 	} else {
1390 		rv = targetLeft;
1391 	}
1392 	return rv;
1393 }
1394 
1395 /*
1396  * Return the four rates of target power for the given target power table
1397  * channel, and number of channels
1398  */
1399 static void
ar5212GetTargetPowers(struct ath_hal * ah,const struct ieee80211_channel * chan,TRGT_POWER_INFO * powInfo,u_int16_t numChannels,TRGT_POWER_INFO * pNewPower)1400 ar5212GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan,
1401 	TRGT_POWER_INFO *powInfo,
1402 	u_int16_t numChannels, TRGT_POWER_INFO *pNewPower)
1403 {
1404 	/* temp array for holding target power channels */
1405 	u_int16_t tempChannelList[NUM_TEST_FREQUENCIES];
1406 	u_int16_t clo, chi, ixlo, ixhi;
1407 	int i;
1408 
1409 	/* Copy the target powers into the temp channel list */
1410 	for (i = 0; i < numChannels; i++)
1411 		tempChannelList[i] = powInfo[i].testChannel;
1412 
1413 	ar5212GetLowerUpperValues(chan->ic_freq, tempChannelList,
1414 		numChannels, &clo, &chi);
1415 
1416 	/* Get the indices for the channel */
1417 	ixlo = ixhi = 0;
1418 	for (i = 0; i < numChannels; i++) {
1419 		if (clo == tempChannelList[i]) {
1420 			ixlo = i;
1421 		}
1422 		if (chi == tempChannelList[i]) {
1423 			ixhi = i;
1424 			break;
1425 		}
1426 	}
1427 
1428 	/*
1429 	 * Get the lower and upper channels, target powers,
1430 	 * and interpolate between them.
1431 	 */
1432 	pNewPower->twicePwr6_24 = interpolate(chan->ic_freq, clo, chi,
1433 		powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24);
1434 	pNewPower->twicePwr36 = interpolate(chan->ic_freq, clo, chi,
1435 		powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36);
1436 	pNewPower->twicePwr48 = interpolate(chan->ic_freq, clo, chi,
1437 		powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48);
1438 	pNewPower->twicePwr54 = interpolate(chan->ic_freq, clo, chi,
1439 		powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54);
1440 }
1441 
1442 static RD_EDGES_POWER*
findEdgePower(struct ath_hal * ah,u_int ctl)1443 findEdgePower(struct ath_hal *ah, u_int ctl)
1444 {
1445 	int i;
1446 
1447 	for (i = 0; i < _numCtls; i++)
1448 		if (_ctl[i] == ctl)
1449 			return &_rdEdgesPower[i * NUM_EDGES];
1450 	return AH_NULL;
1451 }
1452 
1453 /*
1454  * Sets the transmit power in the baseband for the given
1455  * operating channel and mode.
1456  */
1457 static HAL_BOOL
setRateTable(struct ath_hal * ah,const struct ieee80211_channel * chan,int16_t tpcScaleReduction,int16_t powerLimit,int16_t * pMinPower,int16_t * pMaxPower)1458 setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan,
1459 		   int16_t tpcScaleReduction, int16_t powerLimit,
1460                    int16_t *pMinPower, int16_t *pMaxPower)
1461 {
1462 	u_int16_t ratesArray[16];
1463 	u_int16_t *rpow = ratesArray;
1464 	u_int16_t twiceMaxRDPower, twiceMaxEdgePower, twiceMaxEdgePowerCck;
1465 	int8_t twiceAntennaGain, twiceAntennaReduction;
1466 	TRGT_POWER_INFO targetPowerOfdm, targetPowerCck;
1467 	RD_EDGES_POWER *rep;
1468 	int16_t scaledPower;
1469 	u_int8_t cfgCtl;
1470 
1471 	twiceMaxRDPower = chan->ic_maxregpower * 2;
1472 	*pMaxPower = -MAX_RATE_POWER;
1473 	*pMinPower = MAX_RATE_POWER;
1474 
1475 	/* Get conformance test limit maximum for this channel */
1476 	cfgCtl = ath_hal_getctl(ah, chan);
1477 	rep = findEdgePower(ah, cfgCtl);
1478 	if (rep != AH_NULL)
1479 		twiceMaxEdgePower = ar5212GetMaxEdgePower(chan->ic_freq, rep);
1480 	else
1481 		twiceMaxEdgePower = MAX_RATE_POWER;
1482 
1483 	if (IEEE80211_IS_CHAN_G(chan)) {
1484 		/* Check for a CCK CTL for 11G CCK powers */
1485 		cfgCtl = (cfgCtl & 0xFC) | 0x01;
1486 		rep = findEdgePower(ah, cfgCtl);
1487 		if (rep != AH_NULL)
1488 			twiceMaxEdgePowerCck = ar5212GetMaxEdgePower(chan->ic_freq, rep);
1489 		else
1490 			twiceMaxEdgePowerCck = MAX_RATE_POWER;
1491 	} else {
1492 		/* Set the 11B cck edge power to the one found before */
1493 		twiceMaxEdgePowerCck = twiceMaxEdgePower;
1494 	}
1495 
1496 	/* Get Antenna Gain reduction */
1497 	if (IEEE80211_IS_CHAN_5GHZ(chan)) {
1498 		twiceAntennaGain = antennaGainMax[0];
1499 	} else {
1500 		twiceAntennaGain = antennaGainMax[1];
1501 	}
1502 	twiceAntennaReduction =
1503 		ath_hal_getantennareduction(ah, chan, twiceAntennaGain);
1504 
1505 	if (IEEE80211_IS_CHAN_OFDM(chan)) {
1506 		/* Get final OFDM target powers */
1507 		if (IEEE80211_IS_CHAN_G(chan)) {
1508 			/* TODO - add Turbo 2.4 to this mode check */
1509 			ar5212GetTargetPowers(ah, chan, trgtPwr_11g,
1510 				numTargetPwr_11g, &targetPowerOfdm);
1511 		} else {
1512 			ar5212GetTargetPowers(ah, chan, trgtPwr_11a,
1513 				numTargetPwr_11a, &targetPowerOfdm);
1514 		}
1515 
1516 		/* Get Maximum OFDM power */
1517 		/* Minimum of target and edge powers */
1518 		scaledPower = AH_MIN(twiceMaxEdgePower,
1519 				twiceMaxRDPower - twiceAntennaReduction);
1520 
1521 		/*
1522 		 * If turbo is set, reduce power to keep power
1523 		 * consumption under 2 Watts.  Note that we always do
1524 		 * this unless specially configured.  Then we limit
1525 		 * power only for non-AP operation.
1526 		 */
1527 		if (IEEE80211_IS_CHAN_TURBO(chan)
1528 #ifdef AH_ENABLE_AP_SUPPORT
1529 		    && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP
1530 #endif
1531 		) {
1532 			/*
1533 			 * If turbo is set, reduce power to keep power
1534 			 * consumption under 2 Watts
1535 			 */
1536 			if (eeversion >= AR_EEPROM_VER3_1)
1537 				scaledPower = AH_MIN(scaledPower,
1538 					turbo2WMaxPower5);
1539 			/*
1540 			 * EEPROM version 4.0 added an additional
1541 			 * constraint on 2.4GHz channels.
1542 			 */
1543 			if (eeversion >= AR_EEPROM_VER4_0 &&
1544 			    IEEE80211_IS_CHAN_2GHZ(chan))
1545 				scaledPower = AH_MIN(scaledPower,
1546 					turbo2WMaxPower2);
1547 		}
1548 		/* Reduce power by max regulatory domain allowed restrictions */
1549 		scaledPower -= (tpcScaleReduction * 2);
1550 		scaledPower = (scaledPower < 0) ? 0 : scaledPower;
1551 		scaledPower = AH_MIN(scaledPower, powerLimit);
1552 
1553 		scaledPower = AH_MIN(scaledPower, targetPowerOfdm.twicePwr6_24);
1554 
1555 		/* Set OFDM rates 9, 12, 18, 24, 36, 48, 54, XR */
1556 		rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower;
1557 		rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36);
1558 		rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48);
1559 		rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54);
1560 
1561 #ifdef notyet
1562 		if (eeversion >= AR_EEPROM_VER4_0) {
1563 			/* Setup XR target power from EEPROM */
1564 			rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ?
1565 				xrTargetPower2 : xrTargetPower5);
1566 		} else {
1567 			/* XR uses 6mb power */
1568 			rpow[15] = rpow[0];
1569 		}
1570 #else
1571 		rpow[15] = rpow[0];
1572 #endif
1573 
1574 		*pMinPower = rpow[7];
1575 		*pMaxPower = rpow[0];
1576 
1577 #if 0
1578 		ahp->ah_ofdmTxPower = rpow[0];
1579 #endif
1580 
1581 		HALDEBUG(ah, HAL_DEBUG_ANY,
1582 		    "%s: MaxRD: %d TurboMax: %d MaxCTL: %d "
1583 		    "TPC_Reduction %d\n", __func__,
1584 		    twiceMaxRDPower, turbo2WMaxPower5,
1585 		    twiceMaxEdgePower, tpcScaleReduction * 2);
1586 	}
1587 
1588 	if (IEEE80211_IS_CHAN_CCK(chan)) {
1589 		/* Get final CCK target powers */
1590 		ar5212GetTargetPowers(ah, chan, trgtPwr_11b,
1591 			numTargetPwr_11b, &targetPowerCck);
1592 
1593 		/* Reduce power by max regulatory domain allowed restrictions */
1594 		scaledPower = AH_MIN(twiceMaxEdgePowerCck,
1595 			twiceMaxRDPower - twiceAntennaReduction);
1596 
1597 		scaledPower -= (tpcScaleReduction * 2);
1598 		scaledPower = (scaledPower < 0) ? 0 : scaledPower;
1599 		scaledPower = AH_MIN(scaledPower, powerLimit);
1600 
1601 		rpow[8] = (scaledPower < 1) ? 1 : scaledPower;
1602 
1603 		/* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */
1604 		rpow[8]  = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24);
1605 		rpow[9]  = AH_MIN(scaledPower, targetPowerCck.twicePwr36);
1606 		rpow[10] = rpow[9];
1607 		rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48);
1608 		rpow[12] = rpow[11];
1609 		rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54);
1610 		rpow[14] = rpow[13];
1611 
1612 		/* Set min/max power based off OFDM values or initialization */
1613 		if (rpow[13] < *pMinPower)
1614 		    *pMinPower = rpow[13];
1615 		if (rpow[9] > *pMaxPower)
1616 		    *pMaxPower = rpow[9];
1617 
1618 	}
1619 #if 0
1620 	ahp->ah_tx6PowerInHalfDbm = *pMaxPower;
1621 #endif
1622 	return AH_TRUE;
1623 }
1624 
1625 void*
ath_hal_malloc(size_t size)1626 ath_hal_malloc(size_t size)
1627 {
1628 	return calloc(1, size);
1629 }
1630 
1631 void
ath_hal_free(void * p)1632 ath_hal_free(void* p)
1633 {
1634 	return free(p);
1635 }
1636 
1637 void
ath_hal_vprintf(struct ath_hal * ah,const char * fmt,va_list ap)1638 ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap)
1639 {
1640 	vprintf(fmt, ap);
1641 }
1642 
1643 void
ath_hal_printf(struct ath_hal * ah,const char * fmt,...)1644 ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
1645 {
1646 	va_list ap;
1647 	va_start(ap, fmt);
1648 	ath_hal_vprintf(ah, fmt, ap);
1649 	va_end(ap);
1650 }
1651 
1652 void
DO_HALDEBUG(struct ath_hal * ah,u_int mask,const char * fmt,...)1653 DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...)
1654 {
1655 	__va_list ap;
1656 	va_start(ap, fmt);
1657 	ath_hal_vprintf(ah, fmt, ap);
1658 	va_end(ap);
1659 }
1660