1/*-
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
5 * Copyright (c) 2005-2006 Atheros Communications, Inc.
6 * All rights reserved.
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *
20 * $FreeBSD: releng/12.0/sys/dev/ath/ath_hal/ah_regdomain.c 326695 2017-12-08 15:57:29Z pfg $
21 */
22#include "opt_ah.h"
23
24#include "ah.h"
25
26#include <net80211/_ieee80211.h>
27#include <net80211/ieee80211_regdomain.h>
28
29#include "ah_internal.h"
30#include "ah_eeprom.h"
31#include "ah_devid.h"
32
33#include "ah_regdomain.h"
34
35/*
36 * XXX this code needs a audit+review
37 */
38
39/* used throughout this file... */
40#define	N(a)		nitems(a)
41
42#define HAL_MODE_11A_TURBO	HAL_MODE_108A
43#define HAL_MODE_11G_TURBO	HAL_MODE_108G
44
45/*
46 * Mask to check whether a domain is a multidomain or a single domain
47 */
48#define MULTI_DOMAIN_MASK 0xFF00
49
50/*
51 * Enumerated Regulatory Domain Information 8 bit values indicate that
52 * the regdomain is really a pair of unitary regdomains.  12 bit values
53 * are the real unitary regdomains and are the only ones which have the
54 * frequency bitmasks and flags set.
55 */
56#include "ah_regdomain/ah_rd_regenum.h"
57
58#define	WORLD_SKU_MASK		0x00F0
59#define	WORLD_SKU_PREFIX	0x0060
60
61/*
62 * THE following table is the mapping of regdomain pairs specified by
63 * an 8 bit regdomain value to the individual unitary reg domains
64 */
65#include "ah_regdomain/ah_rd_regmap.h"
66
67/*
68 * The following tables are the master list for all different freqeuncy
69 * bands with the complete matrix of all possible flags and settings
70 * for each band if it is used in ANY reg domain.
71 */
72
73#define	COUNTRY_ERD_FLAG        0x8000
74#define WORLDWIDE_ROAMING_FLAG  0x4000
75
76/*
77 * This table maps country ISO codes from net80211 into regulatory
78 * domains which the ath regulatory domain code understands.
79 */
80#include "ah_regdomain/ah_rd_ctry.h"
81
82/*
83 * The frequency band collections are a set of frequency ranges
84 * with shared properties - max tx power, max antenna gain, channel width,
85 * channel spacing, DFS requirements and passive scanning requirements.
86 *
87 * These are represented as entries in a frequency band bitmask.
88 * Each regulatory domain entry in ah_regdomain_domains.h uses one
89 * or more frequency band entries for each of the channel modes
90 * supported (11bg, 11a, half, quarter, turbo, etc.)
91 *
92 */
93#include "ah_regdomain/ah_rd_freqbands.h"
94
95/*
96 * This is the main regulatory database. It defines the supported
97 * set of features and requirements for each of the defined regulatory
98 * zones. It uses combinations of frequency ranges - represented in
99 * a bitmask - to determine the requirements and limitations needed.
100 */
101#include "ah_regdomain/ah_rd_domains.h"
102
103static const struct cmode modes[] = {
104	{ HAL_MODE_TURBO,	IEEE80211_CHAN_ST,	&regDmn5GhzTurboFreq[0] },
105	{ HAL_MODE_11A,		IEEE80211_CHAN_A,	&regDmn5GhzFreq[0] },
106	{ HAL_MODE_11B,		IEEE80211_CHAN_B,	&regDmn2GhzFreq[0] },
107	{ HAL_MODE_11G,		IEEE80211_CHAN_G,	&regDmn2Ghz11gFreq[0] },
108	{ HAL_MODE_11G_TURBO,	IEEE80211_CHAN_108G,	&regDmn2Ghz11gTurboFreq[0] },
109	{ HAL_MODE_11A_TURBO,	IEEE80211_CHAN_108A,	&regDmn5GhzTurboFreq[0] },
110	{ HAL_MODE_11A_QUARTER_RATE,
111	  IEEE80211_CHAN_A | IEEE80211_CHAN_QUARTER,	&regDmn5GhzFreq[0] },
112	{ HAL_MODE_11A_HALF_RATE,
113	  IEEE80211_CHAN_A | IEEE80211_CHAN_HALF,	&regDmn5GhzFreq[0] },
114	{ HAL_MODE_11G_QUARTER_RATE,
115	  IEEE80211_CHAN_G | IEEE80211_CHAN_QUARTER,	&regDmn2Ghz11gFreq[0] },
116	{ HAL_MODE_11G_HALF_RATE,
117	  IEEE80211_CHAN_G | IEEE80211_CHAN_HALF,	&regDmn2Ghz11gFreq[0] },
118	{ HAL_MODE_11NG_HT20,
119	  IEEE80211_CHAN_G | IEEE80211_CHAN_HT20,	&regDmn2Ghz11gFreq[0] },
120	{ HAL_MODE_11NG_HT40PLUS,
121	  IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U,	&regDmn2Ghz11gFreq[0] },
122	{ HAL_MODE_11NG_HT40MINUS,
123	  IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D,	&regDmn2Ghz11gFreq[0] },
124	{ HAL_MODE_11NA_HT20,
125	  IEEE80211_CHAN_A | IEEE80211_CHAN_HT20,	&regDmn5GhzFreq[0] },
126	{ HAL_MODE_11NA_HT40PLUS,
127	  IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U,	&regDmn5GhzFreq[0] },
128	{ HAL_MODE_11NA_HT40MINUS,
129	  IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D,	&regDmn5GhzFreq[0] },
130};
131
132static void ath_hal_update_dfsdomain(struct ath_hal *ah);
133
134static OS_INLINE uint16_t
135getEepromRD(struct ath_hal *ah)
136{
137	return AH_PRIVATE(ah)->ah_currentRD &~ WORLDWIDE_ROAMING_FLAG;
138}
139
140/*
141 * Test to see if the bitmask array is all zeros
142 */
143static HAL_BOOL
144isChanBitMaskZero(const uint64_t *bitmask)
145{
146#if BMLEN > 2
147#error	"add more cases"
148#endif
149#if BMLEN > 1
150	if (bitmask[1] != 0)
151		return AH_FALSE;
152#endif
153	return (bitmask[0] == 0);
154}
155
156/*
157 * Return whether or not the regulatory domain/country in EEPROM
158 * is acceptable.
159 */
160static HAL_BOOL
161isEepromValid(struct ath_hal *ah)
162{
163	uint16_t rd = getEepromRD(ah);
164	int i;
165
166	if (rd & COUNTRY_ERD_FLAG) {
167		uint16_t cc = rd &~ COUNTRY_ERD_FLAG;
168		for (i = 0; i < N(allCountries); i++)
169			if (allCountries[i].countryCode == cc)
170				return AH_TRUE;
171	} else {
172		for (i = 0; i < N(regDomainPairs); i++)
173			if (regDomainPairs[i].regDmnEnum == rd)
174				return AH_TRUE;
175	}
176
177	if (rd == FCC_UBNT) {
178		return AH_TRUE;
179	}
180
181	HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
182	    "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd);
183	return AH_FALSE;
184}
185
186/*
187 * Find the pointer to the country element in the country table
188 * corresponding to the country code
189 */
190static COUNTRY_CODE_TO_ENUM_RD*
191findCountry(HAL_CTRY_CODE countryCode)
192{
193	int i;
194
195	for (i = 0; i < N(allCountries); i++) {
196		if (allCountries[i].countryCode == countryCode)
197			return &allCountries[i];
198	}
199	return AH_NULL;
200}
201
202static REG_DOMAIN *
203findRegDmn(int regDmn)
204{
205	int i;
206
207	for (i = 0; i < N(regDomains); i++) {
208		if (regDomains[i].regDmnEnum == regDmn)
209			return &regDomains[i];
210	}
211	return AH_NULL;
212}
213
214static REG_DMN_PAIR_MAPPING *
215findRegDmnPair(int regDmnPair)
216{
217	int i;
218
219	if (regDmnPair != NO_ENUMRD) {
220		for (i = 0; i < N(regDomainPairs); i++) {
221			if (regDomainPairs[i].regDmnEnum == regDmnPair)
222				return &regDomainPairs[i];
223		}
224	}
225	return AH_NULL;
226}
227
228/*
229 * Calculate a default country based on the EEPROM setting.
230 */
231static HAL_CTRY_CODE
232getDefaultCountry(struct ath_hal *ah)
233{
234	REG_DMN_PAIR_MAPPING *regpair;
235	uint16_t rd;
236
237	rd = getEepromRD(ah);
238	if (rd & COUNTRY_ERD_FLAG) {
239		COUNTRY_CODE_TO_ENUM_RD *country;
240		uint16_t cc = rd & ~COUNTRY_ERD_FLAG;
241		country = findCountry(cc);
242		if (country != AH_NULL)
243			return cc;
244	}
245	/*
246	 * Check reg domains that have only one country
247	 */
248	regpair = findRegDmnPair(rd);
249	return (regpair != AH_NULL) ? regpair->singleCC : CTRY_DEFAULT;
250}
251
252static HAL_BOOL
253IS_BIT_SET(int bit, const uint64_t bitmask[])
254{
255	int byteOffset, bitnum;
256	uint64_t val;
257
258	byteOffset = bit/64;
259	bitnum = bit - byteOffset*64;
260	val = ((uint64_t) 1) << bitnum;
261	return (bitmask[byteOffset] & val) != 0;
262}
263
264static HAL_STATUS
265getregstate(struct ath_hal *ah, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn,
266    COUNTRY_CODE_TO_ENUM_RD **pcountry,
267    REG_DOMAIN **prd2GHz, REG_DOMAIN **prd5GHz)
268{
269	COUNTRY_CODE_TO_ENUM_RD *country;
270	REG_DOMAIN *rd5GHz, *rd2GHz;
271
272	if (cc == CTRY_DEFAULT && regDmn == SKU_NONE) {
273		/*
274		 * Validate the EEPROM setting and setup defaults
275		 */
276		if (!isEepromValid(ah)) {
277			/*
278			 * Don't return any channels if the EEPROM has an
279			 * invalid regulatory domain/country code setting.
280			 */
281			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
282			    "%s: invalid EEPROM contents\n",__func__);
283			return HAL_EEBADREG;
284		}
285
286		cc = getDefaultCountry(ah);
287		country = findCountry(cc);
288		if (country == AH_NULL) {
289			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
290			    "NULL Country!, cc %d\n", cc);
291			return HAL_EEBADCC;
292		}
293		regDmn = country->regDmnEnum;
294		HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: EEPROM cc %u rd 0x%x\n",
295		    __func__, cc, regDmn);
296
297		if (country->countryCode == CTRY_DEFAULT) {
298			/*
299			 * Check EEPROM; SKU may be for a country, single
300			 * domain, or multiple domains (WWR).
301			 */
302			uint16_t rdnum = getEepromRD(ah);
303			if ((rdnum & COUNTRY_ERD_FLAG) == 0 &&
304			    (findRegDmn(rdnum) != AH_NULL ||
305			     findRegDmnPair(rdnum) != AH_NULL)) {
306				regDmn = rdnum;
307				HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
308				    "%s: EEPROM rd 0x%x\n", __func__, rdnum);
309			}
310		}
311	} else {
312		country = findCountry(cc);
313		if (country == AH_NULL) {
314			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
315			    "unknown country, cc %d\n", cc);
316			return HAL_EINVAL;
317		}
318		if (regDmn == SKU_NONE)
319			regDmn = country->regDmnEnum;
320		HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u rd 0x%x\n",
321		    __func__, cc, regDmn);
322	}
323
324	/*
325	 * Setup per-band state.
326	 */
327	if ((regDmn & MULTI_DOMAIN_MASK) == 0) {
328		REG_DMN_PAIR_MAPPING *regpair = findRegDmnPair(regDmn);
329		if (regpair == AH_NULL) {
330			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
331			    "%s: no reg domain pair %u for country %u\n",
332			    __func__, regDmn, country->countryCode);
333			return HAL_EINVAL;
334		}
335		rd5GHz = findRegDmn(regpair->regDmn5GHz);
336		if (rd5GHz == AH_NULL) {
337			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
338			    "%s: no 5GHz reg domain %u for country %u\n",
339			    __func__, regpair->regDmn5GHz, country->countryCode);
340			return HAL_EINVAL;
341		}
342		rd2GHz = findRegDmn(regpair->regDmn2GHz);
343		if (rd2GHz == AH_NULL) {
344			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
345			    "%s: no 2GHz reg domain %u for country %u\n",
346			    __func__, regpair->regDmn2GHz, country->countryCode);
347			return HAL_EINVAL;
348		}
349	} else {
350		rd5GHz = rd2GHz = findRegDmn(regDmn);
351		if (rd2GHz == AH_NULL) {
352			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
353			    "%s: no unitary reg domain %u for country %u\n",
354			    __func__, regDmn, country->countryCode);
355			return HAL_EINVAL;
356		}
357	}
358	if (pcountry != AH_NULL)
359		*pcountry = country;
360	*prd2GHz = rd2GHz;
361	*prd5GHz = rd5GHz;
362	return HAL_OK;
363}
364
365static uint64_t *
366getchannelBM(u_int mode, REG_DOMAIN *rd)
367{
368	switch (mode) {
369	case HAL_MODE_11B:
370		return (rd->chan11b);
371	case HAL_MODE_11G_QUARTER_RATE:
372		return (rd->chan11g_quarter);
373	case HAL_MODE_11G_HALF_RATE:
374		return (rd->chan11g_half);
375	case HAL_MODE_11G:
376	case HAL_MODE_11NG_HT20:
377	case HAL_MODE_11NG_HT40PLUS:
378	case HAL_MODE_11NG_HT40MINUS:
379		return (rd->chan11g);
380	case HAL_MODE_11G_TURBO:
381		return (rd->chan11g_turbo);
382	case HAL_MODE_11A_QUARTER_RATE:
383		return (rd->chan11a_quarter);
384	case HAL_MODE_11A_HALF_RATE:
385		return (rd->chan11a_half);
386	case HAL_MODE_11A:
387	case HAL_MODE_11NA_HT20:
388	case HAL_MODE_11NA_HT40PLUS:
389	case HAL_MODE_11NA_HT40MINUS:
390		return (rd->chan11a);
391	case HAL_MODE_TURBO:
392		return (rd->chan11a_turbo);
393	case HAL_MODE_11A_TURBO:
394		return (rd->chan11a_dyn_turbo);
395	default:
396		return (AH_NULL);
397	}
398}
399
400static void
401setchannelflags(struct ieee80211_channel *c, REG_DMN_FREQ_BAND *fband,
402    REG_DOMAIN *rd)
403{
404	if (fband->usePassScan & rd->pscan)
405		c->ic_flags |= IEEE80211_CHAN_PASSIVE;
406	if (fband->useDfs & rd->dfsMask)
407		c->ic_flags |= IEEE80211_CHAN_DFS;
408	if (IEEE80211_IS_CHAN_5GHZ(c) && (rd->flags & DISALLOW_ADHOC_11A))
409		c->ic_flags |= IEEE80211_CHAN_NOADHOC;
410	if (IEEE80211_IS_CHAN_TURBO(c) &&
411	    (rd->flags & DISALLOW_ADHOC_11A_TURB))
412		c->ic_flags |= IEEE80211_CHAN_NOADHOC;
413	if (rd->flags & NO_HOSTAP)
414		c->ic_flags |= IEEE80211_CHAN_NOHOSTAP;
415	if (rd->flags & LIMIT_FRAME_4MS)
416		c->ic_flags |= IEEE80211_CHAN_4MSXMIT;
417	if (rd->flags & NEED_NFC)
418		c->ic_flags |= CHANNEL_NFCREQUIRED;
419}
420
421static int
422addchan(struct ath_hal *ah, struct ieee80211_channel chans[],
423    u_int maxchans, int *nchans, uint16_t freq, uint32_t flags,
424    REG_DMN_FREQ_BAND *fband, REG_DOMAIN *rd)
425{
426	struct ieee80211_channel *c;
427
428	if (*nchans >= maxchans)
429		return (HAL_ENOMEM);
430
431	HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
432	    "%s: %d: freq=%d, flags=0x%08x\n",
433	    __func__, *nchans, (int) freq, flags);
434
435	c = &chans[(*nchans)++];
436	c->ic_freq = freq;
437	c->ic_flags = flags;
438	setchannelflags(c, fband, rd);
439	c->ic_maxregpower = fband->powerDfs;
440	ath_hal_getpowerlimits(ah, c);
441	c->ic_maxantgain = fband->antennaMax;
442
443	return (0);
444}
445
446static int
447copychan_prev(struct ath_hal *ah, struct ieee80211_channel chans[],
448    u_int maxchans, int *nchans, uint16_t freq, uint32_t flags)
449{
450	struct ieee80211_channel *c;
451
452	if (*nchans == 0)
453		return (HAL_EINVAL);
454
455	if (*nchans >= maxchans)
456		return (HAL_ENOMEM);
457
458	HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
459	    "%s: %d: freq=%d, flags=0x%08x\n",
460	    __func__, *nchans, (int) freq, flags);
461
462	c = &chans[(*nchans)++];
463	c[0] = c[-1];
464	c->ic_freq = freq;
465	/* XXX is it needed here? */
466	ath_hal_getpowerlimits(ah, c);
467
468	return (0);
469}
470
471static int
472add_chanlist_band(struct ath_hal *ah, struct ieee80211_channel chans[],
473    int maxchans, int *nchans, uint16_t freq_lo, uint16_t freq_hi, int step,
474    uint32_t flags, REG_DMN_FREQ_BAND *fband, REG_DOMAIN *rd)
475{
476	uint16_t freq = freq_lo;
477	int error;
478
479	if (freq_hi < freq_lo)
480		return (0);
481
482	HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
483	    "%s: freq=%d..%d, flags=0x%08x, step=%d\n", __func__,
484	    (int) freq_lo, (int) freq_hi, flags, step);
485
486	error = addchan(ah, chans, maxchans, nchans, freq, flags, fband, rd);
487	for (freq += step; freq <= freq_hi && error == 0; freq += step)
488		error = copychan_prev(ah, chans, maxchans, nchans, freq, flags);
489
490	return (error);
491}
492
493static void
494adj_freq_ht40(u_int mode, int *low_adj, int *hi_adj, int *channelSep)
495{
496
497	*low_adj = *hi_adj = *channelSep = 0;
498	switch (mode) {
499	case HAL_MODE_11NA_HT40PLUS:
500		*channelSep = 40;
501		/* FALLTHROUGH */
502	case HAL_MODE_11NG_HT40PLUS:
503		*hi_adj = -20;
504		break;
505	case HAL_MODE_11NA_HT40MINUS:
506		*channelSep = 40;
507		/* FALLTHROUGH */
508	case HAL_MODE_11NG_HT40MINUS:
509		*low_adj = 20;
510		break;
511	}
512}
513
514static void
515add_chanlist_mode(struct ath_hal *ah, struct ieee80211_channel chans[],
516    u_int maxchans, int *nchans, const struct cmode *cm, REG_DOMAIN *rd,
517    HAL_BOOL enableExtendedChannels)
518{
519	uint64_t *channelBM;
520	uint16_t freq_lo, freq_hi;
521	int b, error, low_adj, hi_adj, channelSep;
522
523	if (!ath_hal_getChannelEdges(ah, cm->flags, &freq_lo, &freq_hi)) {
524		/* channel not supported by hardware, skip it */
525		HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
526		    "%s: channels 0x%x not supported by hardware\n",
527		    __func__, cm->flags);
528		return;
529	}
530
531	channelBM = getchannelBM(cm->mode, rd);
532	if (isChanBitMaskZero(channelBM))
533		return;
534
535	/*
536	 * Setup special handling for HT40 channels; e.g.
537	 * 5G HT40 channels require 40Mhz channel separation.
538	 */
539	adj_freq_ht40(cm->mode, &low_adj, &hi_adj, &channelSep);
540
541	for (b = 0; b < 64*BMLEN; b++) {
542		REG_DMN_FREQ_BAND *fband;
543		uint16_t bfreq_lo, bfreq_hi;
544		int step;
545
546		if (!IS_BIT_SET(b, channelBM))
547			continue;
548		fband = &cm->freqs[b];
549
550		if ((fband->usePassScan & IS_ECM_CHAN) &&
551		    !enableExtendedChannels) {
552			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
553			    "skip ecm channels\n");
554			continue;
555		}
556#if 0
557		if ((fband->useDfs & rd->dfsMask) &&
558		    (cm->flags & IEEE80211_CHAN_HT40)) {
559			/* NB: DFS and HT40 don't mix */
560			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
561			    "skip HT40 chan, DFS required\n");
562			continue;
563		}
564#endif
565		/*
566		 * XXX TODO: handle REG_EXT_FCC_CH_144.
567		 *
568		 * Figure out which instances/uses cause us to not
569		 * be allowed to use channel 144 (pri or sec overlap.)
570		 */
571
572		bfreq_lo = MAX(fband->lowChannel + low_adj, freq_lo);
573		bfreq_hi = MIN(fband->highChannel + hi_adj, freq_hi);
574
575		/*
576		 * Don't start the 5GHz channel list at 5120MHz.
577		 *
578		 * Unfortunately (sigh) the HT40 channel creation
579		 * logic will create HT40U channels at 5120, 5160, 5200.
580		 * This means that 36 (5180) isn't considered as a
581		 * HT40 channel, and everything goes messed up from there.
582		 */
583		if ((cm->flags & IEEE80211_CHAN_5GHZ) &&
584		    (cm->flags & IEEE80211_CHAN_HT40U)) {
585			if (bfreq_lo < 5180)
586				bfreq_lo = 5180;
587		}
588
589		/*
590		 * Same with HT40D - need to start at 5200 or the low
591		 * channels are all wrong again.
592		 */
593		if ((cm->flags & IEEE80211_CHAN_5GHZ) &&
594		    (cm->flags & IEEE80211_CHAN_HT40D)) {
595			if (bfreq_lo < 5200)
596				bfreq_lo = 5200;
597		}
598
599		if (fband->channelSep >= channelSep)
600			step = fband->channelSep;
601		else
602			step = roundup(channelSep, fband->channelSep);
603
604		HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
605		    "%s: freq_lo=%d, freq_hi=%d, low_adj=%d, hi_adj=%d, "
606		    "bandlo=%d, bandhi=%d, bfreqlo=%d, bfreqhi=%d, step=%d, "
607		    "flags=0x%08x\n",
608		    __func__,
609		    (int) freq_lo,
610		    (int) freq_hi,
611		    (int) low_adj,
612		    (int) hi_adj,
613		    (int) fband->lowChannel,
614		    (int) fband->highChannel,
615		    (int) bfreq_lo,
616		    (int) bfreq_hi,
617		    step,
618		    (int) cm->flags);
619
620		error = add_chanlist_band(ah, chans, maxchans, nchans,
621		    bfreq_lo, bfreq_hi, step, cm->flags, fband, rd);
622		if (error != 0)	{
623			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
624			    "%s: too many channels for channel table\n",
625			    __func__);
626			return;
627		}
628	}
629}
630
631static u_int
632getmodesmask(struct ath_hal *ah, REG_DOMAIN *rd5GHz, u_int modeSelect)
633{
634#define	HAL_MODE_11A_ALL \
635	(HAL_MODE_11A | HAL_MODE_11A_TURBO | HAL_MODE_TURBO | \
636	 HAL_MODE_11A_QUARTER_RATE | HAL_MODE_11A_HALF_RATE)
637	u_int modesMask;
638
639	/* get modes that HW is capable of */
640	modesMask = ath_hal_getWirelessModes(ah);
641	modesMask &= modeSelect;
642	/* optimize work below if no 11a channels */
643	if (isChanBitMaskZero(rd5GHz->chan11a) &&
644	    (modesMask & HAL_MODE_11A_ALL)) {
645		HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
646		    "%s: disallow all 11a\n", __func__);
647		modesMask &= ~HAL_MODE_11A_ALL;
648	}
649
650	return (modesMask);
651#undef HAL_MODE_11A_ALL
652}
653
654/*
655 * Construct the channel list for the specified regulatory config.
656 */
657static HAL_STATUS
658getchannels(struct ath_hal *ah,
659    struct ieee80211_channel chans[], u_int maxchans, int *nchans,
660    u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn,
661    HAL_BOOL enableExtendedChannels,
662    COUNTRY_CODE_TO_ENUM_RD **pcountry,
663    REG_DOMAIN **prd2GHz, REG_DOMAIN **prd5GHz)
664{
665	REG_DOMAIN *rd5GHz, *rd2GHz;
666	u_int modesMask;
667	const struct cmode *cm;
668	HAL_STATUS status;
669
670	HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u regDmn 0x%x mode 0x%x%s\n",
671	    __func__, cc, regDmn, modeSelect,
672	    enableExtendedChannels ? " ecm" : "");
673
674	status = getregstate(ah, cc, regDmn, pcountry, &rd2GHz, &rd5GHz);
675	if (status != HAL_OK)
676		return status;
677
678	modesMask = getmodesmask(ah, rd5GHz, modeSelect);
679	/* XXX error? */
680	if (modesMask == 0)
681		goto done;
682
683	for (cm = modes; cm < &modes[N(modes)]; cm++) {
684		REG_DOMAIN *rd;
685
686		if ((cm->mode & modesMask) == 0) {
687			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
688			    "%s: skip mode 0x%x flags 0x%x\n",
689			    __func__, cm->mode, cm->flags);
690			continue;
691		}
692
693		if (cm->flags & IEEE80211_CHAN_5GHZ)
694			rd = rd5GHz;
695		else if (cm->flags & IEEE80211_CHAN_2GHZ)
696			rd = rd2GHz;
697		else {
698			ath_hal_printf(ah, "%s: Unknown HAL flags 0x%x\n",
699			    __func__, cm->flags);
700			return HAL_EINVAL;
701		}
702
703		add_chanlist_mode(ah, chans, maxchans, nchans, cm,
704		    rd, enableExtendedChannels);
705		if (*nchans >= maxchans)
706			goto done;
707	}
708done:
709	/* NB: pcountry set above by getregstate */
710	if (prd2GHz != AH_NULL)
711		*prd2GHz = rd2GHz;
712	if (prd5GHz != AH_NULL)
713		*prd5GHz = rd5GHz;
714	return HAL_OK;
715}
716
717/*
718 * Retrieve a channel list without affecting runtime state.
719 */
720HAL_STATUS
721ath_hal_getchannels(struct ath_hal *ah,
722    struct ieee80211_channel chans[], u_int maxchans, int *nchans,
723    u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn,
724    HAL_BOOL enableExtendedChannels)
725{
726	return getchannels(ah, chans, maxchans, nchans, modeSelect,
727	    cc, regDmn, enableExtendedChannels, AH_NULL, AH_NULL, AH_NULL);
728}
729
730/*
731 * Handle frequency mapping from 900Mhz range to 2.4GHz range
732 * for GSM radios.  This is done when we need the h/w frequency
733 * and the channel is marked IEEE80211_CHAN_GSM.
734 */
735static int
736ath_hal_mapgsm(int sku, int freq)
737{
738	if (sku == SKU_XR9)
739		return 1520 + freq;
740	if (sku == SKU_GZ901)
741		return 1544 + freq;
742	if (sku == SKU_SR9)
743		return 3344 - freq;
744	if (sku == SKU_XC900M)
745		return 1517 + freq;
746	HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
747	    "%s: cannot map freq %u unknown gsm sku %u\n",
748	    __func__, freq, sku);
749	return freq;
750}
751
752/*
753 * Setup the internal/private channel state given a table of
754 * net80211 channels.  We collapse entries for the same frequency
755 * and record the frequency for doing noise floor processing
756 * where we don't have net80211 channel context.
757 */
758static HAL_BOOL
759assignPrivateChannels(struct ath_hal *ah,
760	struct ieee80211_channel chans[], int nchans, int sku)
761{
762	HAL_CHANNEL_INTERNAL *ic;
763	int i, j, next, freq;
764
765	next = 0;
766	for (i = 0; i < nchans; i++) {
767		struct ieee80211_channel *c = &chans[i];
768		for (j = i-1; j >= 0; j--)
769			if (chans[j].ic_freq == c->ic_freq) {
770				c->ic_devdata = chans[j].ic_devdata;
771				break;
772			}
773		if (j < 0) {
774			/* new entry, assign a private channel entry */
775			if (next >= N(AH_PRIVATE(ah)->ah_channels)) {
776				HALDEBUG(ah, HAL_DEBUG_ANY,
777				    "%s: too many channels, max %zu\n",
778				    __func__, N(AH_PRIVATE(ah)->ah_channels));
779				return AH_FALSE;
780			}
781			/*
782			 * Handle frequency mapping for 900MHz devices.
783			 * The hardware uses 2.4GHz frequencies that are
784			 * down-converted.  The 802.11 layer uses the
785			 * true frequencies.
786			 */
787			freq = IEEE80211_IS_CHAN_GSM(c) ?
788			    ath_hal_mapgsm(sku, c->ic_freq) : c->ic_freq;
789
790			HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
791			    "%s: private[%3u] %u/0x%x -> channel %u\n",
792			    __func__, next, c->ic_freq, c->ic_flags, freq);
793
794			ic = &AH_PRIVATE(ah)->ah_channels[next];
795			/*
796			 * NB: This clears privFlags which means ancillary
797			 *     code like ANI and IQ calibration will be
798			 *     restarted and re-setup any per-channel state.
799			 */
800			OS_MEMZERO(ic, sizeof(*ic));
801			ic->channel = freq;
802			c->ic_devdata = next;
803			next++;
804		}
805	}
806	AH_PRIVATE(ah)->ah_nchan = next;
807	HALDEBUG(ah, HAL_DEBUG_ANY, "%s: %u public, %u private channels\n",
808	    __func__, nchans, next);
809	return AH_TRUE;
810}
811
812/*
813 * Setup the channel list based on the information in the EEPROM.
814 */
815HAL_STATUS
816ath_hal_init_channels(struct ath_hal *ah,
817    struct ieee80211_channel chans[], u_int maxchans, int *nchans,
818    u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn,
819    HAL_BOOL enableExtendedChannels)
820{
821	COUNTRY_CODE_TO_ENUM_RD *country;
822	REG_DOMAIN *rd5GHz, *rd2GHz;
823	HAL_STATUS status;
824
825	status = getchannels(ah, chans, maxchans, nchans, modeSelect,
826	    cc, regDmn, enableExtendedChannels, &country, &rd2GHz, &rd5GHz);
827	if (status == HAL_OK &&
828	    assignPrivateChannels(ah, chans, *nchans, AH_PRIVATE(ah)->ah_currentRD)) {
829		AH_PRIVATE(ah)->ah_rd2GHz = rd2GHz;
830		AH_PRIVATE(ah)->ah_rd5GHz = rd5GHz;
831
832		ah->ah_countryCode = country->countryCode;
833		HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u\n",
834		    __func__, ah->ah_countryCode);
835
836		/* Update current DFS domain */
837		ath_hal_update_dfsdomain(ah);
838	} else
839		status = HAL_EINVAL;
840
841	return status;
842}
843
844/*
845 * Set the channel list.
846 */
847HAL_STATUS
848ath_hal_set_channels(struct ath_hal *ah,
849    struct ieee80211_channel chans[], int nchans,
850    HAL_CTRY_CODE cc, HAL_REG_DOMAIN rd)
851{
852	COUNTRY_CODE_TO_ENUM_RD *country;
853	REG_DOMAIN *rd5GHz, *rd2GHz;
854	HAL_STATUS status;
855
856	switch (rd) {
857	case SKU_SR9:
858	case SKU_XR9:
859	case SKU_GZ901:
860	case SKU_XC900M:
861		/*
862		 * Map 900MHz sku's.  The frequencies will be mapped
863		 * according to the sku to compensate for the down-converter.
864		 * We use the FCC for these sku's as the mapped channel
865		 * list is known compatible (will need to change if/when
866		 * vendors do different mapping in different locales).
867		 */
868		status = getregstate(ah, CTRY_DEFAULT, SKU_FCC,
869		    &country, &rd2GHz, &rd5GHz);
870		break;
871	default:
872		status = getregstate(ah, cc, rd,
873		    &country, &rd2GHz, &rd5GHz);
874		rd = AH_PRIVATE(ah)->ah_currentRD;
875		break;
876	}
877	if (status == HAL_OK && assignPrivateChannels(ah, chans, nchans, rd)) {
878		AH_PRIVATE(ah)->ah_rd2GHz = rd2GHz;
879		AH_PRIVATE(ah)->ah_rd5GHz = rd5GHz;
880
881		ah->ah_countryCode = country->countryCode;
882		HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u\n",
883		    __func__, ah->ah_countryCode);
884	} else
885		status = HAL_EINVAL;
886
887	if (status == HAL_OK) {
888		/* Update current DFS domain */
889		(void) ath_hal_update_dfsdomain(ah);
890	}
891	return status;
892}
893
894#ifdef AH_DEBUG
895/*
896 * Return the internal channel corresponding to a public channel.
897 * NB: normally this routine is inline'd (see ah_internal.h)
898 */
899HAL_CHANNEL_INTERNAL *
900ath_hal_checkchannel(struct ath_hal *ah, const struct ieee80211_channel *c)
901{
902	HAL_CHANNEL_INTERNAL *cc = &AH_PRIVATE(ah)->ah_channels[c->ic_devdata];
903
904	if (c->ic_devdata < AH_PRIVATE(ah)->ah_nchan &&
905	    (c->ic_freq == cc->channel || IEEE80211_IS_CHAN_GSM(c)))
906		return cc;
907	if (c->ic_devdata >= AH_PRIVATE(ah)->ah_nchan) {
908		HALDEBUG(ah, HAL_DEBUG_ANY,
909		    "%s: bad mapping, devdata %u nchans %u\n",
910		   __func__, c->ic_devdata, AH_PRIVATE(ah)->ah_nchan);
911		HALASSERT(c->ic_devdata < AH_PRIVATE(ah)->ah_nchan);
912	} else {
913		HALDEBUG(ah, HAL_DEBUG_ANY,
914		    "%s: no match for %u/0x%x devdata %u channel %u\n",
915		   __func__, c->ic_freq, c->ic_flags, c->ic_devdata,
916		   cc->channel);
917		HALASSERT(c->ic_freq == cc->channel || IEEE80211_IS_CHAN_GSM(c));
918	}
919	return AH_NULL;
920}
921#endif /* AH_DEBUG */
922
923#define isWwrSKU(_ah) \
924	((getEepromRD((_ah)) & WORLD_SKU_MASK) == WORLD_SKU_PREFIX || \
925	  getEepromRD(_ah) == WORLD)
926
927/*
928 * Return the test group for the specific channel based on
929 * the current regulatory setup.
930 */
931u_int
932ath_hal_getctl(struct ath_hal *ah, const struct ieee80211_channel *c)
933{
934	u_int ctl;
935
936	if (AH_PRIVATE(ah)->ah_rd2GHz == AH_PRIVATE(ah)->ah_rd5GHz ||
937	    (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)))
938		ctl = SD_NO_CTL;
939	else if (IEEE80211_IS_CHAN_2GHZ(c))
940		ctl = AH_PRIVATE(ah)->ah_rd2GHz->conformanceTestLimit;
941	else
942		ctl = AH_PRIVATE(ah)->ah_rd5GHz->conformanceTestLimit;
943	if (IEEE80211_IS_CHAN_B(c))
944		return ctl | CTL_11B;
945	if (IEEE80211_IS_CHAN_G(c))
946		return ctl | CTL_11G;
947	if (IEEE80211_IS_CHAN_108G(c))
948		return ctl | CTL_108G;
949	if (IEEE80211_IS_CHAN_TURBO(c))
950		return ctl | CTL_TURBO;
951	if (IEEE80211_IS_CHAN_A(c))
952		return ctl | CTL_11A;
953	return ctl;
954}
955
956/*
957 * Update the current dfsDomain setting based on the given
958 * country code.
959 *
960 * Since FreeBSD/net80211 allows the channel set to change
961 * after the card has been setup (via ath_hal_init_channels())
962 * this function method is needed to update ah_dfsDomain.
963 */
964void
965ath_hal_update_dfsdomain(struct ath_hal *ah)
966{
967	const REG_DOMAIN *rd5GHz = AH_PRIVATE(ah)->ah_rd5GHz;
968	HAL_DFS_DOMAIN dfsDomain = HAL_DFS_UNINIT_DOMAIN;
969
970	if (rd5GHz->dfsMask & DFS_FCC3)
971		dfsDomain = HAL_DFS_FCC_DOMAIN;
972	if (rd5GHz->dfsMask & DFS_ETSI)
973		dfsDomain = HAL_DFS_ETSI_DOMAIN;
974	if (rd5GHz->dfsMask & DFS_MKK4)
975		dfsDomain = HAL_DFS_MKK4_DOMAIN;
976	AH_PRIVATE(ah)->ah_dfsDomain = dfsDomain;
977	HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s ah_dfsDomain: %d\n",
978	    __func__, AH_PRIVATE(ah)->ah_dfsDomain);
979}
980
981/*
982 * Return the max allowed antenna gain and apply any regulatory
983 * domain specific changes.
984 *
985 * NOTE: a negative reduction is possible in RD's that only
986 * measure radiated power (e.g., ETSI) which would increase
987 * that actual conducted output power (though never beyond
988 * the calibrated target power).
989 */
990u_int
991ath_hal_getantennareduction(struct ath_hal *ah,
992    const struct ieee80211_channel *chan, u_int twiceGain)
993{
994	int8_t antennaMax = twiceGain - chan->ic_maxantgain*2;
995	return (antennaMax < 0) ? 0 : antennaMax;
996}
997