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