xref: /illumos-gate/usr/src/uts/common/io/arn/arn_regd.c (revision dd1de374)
1*dd1de374Slin wang - Sun Microsystems - Beijing China /*
2*dd1de374Slin wang - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3*dd1de374Slin wang - Sun Microsystems - Beijing China  * Use is subject to license terms.
4*dd1de374Slin wang - Sun Microsystems - Beijing China  */
5*dd1de374Slin wang - Sun Microsystems - Beijing China 
6*dd1de374Slin wang - Sun Microsystems - Beijing China /*
7*dd1de374Slin wang - Sun Microsystems - Beijing China  * Copyright (c) 2008 Atheros Communications Inc.
8*dd1de374Slin wang - Sun Microsystems - Beijing China  *
9*dd1de374Slin wang - Sun Microsystems - Beijing China  * Permission to use, copy, modify, and/or distribute this software for any
10*dd1de374Slin wang - Sun Microsystems - Beijing China  * purpose with or without fee is hereby granted, provided that the above
11*dd1de374Slin wang - Sun Microsystems - Beijing China  * copyright notice and this permission notice appear in all copies.
12*dd1de374Slin wang - Sun Microsystems - Beijing China  *
13*dd1de374Slin wang - Sun Microsystems - Beijing China  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14*dd1de374Slin wang - Sun Microsystems - Beijing China  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15*dd1de374Slin wang - Sun Microsystems - Beijing China  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16*dd1de374Slin wang - Sun Microsystems - Beijing China  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17*dd1de374Slin wang - Sun Microsystems - Beijing China  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18*dd1de374Slin wang - Sun Microsystems - Beijing China  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19*dd1de374Slin wang - Sun Microsystems - Beijing China  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20*dd1de374Slin wang - Sun Microsystems - Beijing China  */
21*dd1de374Slin wang - Sun Microsystems - Beijing China 
22*dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_core.h"
23*dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_hw.h"
24*dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_regd.h"
25*dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_regd_common.h"
26*dd1de374Slin wang - Sun Microsystems - Beijing China 
27*dd1de374Slin wang - Sun Microsystems - Beijing China static int
ath9k_regd_chansort(const void * a,const void * b)28*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_chansort(const void *a, const void *b)
29*dd1de374Slin wang - Sun Microsystems - Beijing China {
30*dd1de374Slin wang - Sun Microsystems - Beijing China 	const struct ath9k_channel *ca = a;
31*dd1de374Slin wang - Sun Microsystems - Beijing China 	const struct ath9k_channel *cb = b;
32*dd1de374Slin wang - Sun Microsystems - Beijing China 
33*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (ca->channel == cb->channel) ?
34*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (ca->channelFlags & CHAN_FLAGS) -
35*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (cb->channelFlags & CHAN_FLAGS) : ca->channel - cb->channel;
36*dd1de374Slin wang - Sun Microsystems - Beijing China }
37*dd1de374Slin wang - Sun Microsystems - Beijing China 
38*dd1de374Slin wang - Sun Microsystems - Beijing China static void
ath9k_regd_sort(void * a,uint32_t n,uint32_t size,ath_hal_cmp_t * cmp)39*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_sort(void *a, uint32_t n, uint32_t size, ath_hal_cmp_t *cmp)
40*dd1de374Slin wang - Sun Microsystems - Beijing China {
41*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint8_t *aa = a;
42*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint8_t *ai, *t;
43*dd1de374Slin wang - Sun Microsystems - Beijing China 
44*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (ai = aa + size; --n >= 1; ai += size)
45*dd1de374Slin wang - Sun Microsystems - Beijing China 		for (t = ai; t > aa; t -= size) {
46*dd1de374Slin wang - Sun Microsystems - Beijing China 			uint8_t *u = t - size;
47*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (cmp(u, t) <= 0)
48*dd1de374Slin wang - Sun Microsystems - Beijing China 				break;
49*dd1de374Slin wang - Sun Microsystems - Beijing China 			swap(u, t, size);
50*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
51*dd1de374Slin wang - Sun Microsystems - Beijing China }
52*dd1de374Slin wang - Sun Microsystems - Beijing China 
53*dd1de374Slin wang - Sun Microsystems - Beijing China static uint16_t
ath9k_regd_get_eepromRD(struct ath_hal * ah)54*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_get_eepromRD(struct ath_hal *ah)
55*dd1de374Slin wang - Sun Microsystems - Beijing China {
56*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (ah->ah_currentRD & ~WORLDWIDE_ROAMING_FLAG);
57*dd1de374Slin wang - Sun Microsystems - Beijing China }
58*dd1de374Slin wang - Sun Microsystems - Beijing China 
59*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_is_chan_bm_zero(uint64_t * bitmask)60*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_chan_bm_zero(uint64_t *bitmask)
61*dd1de374Slin wang - Sun Microsystems - Beijing China {
62*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
63*dd1de374Slin wang - Sun Microsystems - Beijing China 
64*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < BMLEN; i++) {
65*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (bitmask[i] != 0)
66*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (B_FALSE);
67*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
68*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (B_TRUE);
69*dd1de374Slin wang - Sun Microsystems - Beijing China }
70*dd1de374Slin wang - Sun Microsystems - Beijing China 
71*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_is_eeprom_valid(struct ath_hal * ah)72*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_eeprom_valid(struct ath_hal *ah)
73*dd1de374Slin wang - Sun Microsystems - Beijing China {
74*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint16_t rd = ath9k_regd_get_eepromRD(ah);
75*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
76*dd1de374Slin wang - Sun Microsystems - Beijing China 
77*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (rd & COUNTRY_ERD_FLAG) {
78*dd1de374Slin wang - Sun Microsystems - Beijing China 		uint16_t cc = rd & ~COUNTRY_ERD_FLAG;
79*dd1de374Slin wang - Sun Microsystems - Beijing China 		for (i = 0; i < ARRAY_SIZE(allCountries); i++)
80*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (allCountries[i].countryCode == cc)
81*dd1de374Slin wang - Sun Microsystems - Beijing China 				return (B_TRUE);
82*dd1de374Slin wang - Sun Microsystems - Beijing China 	} else {
83*dd1de374Slin wang - Sun Microsystems - Beijing China 		for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
84*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (regDomainPairs[i].regDmnEnum == rd)
85*dd1de374Slin wang - Sun Microsystems - Beijing China 				return (B_TRUE);
86*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
87*dd1de374Slin wang - Sun Microsystems - Beijing China 
88*dd1de374Slin wang - Sun Microsystems - Beijing China 	ARN_DBG((ARN_DBG_REGULATORY,
89*dd1de374Slin wang - Sun Microsystems - Beijing China 	    "%s: invalid regulatory domain/country code 0x%x\n",
90*dd1de374Slin wang - Sun Microsystems - Beijing China 	    __func__, rd));
91*dd1de374Slin wang - Sun Microsystems - Beijing China 
92*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (B_FALSE);
93*dd1de374Slin wang - Sun Microsystems - Beijing China }
94*dd1de374Slin wang - Sun Microsystems - Beijing China 
95*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_is_fcc_midband_supported(struct ath_hal * ah)96*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_fcc_midband_supported(struct ath_hal *ah)
97*dd1de374Slin wang - Sun Microsystems - Beijing China {
98*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint32_t regcap;
99*dd1de374Slin wang - Sun Microsystems - Beijing China 
100*dd1de374Slin wang - Sun Microsystems - Beijing China 	regcap = ah->ah_caps.reg_cap;
101*dd1de374Slin wang - Sun Microsystems - Beijing China 
102*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (regcap & AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND)
103*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_TRUE);
104*dd1de374Slin wang - Sun Microsystems - Beijing China 	else
105*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
106*dd1de374Slin wang - Sun Microsystems - Beijing China }
107*dd1de374Slin wang - Sun Microsystems - Beijing China 
108*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_is_ccode_valid(struct ath_hal * ah,uint16_t cc)109*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_ccode_valid(struct ath_hal *ah, uint16_t cc)
110*dd1de374Slin wang - Sun Microsystems - Beijing China {
111*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint16_t rd;
112*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
113*dd1de374Slin wang - Sun Microsystems - Beijing China 
114*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (cc == CTRY_DEFAULT)
115*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_TRUE);
116*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (cc == CTRY_DEBUG)
117*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_TRUE);
118*dd1de374Slin wang - Sun Microsystems - Beijing China 
119*dd1de374Slin wang - Sun Microsystems - Beijing China 	rd = ath9k_regd_get_eepromRD(ah);
120*dd1de374Slin wang - Sun Microsystems - Beijing China 
121*dd1de374Slin wang - Sun Microsystems - Beijing China 	ARN_DBG((ARN_DBG_REGULATORY, "%s: EEPROM regdomain 0x%x\n",
122*dd1de374Slin wang - Sun Microsystems - Beijing China 	    __func__, rd));
123*dd1de374Slin wang - Sun Microsystems - Beijing China 
124*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (rd & COUNTRY_ERD_FLAG) {
125*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
126*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "%s: EEPROM setting is country code %u\n",
127*dd1de374Slin wang - Sun Microsystems - Beijing China 		    __func__, rd & ~COUNTRY_ERD_FLAG));
128*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (cc == (rd & ~COUNTRY_ERD_FLAG));
129*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
130*dd1de374Slin wang - Sun Microsystems - Beijing China 
131*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
132*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (cc == allCountries[i].countryCode) {
133*dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_SUPPORT_11D
134*dd1de374Slin wang - Sun Microsystems - Beijing China 			if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)
135*dd1de374Slin wang - Sun Microsystems - Beijing China 				return (B_TRUE);
136*dd1de374Slin wang - Sun Microsystems - Beijing China #endif
137*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (allCountries[i].regDmnEnum == rd ||
138*dd1de374Slin wang - Sun Microsystems - Beijing China 			    rd == DEBUG_REG_DMN || rd == NO_ENUMRD)
139*dd1de374Slin wang - Sun Microsystems - Beijing China 				return (B_TRUE);
140*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
141*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
142*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (B_FALSE);
143*dd1de374Slin wang - Sun Microsystems - Beijing China }
144*dd1de374Slin wang - Sun Microsystems - Beijing China 
145*dd1de374Slin wang - Sun Microsystems - Beijing China static void
ath9k_regd_get_wmodes_nreg(struct ath_hal * ah,struct country_code_to_enum_rd * country,struct regDomain * rd5GHz,uint8_t * modes_allowed)146*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_get_wmodes_nreg(struct ath_hal *ah,
147*dd1de374Slin wang - Sun Microsystems - Beijing China     struct country_code_to_enum_rd *country,
148*dd1de374Slin wang - Sun Microsystems - Beijing China     struct regDomain *rd5GHz,
149*dd1de374Slin wang - Sun Microsystems - Beijing China     uint8_t *modes_allowed)
150*dd1de374Slin wang - Sun Microsystems - Beijing China 
151*dd1de374Slin wang - Sun Microsystems - Beijing China {
152*dd1de374Slin wang - Sun Microsystems - Beijing China 	bcopy(ah->ah_caps.wireless_modes, modes_allowed,
153*dd1de374Slin wang - Sun Microsystems - Beijing China 	    sizeof (ah->ah_caps.wireless_modes));
154*dd1de374Slin wang - Sun Microsystems - Beijing China 
155*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (is_set(ATH9K_MODE_11G, ah->ah_caps.wireless_modes) &&
156*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (!country->allow11g))
157*dd1de374Slin wang - Sun Microsystems - Beijing China 		clr_bit(ATH9K_MODE_11G, modes_allowed);
158*dd1de374Slin wang - Sun Microsystems - Beijing China 
159*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (is_set(ATH9K_MODE_11A, ah->ah_caps.wireless_modes) &&
160*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (ath9k_regd_is_chan_bm_zero(rd5GHz->chan11a)))
161*dd1de374Slin wang - Sun Microsystems - Beijing China 		clr_bit(ATH9K_MODE_11A, modes_allowed);
162*dd1de374Slin wang - Sun Microsystems - Beijing China 
163*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (is_set(ATH9K_MODE_11NG_HT20, ah->ah_caps.wireless_modes) &&
164*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (!country->allow11ng20))
165*dd1de374Slin wang - Sun Microsystems - Beijing China 		clr_bit(ATH9K_MODE_11NG_HT20, modes_allowed);
166*dd1de374Slin wang - Sun Microsystems - Beijing China 
167*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (is_set(ATH9K_MODE_11NA_HT20, ah->ah_caps.wireless_modes) &&
168*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (!country->allow11na20))
169*dd1de374Slin wang - Sun Microsystems - Beijing China 		clr_bit(ATH9K_MODE_11NA_HT20, modes_allowed);
170*dd1de374Slin wang - Sun Microsystems - Beijing China 
171*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (is_set(ATH9K_MODE_11NG_HT40PLUS, ah->ah_caps.wireless_modes) &&
172*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (!country->allow11ng40))
173*dd1de374Slin wang - Sun Microsystems - Beijing China 		clr_bit(ATH9K_MODE_11NG_HT40PLUS, modes_allowed);
174*dd1de374Slin wang - Sun Microsystems - Beijing China 
175*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (is_set(ATH9K_MODE_11NG_HT40MINUS, ah->ah_caps.wireless_modes) &&
176*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (!country->allow11ng40))
177*dd1de374Slin wang - Sun Microsystems - Beijing China 		clr_bit(ATH9K_MODE_11NG_HT40MINUS, modes_allowed);
178*dd1de374Slin wang - Sun Microsystems - Beijing China 
179*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (is_set(ATH9K_MODE_11NA_HT40PLUS, ah->ah_caps.wireless_modes) &&
180*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (!country->allow11na40))
181*dd1de374Slin wang - Sun Microsystems - Beijing China 		clr_bit(ATH9K_MODE_11NA_HT40PLUS, modes_allowed);
182*dd1de374Slin wang - Sun Microsystems - Beijing China 
183*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (is_set(ATH9K_MODE_11NA_HT40MINUS, ah->ah_caps.wireless_modes) &&
184*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (!country->allow11na40))
185*dd1de374Slin wang - Sun Microsystems - Beijing China 		clr_bit(ATH9K_MODE_11NA_HT40MINUS, modes_allowed);
186*dd1de374Slin wang - Sun Microsystems - Beijing China }
187*dd1de374Slin wang - Sun Microsystems - Beijing China 
188*dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t
ath9k_regd_is_public_safety_sku(struct ath_hal * ah)189*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_public_safety_sku(struct ath_hal *ah)
190*dd1de374Slin wang - Sun Microsystems - Beijing China {
191*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint16_t rd;
192*dd1de374Slin wang - Sun Microsystems - Beijing China 
193*dd1de374Slin wang - Sun Microsystems - Beijing China 	rd = ath9k_regd_get_eepromRD(ah);
194*dd1de374Slin wang - Sun Microsystems - Beijing China 
195*dd1de374Slin wang - Sun Microsystems - Beijing China 	switch (rd) {
196*dd1de374Slin wang - Sun Microsystems - Beijing China 	case FCC4_FCCA:
197*dd1de374Slin wang - Sun Microsystems - Beijing China 	case (CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG):
198*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_TRUE);
199*dd1de374Slin wang - Sun Microsystems - Beijing China 	case DEBUG_REG_DMN:
200*dd1de374Slin wang - Sun Microsystems - Beijing China 	case NO_ENUMRD:
201*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (ah->ah_countryCode == CTRY_UNITED_STATES_FCC49)
202*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (B_TRUE);
203*dd1de374Slin wang - Sun Microsystems - Beijing China 		break;
204*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
205*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (B_FALSE);
206*dd1de374Slin wang - Sun Microsystems - Beijing China }
207*dd1de374Slin wang - Sun Microsystems - Beijing China 
208*dd1de374Slin wang - Sun Microsystems - Beijing China static struct country_code_to_enum_rd *
ath9k_regd_find_country(uint16_t countryCode)209*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_find_country(uint16_t countryCode)
210*dd1de374Slin wang - Sun Microsystems - Beijing China {
211*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
212*dd1de374Slin wang - Sun Microsystems - Beijing China 
213*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
214*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (allCountries[i].countryCode == countryCode)
215*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (&allCountries[i]);
216*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
217*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (NULL);
218*dd1de374Slin wang - Sun Microsystems - Beijing China }
219*dd1de374Slin wang - Sun Microsystems - Beijing China 
220*dd1de374Slin wang - Sun Microsystems - Beijing China static uint16_t
ath9k_regd_get_default_country(struct ath_hal * ah)221*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_get_default_country(struct ath_hal *ah)
222*dd1de374Slin wang - Sun Microsystems - Beijing China {
223*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint16_t rd;
224*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
225*dd1de374Slin wang - Sun Microsystems - Beijing China 
226*dd1de374Slin wang - Sun Microsystems - Beijing China 	rd = ath9k_regd_get_eepromRD(ah);
227*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (rd & COUNTRY_ERD_FLAG) {
228*dd1de374Slin wang - Sun Microsystems - Beijing China 		struct country_code_to_enum_rd *country = NULL;
229*dd1de374Slin wang - Sun Microsystems - Beijing China 		uint16_t cc = rd & ~COUNTRY_ERD_FLAG;
230*dd1de374Slin wang - Sun Microsystems - Beijing China 
231*dd1de374Slin wang - Sun Microsystems - Beijing China 		country = ath9k_regd_find_country(cc);
232*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (country != NULL)
233*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (cc);
234*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
235*dd1de374Slin wang - Sun Microsystems - Beijing China 
236*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
237*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (regDomainPairs[i].regDmnEnum == rd) {
238*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (regDomainPairs[i].singleCC != 0)
239*dd1de374Slin wang - Sun Microsystems - Beijing China 				return (regDomainPairs[i].singleCC);
240*dd1de374Slin wang - Sun Microsystems - Beijing China 			else
241*dd1de374Slin wang - Sun Microsystems - Beijing China 				i = ARRAY_SIZE(regDomainPairs);
242*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
243*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (CTRY_DEFAULT);
244*dd1de374Slin wang - Sun Microsystems - Beijing China }
245*dd1de374Slin wang - Sun Microsystems - Beijing China 
246*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_is_valid_reg_domain(int regDmn,struct regDomain * rd)247*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_valid_reg_domain(int regDmn, struct regDomain *rd)
248*dd1de374Slin wang - Sun Microsystems - Beijing China {
249*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
250*dd1de374Slin wang - Sun Microsystems - Beijing China 
251*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < ARRAY_SIZE(regDomains); i++) {
252*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (regDomains[i].regDmnEnum == regDmn) {
253*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (rd != NULL) {
254*dd1de374Slin wang - Sun Microsystems - Beijing China 				(void) memcpy(rd, &regDomains[i],
255*dd1de374Slin wang - Sun Microsystems - Beijing China 				    sizeof (struct regDomain));
256*dd1de374Slin wang - Sun Microsystems - Beijing China 			}
257*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (B_TRUE);
258*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
259*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
260*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (B_FALSE);
261*dd1de374Slin wang - Sun Microsystems - Beijing China }
262*dd1de374Slin wang - Sun Microsystems - Beijing China 
263*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_is_valid_reg_domainPair(int regDmnPair)264*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_valid_reg_domainPair(int regDmnPair)
265*dd1de374Slin wang - Sun Microsystems - Beijing China {
266*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
267*dd1de374Slin wang - Sun Microsystems - Beijing China 
268*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (regDmnPair == NO_ENUMRD)
269*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
270*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
271*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (regDomainPairs[i].regDmnEnum == regDmnPair)
272*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (B_TRUE);
273*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
274*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (B_FALSE);
275*dd1de374Slin wang - Sun Microsystems - Beijing China }
276*dd1de374Slin wang - Sun Microsystems - Beijing China 
277*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_get_wmode_regdomain(struct ath_hal * ah,int regDmn,uint16_t channelFlag,struct regDomain * rd)278*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn,
279*dd1de374Slin wang - Sun Microsystems - Beijing China     uint16_t channelFlag, struct regDomain *rd)
280*dd1de374Slin wang - Sun Microsystems - Beijing China {
281*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i, found;
282*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint64_t flags = NO_REQ;
283*dd1de374Slin wang - Sun Microsystems - Beijing China 	struct reg_dmn_pair_mapping *regPair = NULL;
284*dd1de374Slin wang - Sun Microsystems - Beijing China 	int regOrg;
285*dd1de374Slin wang - Sun Microsystems - Beijing China 
286*dd1de374Slin wang - Sun Microsystems - Beijing China 	regOrg = regDmn;
287*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (regDmn == CTRY_DEFAULT) {
288*dd1de374Slin wang - Sun Microsystems - Beijing China 		uint16_t rdnum;
289*dd1de374Slin wang - Sun Microsystems - Beijing China 		rdnum = ath9k_regd_get_eepromRD(ah);
290*dd1de374Slin wang - Sun Microsystems - Beijing China 
291*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (!(rdnum & COUNTRY_ERD_FLAG)) {
292*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (ath9k_regd_is_valid_reg_domain(rdnum, NULL) ||
293*dd1de374Slin wang - Sun Microsystems - Beijing China 			    ath9k_regd_is_valid_reg_domainPair(rdnum)) {
294*dd1de374Slin wang - Sun Microsystems - Beijing China 				regDmn = rdnum;
295*dd1de374Slin wang - Sun Microsystems - Beijing China 			}
296*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
297*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
298*dd1de374Slin wang - Sun Microsystems - Beijing China 
299*dd1de374Slin wang - Sun Microsystems - Beijing China 	if ((regDmn & MULTI_DOMAIN_MASK) == 0) {
300*dd1de374Slin wang - Sun Microsystems - Beijing China 		for (i = 0, found = 0;
301*dd1de374Slin wang - Sun Microsystems - Beijing China 		    (i < ARRAY_SIZE(regDomainPairs)) && (!found); i++) {
302*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (regDomainPairs[i].regDmnEnum == regDmn) {
303*dd1de374Slin wang - Sun Microsystems - Beijing China 				regPair = &regDomainPairs[i];
304*dd1de374Slin wang - Sun Microsystems - Beijing China 				found = 1;
305*dd1de374Slin wang - Sun Microsystems - Beijing China 			}
306*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
307*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (!found) {
308*dd1de374Slin wang - Sun Microsystems - Beijing China 			ARN_DBG((ARN_DBG_REGULATORY,
309*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "%s: Failed to find reg domain pair %u\n",
310*dd1de374Slin wang - Sun Microsystems - Beijing China 			    __func__, regDmn));
311*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (B_FALSE);
312*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
313*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (!(channelFlag & CHANNEL_2GHZ)) {
314*dd1de374Slin wang - Sun Microsystems - Beijing China 			regDmn = regPair->regDmn5GHz;
315*dd1de374Slin wang - Sun Microsystems - Beijing China 			flags = regPair->flags5GHz;
316*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
317*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (channelFlag & CHANNEL_2GHZ) {
318*dd1de374Slin wang - Sun Microsystems - Beijing China 			regDmn = regPair->regDmn2GHz;
319*dd1de374Slin wang - Sun Microsystems - Beijing China 			flags = regPair->flags2GHz;
320*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
321*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
322*dd1de374Slin wang - Sun Microsystems - Beijing China 
323*dd1de374Slin wang - Sun Microsystems - Beijing China 	found = ath9k_regd_is_valid_reg_domain(regDmn, rd);
324*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (!found) {
325*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
326*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "%s: Failed to find unitary reg domain %u\n",
327*dd1de374Slin wang - Sun Microsystems - Beijing China 		    __func__, regDmn));
328*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
329*dd1de374Slin wang - Sun Microsystems - Beijing China 	} else {
330*dd1de374Slin wang - Sun Microsystems - Beijing China 		rd->pscan &= regPair->pscanMask;
331*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (((regOrg & MULTI_DOMAIN_MASK) == 0) &&
332*dd1de374Slin wang - Sun Microsystems - Beijing China 		    (flags != NO_REQ)) {
333*dd1de374Slin wang - Sun Microsystems - Beijing China 			rd->flags = (uint32_t)flags; /* LINT */
334*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
335*dd1de374Slin wang - Sun Microsystems - Beijing China 
336*dd1de374Slin wang - Sun Microsystems - Beijing China 		rd->flags &= (channelFlag & CHANNEL_2GHZ) ?
337*dd1de374Slin wang - Sun Microsystems - Beijing China 		    REG_DOMAIN_2GHZ_MASK : REG_DOMAIN_5GHZ_MASK;
338*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_TRUE);
339*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
340*dd1de374Slin wang - Sun Microsystems - Beijing China }
341*dd1de374Slin wang - Sun Microsystems - Beijing China 
342*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_is_bit_set(int bit,uint64_t * bitmask)343*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_bit_set(int bit, uint64_t *bitmask)
344*dd1de374Slin wang - Sun Microsystems - Beijing China {
345*dd1de374Slin wang - Sun Microsystems - Beijing China 	int byteOffset, bitnum;
346*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint64_t val;
347*dd1de374Slin wang - Sun Microsystems - Beijing China 
348*dd1de374Slin wang - Sun Microsystems - Beijing China 	byteOffset = bit / 64;
349*dd1de374Slin wang - Sun Microsystems - Beijing China 	bitnum = bit - byteOffset * 64;
350*dd1de374Slin wang - Sun Microsystems - Beijing China 	val = ((uint64_t)1) << bitnum;
351*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (bitmask[byteOffset] & val)
352*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_TRUE);
353*dd1de374Slin wang - Sun Microsystems - Beijing China 	else
354*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
355*dd1de374Slin wang - Sun Microsystems - Beijing China }
356*dd1de374Slin wang - Sun Microsystems - Beijing China 
357*dd1de374Slin wang - Sun Microsystems - Beijing China static void
ath9k_regd_add_reg_classid(uint8_t * regclassids,uint32_t maxregids,uint32_t * nregids,uint8_t regclassid)358*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_add_reg_classid(uint8_t *regclassids, uint32_t maxregids,
359*dd1de374Slin wang - Sun Microsystems - Beijing China     uint32_t *nregids, uint8_t regclassid)
360*dd1de374Slin wang - Sun Microsystems - Beijing China {
361*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
362*dd1de374Slin wang - Sun Microsystems - Beijing China 
363*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (regclassid == 0)
364*dd1de374Slin wang - Sun Microsystems - Beijing China 		return;
365*dd1de374Slin wang - Sun Microsystems - Beijing China 
366*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < maxregids; i++) {
367*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (regclassids[i] == regclassid)
368*dd1de374Slin wang - Sun Microsystems - Beijing China 			return;
369*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (regclassids[i] == 0)
370*dd1de374Slin wang - Sun Microsystems - Beijing China 			break;
371*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
372*dd1de374Slin wang - Sun Microsystems - Beijing China 
373*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (i == maxregids)
374*dd1de374Slin wang - Sun Microsystems - Beijing China 		return;
375*dd1de374Slin wang - Sun Microsystems - Beijing China 	else {
376*dd1de374Slin wang - Sun Microsystems - Beijing China 		regclassids[i] = regclassid;
377*dd1de374Slin wang - Sun Microsystems - Beijing China 		*nregids += 1;
378*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
379*dd1de374Slin wang - Sun Microsystems - Beijing China }
380*dd1de374Slin wang - Sun Microsystems - Beijing China 
381*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_get_eeprom_reg_ext_bits(struct ath_hal * ah,enum reg_ext_bitmap bit)382*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_get_eeprom_reg_ext_bits(struct ath_hal *ah,
383*dd1de374Slin wang - Sun Microsystems - Beijing China     enum reg_ext_bitmap bit)
384*dd1de374Slin wang - Sun Microsystems - Beijing China {
385*dd1de374Slin wang - Sun Microsystems - Beijing China 	return ((ah->ah_currentRDExt & (1 << bit)) ? B_TRUE : B_FALSE);
386*dd1de374Slin wang - Sun Microsystems - Beijing China }
387*dd1de374Slin wang - Sun Microsystems - Beijing China 
388*dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_NF_PER_CHAN
389*dd1de374Slin wang - Sun Microsystems - Beijing China 
390*dd1de374Slin wang - Sun Microsystems - Beijing China static void
ath9k_regd_init_rf_buffer(struct ath9k_channel * ichans,int nchans)391*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_init_rf_buffer(struct ath9k_channel *ichans, int nchans)
392*dd1de374Slin wang - Sun Microsystems - Beijing China {
393*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i, j, next;
394*dd1de374Slin wang - Sun Microsystems - Beijing China 
395*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (next = 0; next < nchans; next++) {
396*dd1de374Slin wang - Sun Microsystems - Beijing China 		for (i = 0; i < NUM_NF_READINGS; i++) {
397*dd1de374Slin wang - Sun Microsystems - Beijing China 			ichans[next].nfCalHist[i].currIndex = 0;
398*dd1de374Slin wang - Sun Microsystems - Beijing China 			ichans[next].nfCalHist[i].privNF =
399*dd1de374Slin wang - Sun Microsystems - Beijing China 			    AR_PHY_CCA_MAX_GOOD_VALUE;
400*dd1de374Slin wang - Sun Microsystems - Beijing China 			ichans[next].nfCalHist[i].invalidNFcount =
401*dd1de374Slin wang - Sun Microsystems - Beijing China 			    AR_PHY_CCA_FILTERWINDOW_LENGTH;
402*dd1de374Slin wang - Sun Microsystems - Beijing China 			for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
403*dd1de374Slin wang - Sun Microsystems - Beijing China 				ichans[next].nfCalHist[i].nfCalBuffer[j] =
404*dd1de374Slin wang - Sun Microsystems - Beijing China 				    AR_PHY_CCA_MAX_GOOD_VALUE;
405*dd1de374Slin wang - Sun Microsystems - Beijing China 			}
406*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
407*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
408*dd1de374Slin wang - Sun Microsystems - Beijing China }
409*dd1de374Slin wang - Sun Microsystems - Beijing China #endif
410*dd1de374Slin wang - Sun Microsystems - Beijing China 
411*dd1de374Slin wang - Sun Microsystems - Beijing China static int
ath9k_regd_is_chan_present(struct ath_hal * ah,uint16_t c)412*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_is_chan_present(struct ath_hal *ah, uint16_t c)
413*dd1de374Slin wang - Sun Microsystems - Beijing China {
414*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
415*dd1de374Slin wang - Sun Microsystems - Beijing China 
416*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < 150; i++) {
417*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (!ah->ah_channels[i].channel)
418*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (-1);
419*dd1de374Slin wang - Sun Microsystems - Beijing China 		else if (ah->ah_channels[i].channel == c)
420*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (i);
421*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
422*dd1de374Slin wang - Sun Microsystems - Beijing China 
423*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (-1);
424*dd1de374Slin wang - Sun Microsystems - Beijing China }
425*dd1de374Slin wang - Sun Microsystems - Beijing China 
426*dd1de374Slin wang - Sun Microsystems - Beijing China /* ARGSUSED */
427*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_add_channel(struct ath_hal * ah,uint16_t c,uint16_t c_lo,uint16_t c_hi,uint16_t maxChan,uint8_t ctl,int pos,struct regDomain rd5GHz,struct RegDmnFreqBand * fband,struct regDomain * rd,const struct cmode * cm,struct ath9k_channel * ichans,boolean_t enableExtendedChannels)428*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_add_channel(
429*dd1de374Slin wang - Sun Microsystems - Beijing China     struct ath_hal *ah,
430*dd1de374Slin wang - Sun Microsystems - Beijing China     uint16_t c,
431*dd1de374Slin wang - Sun Microsystems - Beijing China     uint16_t c_lo,
432*dd1de374Slin wang - Sun Microsystems - Beijing China     uint16_t c_hi,
433*dd1de374Slin wang - Sun Microsystems - Beijing China     uint16_t maxChan,
434*dd1de374Slin wang - Sun Microsystems - Beijing China     uint8_t ctl,
435*dd1de374Slin wang - Sun Microsystems - Beijing China     int pos,
436*dd1de374Slin wang - Sun Microsystems - Beijing China     struct regDomain rd5GHz,
437*dd1de374Slin wang - Sun Microsystems - Beijing China     struct RegDmnFreqBand *fband,
438*dd1de374Slin wang - Sun Microsystems - Beijing China     struct regDomain *rd,
439*dd1de374Slin wang - Sun Microsystems - Beijing China     const struct cmode *cm,
440*dd1de374Slin wang - Sun Microsystems - Beijing China     struct ath9k_channel *ichans,
441*dd1de374Slin wang - Sun Microsystems - Beijing China     boolean_t enableExtendedChannels)
442*dd1de374Slin wang - Sun Microsystems - Beijing China {
443*dd1de374Slin wang - Sun Microsystems - Beijing China 	struct ath9k_channel *chan;
444*dd1de374Slin wang - Sun Microsystems - Beijing China 	int ret;
445*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint32_t channelFlags = 0;
446*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint8_t privFlags = 0;
447*dd1de374Slin wang - Sun Microsystems - Beijing China 
448*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (!(c_lo <= c && c <= c_hi)) {
449*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
450*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "%s: c %u out of range [%u..%u]\n",
451*dd1de374Slin wang - Sun Microsystems - Beijing China 		    __func__, c, c_lo, c_hi));
452*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
453*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
454*dd1de374Slin wang - Sun Microsystems - Beijing China 	if ((fband->channelBW == CHANNEL_HALF_BW) &&
455*dd1de374Slin wang - Sun Microsystems - Beijing China 	    !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_HALFRATE)) {
456*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
457*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "%s: Skipping %u half rate channel\n",
458*dd1de374Slin wang - Sun Microsystems - Beijing China 		    __func__, c));
459*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
460*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
461*dd1de374Slin wang - Sun Microsystems - Beijing China 
462*dd1de374Slin wang - Sun Microsystems - Beijing China 	if ((fband->channelBW == CHANNEL_QUARTER_BW) &&
463*dd1de374Slin wang - Sun Microsystems - Beijing China 	    !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_QUARTERRATE)) {
464*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
465*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "%s: Skipping %u quarter rate channel\n",
466*dd1de374Slin wang - Sun Microsystems - Beijing China 		    __func__, c));
467*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
468*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
469*dd1de374Slin wang - Sun Microsystems - Beijing China 
470*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (((c + fband->channelSep) / 2) > (maxChan + HALF_MAXCHANBW)) {
471*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
472*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "%s: c %u > maxChan %u\n",
473*dd1de374Slin wang - Sun Microsystems - Beijing China 		    __func__, c, maxChan));
474*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
475*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
476*dd1de374Slin wang - Sun Microsystems - Beijing China 
477*dd1de374Slin wang - Sun Microsystems - Beijing China 	if ((fband->usePassScan & IS_ECM_CHAN) && !enableExtendedChannels) {
478*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
479*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "Skipping ecm channel\n"));
480*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
481*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
482*dd1de374Slin wang - Sun Microsystems - Beijing China 
483*dd1de374Slin wang - Sun Microsystems - Beijing China 	if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == ATH9K_M_HOSTAP)) {
484*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
485*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "Skipping HOSTAP channel\n"));
486*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
487*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
488*dd1de374Slin wang - Sun Microsystems - Beijing China 
489*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (IS_HT40_MODE(cm->mode) &&
490*dd1de374Slin wang - Sun Microsystems - Beijing China 	    !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_FCC_DFS_HT40)) &&
491*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (fband->useDfs) &&
492*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (rd->conformanceTestLimit != MKK)) {
493*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
494*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "Skipping HT40 channel (en_fcc_dfs_ht40 = 0)\n"));
495*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
496*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
497*dd1de374Slin wang - Sun Microsystems - Beijing China 
498*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (IS_HT40_MODE(cm->mode) &&
499*dd1de374Slin wang - Sun Microsystems - Beijing China 	    !(ath9k_regd_get_eeprom_reg_ext_bits(ah,
500*dd1de374Slin wang - Sun Microsystems - Beijing China 	    REG_EXT_JAPAN_NONDFS_HT40)) &&
501*dd1de374Slin wang - Sun Microsystems - Beijing China 	    !(fband->useDfs) && (rd->conformanceTestLimit == MKK)) {
502*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
503*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "Skipping HT40 channel (en_jap_ht40 = 0)\n"));
504*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
505*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
506*dd1de374Slin wang - Sun Microsystems - Beijing China 
507*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (IS_HT40_MODE(cm->mode) &&
508*dd1de374Slin wang - Sun Microsystems - Beijing China 	    !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_JAPAN_DFS_HT40)) &&
509*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (fband->useDfs) &&
510*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (rd->conformanceTestLimit == MKK)) {
511*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY,
512*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "Skipping HT40 channel (en_jap_dfs_ht40 = 0)\n"));
513*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
514*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
515*dd1de374Slin wang - Sun Microsystems - Beijing China 
516*dd1de374Slin wang - Sun Microsystems - Beijing China 	/* Calculate channel flags */
517*dd1de374Slin wang - Sun Microsystems - Beijing China 
518*dd1de374Slin wang - Sun Microsystems - Beijing China 	channelFlags = cm->flags;
519*dd1de374Slin wang - Sun Microsystems - Beijing China 
520*dd1de374Slin wang - Sun Microsystems - Beijing China 	switch (fband->channelBW) {
521*dd1de374Slin wang - Sun Microsystems - Beijing China 	case CHANNEL_HALF_BW:
522*dd1de374Slin wang - Sun Microsystems - Beijing China 		channelFlags |= CHANNEL_HALF;
523*dd1de374Slin wang - Sun Microsystems - Beijing China 		break;
524*dd1de374Slin wang - Sun Microsystems - Beijing China 	case CHANNEL_QUARTER_BW:
525*dd1de374Slin wang - Sun Microsystems - Beijing China 		channelFlags |= CHANNEL_QUARTER;
526*dd1de374Slin wang - Sun Microsystems - Beijing China 		break;
527*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
528*dd1de374Slin wang - Sun Microsystems - Beijing China 
529*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (fband->usePassScan & rd->pscan)
530*dd1de374Slin wang - Sun Microsystems - Beijing China 		channelFlags |= CHANNEL_PASSIVE;
531*dd1de374Slin wang - Sun Microsystems - Beijing China 	else
532*dd1de374Slin wang - Sun Microsystems - Beijing China 		channelFlags &= ~CHANNEL_PASSIVE;
533*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (fband->useDfs & rd->dfsMask)
534*dd1de374Slin wang - Sun Microsystems - Beijing China 		privFlags = CHANNEL_DFS;
535*dd1de374Slin wang - Sun Microsystems - Beijing China 	else
536*dd1de374Slin wang - Sun Microsystems - Beijing China 		privFlags = 0;
537*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (rd->flags & LIMIT_FRAME_4MS)
538*dd1de374Slin wang - Sun Microsystems - Beijing China 		privFlags |= CHANNEL_4MS_LIMIT;
539*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (privFlags & CHANNEL_DFS)
540*dd1de374Slin wang - Sun Microsystems - Beijing China 		privFlags |= CHANNEL_DISALLOW_ADHOC;
541*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (rd->flags & ADHOC_PER_11D)
542*dd1de374Slin wang - Sun Microsystems - Beijing China 		privFlags |= CHANNEL_PER_11D_ADHOC;
543*dd1de374Slin wang - Sun Microsystems - Beijing China 
544*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (channelFlags & CHANNEL_PASSIVE) {
545*dd1de374Slin wang - Sun Microsystems - Beijing China 		if ((c < 2412) || (c > 2462)) {
546*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (rd5GHz.regDmnEnum == MKK1 ||
547*dd1de374Slin wang - Sun Microsystems - Beijing China 			    rd5GHz.regDmnEnum == MKK2) {
548*dd1de374Slin wang - Sun Microsystems - Beijing China 				uint32_t regcap = ah->ah_caps.reg_cap;
549*dd1de374Slin wang - Sun Microsystems - Beijing China 				if (!(regcap &
550*dd1de374Slin wang - Sun Microsystems - Beijing China 				    (AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
551*dd1de374Slin wang - Sun Microsystems - Beijing China 				    AR_EEPROM_EEREGCAP_EN_KK_U2 |
552*dd1de374Slin wang - Sun Microsystems - Beijing China 				    AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) &&
553*dd1de374Slin wang - Sun Microsystems - Beijing China 				    isUNII1OddChan(c)) {
554*dd1de374Slin wang - Sun Microsystems - Beijing China 					channelFlags &= ~CHANNEL_PASSIVE;
555*dd1de374Slin wang - Sun Microsystems - Beijing China 				} else {
556*dd1de374Slin wang - Sun Microsystems - Beijing China 					privFlags |= CHANNEL_DISALLOW_ADHOC;
557*dd1de374Slin wang - Sun Microsystems - Beijing China 				}
558*dd1de374Slin wang - Sun Microsystems - Beijing China 			} else {
559*dd1de374Slin wang - Sun Microsystems - Beijing China 				privFlags |= CHANNEL_DISALLOW_ADHOC;
560*dd1de374Slin wang - Sun Microsystems - Beijing China 			}
561*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
562*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
563*dd1de374Slin wang - Sun Microsystems - Beijing China 
564*dd1de374Slin wang - Sun Microsystems - Beijing China 	if ((cm->mode == ATH9K_MODE_11A) ||
565*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (cm->mode == ATH9K_MODE_11NA_HT20) ||
566*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
567*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (cm->mode == ATH9K_MODE_11NA_HT40MINUS)) {
568*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (rd->flags & (ADHOC_NO_11A | DISALLOW_ADHOC_11A))
569*dd1de374Slin wang - Sun Microsystems - Beijing China 			privFlags |= CHANNEL_DISALLOW_ADHOC;
570*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
571*dd1de374Slin wang - Sun Microsystems - Beijing China 
572*dd1de374Slin wang - Sun Microsystems - Beijing China 	/* Fill in channel details */
573*dd1de374Slin wang - Sun Microsystems - Beijing China 
574*dd1de374Slin wang - Sun Microsystems - Beijing China 	ret = ath9k_regd_is_chan_present(ah, c);
575*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (ret == -1) {
576*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan = &ah->ah_channels[pos];
577*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->channel = c;
578*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->maxRegTxPower = fband->powerDfs;
579*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->antennaMax = fband->antennaMax;
580*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->regDmnFlags = rd->flags;
581*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->maxTxPower = AR5416_MAX_RATE_POWER;
582*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->minTxPower = AR5416_MAX_RATE_POWER;
583*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->channelFlags = channelFlags;
584*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->privFlags = privFlags;
585*dd1de374Slin wang - Sun Microsystems - Beijing China 	} else {
586*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan = &ah->ah_channels[ret];
587*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->channelFlags |= channelFlags;
588*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->privFlags |= privFlags;
589*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
590*dd1de374Slin wang - Sun Microsystems - Beijing China 
591*dd1de374Slin wang - Sun Microsystems - Beijing China 	/* Set CTLs */
592*dd1de374Slin wang - Sun Microsystems - Beijing China 
593*dd1de374Slin wang - Sun Microsystems - Beijing China 	if ((cm->flags & CHANNEL_ALL) == CHANNEL_A)
594*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->conformanceTestLimit[0] = ctl;
595*dd1de374Slin wang - Sun Microsystems - Beijing China 	else if ((cm->flags & CHANNEL_ALL) == CHANNEL_B)
596*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->conformanceTestLimit[1] = ctl;
597*dd1de374Slin wang - Sun Microsystems - Beijing China 	else if ((cm->flags & CHANNEL_ALL) == CHANNEL_G)
598*dd1de374Slin wang - Sun Microsystems - Beijing China 		chan->conformanceTestLimit[2] = ctl;
599*dd1de374Slin wang - Sun Microsystems - Beijing China 
600*dd1de374Slin wang - Sun Microsystems - Beijing China 	return ((ret == -1) ? B_TRUE : B_FALSE);
601*dd1de374Slin wang - Sun Microsystems - Beijing China }
602*dd1de374Slin wang - Sun Microsystems - Beijing China 
603*dd1de374Slin wang - Sun Microsystems - Beijing China static boolean_t
ath9k_regd_japan_check(struct ath_hal * ah,int b,struct regDomain * rd5GHz)604*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_japan_check(struct ath_hal *ah, int b, struct regDomain *rd5GHz)
605*dd1de374Slin wang - Sun Microsystems - Beijing China {
606*dd1de374Slin wang - Sun Microsystems - Beijing China 	boolean_t skipband = B_FALSE;
607*dd1de374Slin wang - Sun Microsystems - Beijing China 	int i;
608*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint32_t regcap;
609*dd1de374Slin wang - Sun Microsystems - Beijing China 
610*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (i = 0; i < ARRAY_SIZE(j_bandcheck); i++) {
611*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (j_bandcheck[i].freqbandbit == b) {
612*dd1de374Slin wang - Sun Microsystems - Beijing China 			regcap = ah->ah_caps.reg_cap;
613*dd1de374Slin wang - Sun Microsystems - Beijing China 			if ((j_bandcheck[i].eepromflagtocheck & regcap) == 0) {
614*dd1de374Slin wang - Sun Microsystems - Beijing China 				skipband = B_TRUE;
615*dd1de374Slin wang - Sun Microsystems - Beijing China 			} else if ((regcap & AR_EEPROM_EEREGCAP_EN_KK_U2) ||
616*dd1de374Slin wang - Sun Microsystems - Beijing China 			    (regcap & AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) {
617*dd1de374Slin wang - Sun Microsystems - Beijing China 				rd5GHz->dfsMask |= DFS_MKK4;
618*dd1de374Slin wang - Sun Microsystems - Beijing China 				rd5GHz->pscan |= PSCAN_MKK3;
619*dd1de374Slin wang - Sun Microsystems - Beijing China 			}
620*dd1de374Slin wang - Sun Microsystems - Beijing China 			break;
621*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
622*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
623*dd1de374Slin wang - Sun Microsystems - Beijing China 
624*dd1de374Slin wang - Sun Microsystems - Beijing China 	ARN_DBG((ARN_DBG_REGULATORY,
625*dd1de374Slin wang - Sun Microsystems - Beijing China 	    "%s: Skipping %d freq band\n",
626*dd1de374Slin wang - Sun Microsystems - Beijing China 	    __func__, j_bandcheck[i].freqbandbit));
627*dd1de374Slin wang - Sun Microsystems - Beijing China 
628*dd1de374Slin wang - Sun Microsystems - Beijing China 	return (skipband);
629*dd1de374Slin wang - Sun Microsystems - Beijing China }
630*dd1de374Slin wang - Sun Microsystems - Beijing China 
631*dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t
ath9k_regd_init_channels(struct ath_hal * ah,uint32_t maxchans,uint32_t * nchans,uint8_t * regclassids,uint32_t maxregids,uint32_t * nregids,uint16_t cc,boolean_t enableOutdoor,boolean_t enableExtendedChannels)632*dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_regd_init_channels(
633*dd1de374Slin wang - Sun Microsystems - Beijing China     struct ath_hal *ah,
634*dd1de374Slin wang - Sun Microsystems - Beijing China     uint32_t maxchans,
635*dd1de374Slin wang - Sun Microsystems - Beijing China     uint32_t *nchans,
636*dd1de374Slin wang - Sun Microsystems - Beijing China     uint8_t *regclassids,
637*dd1de374Slin wang - Sun Microsystems - Beijing China     uint32_t maxregids,
638*dd1de374Slin wang - Sun Microsystems - Beijing China     uint32_t *nregids,
639*dd1de374Slin wang - Sun Microsystems - Beijing China     uint16_t cc,
640*dd1de374Slin wang - Sun Microsystems - Beijing China     boolean_t enableOutdoor,
641*dd1de374Slin wang - Sun Microsystems - Beijing China     boolean_t enableExtendedChannels)
642*dd1de374Slin wang - Sun Microsystems - Beijing China {
643*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint16_t maxChan = 7000;
644*dd1de374Slin wang - Sun Microsystems - Beijing China 	struct country_code_to_enum_rd *country = NULL;
645*dd1de374Slin wang - Sun Microsystems - Beijing China 	struct regDomain rd5GHz, rd2GHz;
646*dd1de374Slin wang - Sun Microsystems - Beijing China 	const struct cmode *cm;
647*dd1de374Slin wang - Sun Microsystems - Beijing China 	struct ath9k_channel *ichans = &ah->ah_channels[0];
648*dd1de374Slin wang - Sun Microsystems - Beijing China 	int next = 0, b;
649*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint8_t ctl;
650*dd1de374Slin wang - Sun Microsystems - Beijing China 	int regdmn;
651*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint16_t chanSep;
652*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint8_t *modes_avail;
653*dd1de374Slin wang - Sun Microsystems - Beijing China 	uint8_t modes_allowed[4];
654*dd1de374Slin wang - Sun Microsystems - Beijing China 
655*dd1de374Slin wang - Sun Microsystems - Beijing China 	(void) memset(modes_allowed, 0, sizeof (modes_allowed));
656*dd1de374Slin wang - Sun Microsystems - Beijing China 	ARN_DBG((ARN_DBG_REGULATORY, "arn: ath9k_regd_init_channels(): "
657*dd1de374Slin wang - Sun Microsystems - Beijing China 	    "cc %u %s %s\n",
658*dd1de374Slin wang - Sun Microsystems - Beijing China 	    cc,
659*dd1de374Slin wang - Sun Microsystems - Beijing China 	    enableOutdoor ? "Enable outdoor" : "",
660*dd1de374Slin wang - Sun Microsystems - Beijing China 	    enableExtendedChannels ? "Enable ecm" : ""));
661*dd1de374Slin wang - Sun Microsystems - Beijing China 
662*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (!ath9k_regd_is_ccode_valid(ah, cc)) {
663*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_XMIT, "arn: ath9k_regd_init_channels(): "
664*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "invalid country code %d\n", cc));
665*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
666*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
667*dd1de374Slin wang - Sun Microsystems - Beijing China 
668*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (!ath9k_regd_is_eeprom_valid(ah)) {
669*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_ANY, "arn: ath9k_regd_init_channels(): "
670*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "invalid EEPROM contents\n"));
671*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
672*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
673*dd1de374Slin wang - Sun Microsystems - Beijing China 
674*dd1de374Slin wang - Sun Microsystems - Beijing China 	ah->ah_countryCode = ath9k_regd_get_default_country(ah);
675*dd1de374Slin wang - Sun Microsystems - Beijing China 
676*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (ah->ah_countryCode == CTRY_DEFAULT) {
677*dd1de374Slin wang - Sun Microsystems - Beijing China 		ah->ah_countryCode = cc & COUNTRY_CODE_MASK;
678*dd1de374Slin wang - Sun Microsystems - Beijing China 		if ((ah->ah_countryCode == CTRY_DEFAULT) &&
679*dd1de374Slin wang - Sun Microsystems - Beijing China 		    (ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT)) {
680*dd1de374Slin wang - Sun Microsystems - Beijing China 			ah->ah_countryCode = CTRY_UNITED_STATES;
681*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
682*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
683*dd1de374Slin wang - Sun Microsystems - Beijing China 
684*dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_SUPPORT_11D
685*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (ah->ah_countryCode == CTRY_DEFAULT) {
686*dd1de374Slin wang - Sun Microsystems - Beijing China 		regdmn = ath9k_regd_get_eepromRD(ah);
687*dd1de374Slin wang - Sun Microsystems - Beijing China 		country = NULL;
688*dd1de374Slin wang - Sun Microsystems - Beijing China 	} else {
689*dd1de374Slin wang - Sun Microsystems - Beijing China #endif
690*dd1de374Slin wang - Sun Microsystems - Beijing China 		country = ath9k_regd_find_country(ah->ah_countryCode);
691*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (country == NULL) {
692*dd1de374Slin wang - Sun Microsystems - Beijing China 			ARN_DBG((ARN_DBG_REGULATORY,
693*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "arn: ath9k_regd_init_channels(): "
694*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "Country is NULL!!!!, cc= %d\n",
695*dd1de374Slin wang - Sun Microsystems - Beijing China 			    ah->ah_countryCode));
696*dd1de374Slin wang - Sun Microsystems - Beijing China 
697*dd1de374Slin wang - Sun Microsystems - Beijing China 			return (B_FALSE);
698*dd1de374Slin wang - Sun Microsystems - Beijing China 		} else {
699*dd1de374Slin wang - Sun Microsystems - Beijing China 			regdmn = country->regDmnEnum;
700*dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_SUPPORT_11D
701*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (((ath9k_regd_get_eepromRD(ah) &
702*dd1de374Slin wang - Sun Microsystems - Beijing China 			    WORLD_SKU_MASK) == WORLD_SKU_PREFIX) &&
703*dd1de374Slin wang - Sun Microsystems - Beijing China 			    (cc == CTRY_UNITED_STATES)) {
704*dd1de374Slin wang - Sun Microsystems - Beijing China 				if (!isWwrSKU_NoMidband(ah) &&
705*dd1de374Slin wang - Sun Microsystems - Beijing China 				    ath9k_regd_is_fcc_midband_supported(ah))
706*dd1de374Slin wang - Sun Microsystems - Beijing China 					regdmn = FCC3_FCCA;
707*dd1de374Slin wang - Sun Microsystems - Beijing China 				else
708*dd1de374Slin wang - Sun Microsystems - Beijing China 					regdmn = FCC1_FCCA;
709*dd1de374Slin wang - Sun Microsystems - Beijing China 			}
710*dd1de374Slin wang - Sun Microsystems - Beijing China #endif
711*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
712*dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_SUPPORT_11D
713*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
714*dd1de374Slin wang - Sun Microsystems - Beijing China #endif
715*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (!ath9k_regd_get_wmode_regdomain(ah, regdmn,
716*dd1de374Slin wang - Sun Microsystems - Beijing China 	    ~CHANNEL_2GHZ, &rd5GHz)) {
717*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY, "arn: ath9k_regd_init_channels(): "
718*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "couldn't find unitary "
719*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "5GHz reg domain for country %u\n",
720*dd1de374Slin wang - Sun Microsystems - Beijing China 		    ah->ah_countryCode));
721*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
722*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
723*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (!ath9k_regd_get_wmode_regdomain(ah, regdmn,
724*dd1de374Slin wang - Sun Microsystems - Beijing China 	    CHANNEL_2GHZ, &rd2GHz)) {
725*dd1de374Slin wang - Sun Microsystems - Beijing China 		ARN_DBG((ARN_DBG_REGULATORY, "arn: ath9k_regd_init_channels(): "
726*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "couldn't find unitary 2GHz "
727*dd1de374Slin wang - Sun Microsystems - Beijing China 		    "reg domain for country %u\n",
728*dd1de374Slin wang - Sun Microsystems - Beijing China 		    ah->ah_countryCode));
729*dd1de374Slin wang - Sun Microsystems - Beijing China 		return (B_FALSE);
730*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
731*dd1de374Slin wang - Sun Microsystems - Beijing China 
732*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (!isWwrSKU(ah) && ((rd5GHz.regDmnEnum == FCC1) ||
733*dd1de374Slin wang - Sun Microsystems - Beijing China 	    (rd5GHz.regDmnEnum == FCC2))) {
734*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (ath9k_regd_is_fcc_midband_supported(ah)) {
735*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (!ath9k_regd_get_wmode_regdomain(ah,
736*dd1de374Slin wang - Sun Microsystems - Beijing China 			    FCC3_FCCA, ~CHANNEL_2GHZ, &rd5GHz)) {
737*dd1de374Slin wang - Sun Microsystems - Beijing China 				ARN_DBG((ARN_DBG_REGULATORY,
738*dd1de374Slin wang - Sun Microsystems - Beijing China 				    "arn: ath9k_regd_init_channels(): "
739*dd1de374Slin wang - Sun Microsystems - Beijing China 				    "couldn't find unitary 5GHz "
740*dd1de374Slin wang - Sun Microsystems - Beijing China 				    "reg domain for country %u\n",
741*dd1de374Slin wang - Sun Microsystems - Beijing China 				    ah->ah_countryCode));
742*dd1de374Slin wang - Sun Microsystems - Beijing China 				return (B_FALSE);
743*dd1de374Slin wang - Sun Microsystems - Beijing China 			}
744*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
745*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
746*dd1de374Slin wang - Sun Microsystems - Beijing China 
747*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (country == NULL) {
748*dd1de374Slin wang - Sun Microsystems - Beijing China 		modes_avail = ah->ah_caps.wireless_modes;
749*dd1de374Slin wang - Sun Microsystems - Beijing China 	} else {
750*dd1de374Slin wang - Sun Microsystems - Beijing China 		ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz, modes_allowed);
751*dd1de374Slin wang - Sun Microsystems - Beijing China 		modes_avail = modes_allowed;
752*dd1de374Slin wang - Sun Microsystems - Beijing China 
753*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (!enableOutdoor)
754*dd1de374Slin wang - Sun Microsystems - Beijing China 			maxChan = country->outdoorChanStart;
755*dd1de374Slin wang - Sun Microsystems - Beijing China 	}
756*dd1de374Slin wang - Sun Microsystems - Beijing China 
757*dd1de374Slin wang - Sun Microsystems - Beijing China 	next = 0;
758*dd1de374Slin wang - Sun Microsystems - Beijing China 
759*dd1de374Slin wang - Sun Microsystems - Beijing China 	if (maxchans > ARRAY_SIZE(ah->ah_channels))
760*dd1de374Slin wang - Sun Microsystems - Beijing China 		maxchans = ARRAY_SIZE(ah->ah_channels);
761*dd1de374Slin wang - Sun Microsystems - Beijing China 
762*dd1de374Slin wang - Sun Microsystems - Beijing China 	for (cm = modes; cm < &modes[ARRAY_SIZE(modes)]; cm++) {
763*dd1de374Slin wang - Sun Microsystems - Beijing China 		uint16_t c, c_hi, c_lo;
764*dd1de374Slin wang - Sun Microsystems - Beijing China 		uint64_t *channelBM = NULL;
765*dd1de374Slin wang - Sun Microsystems - Beijing China 		struct regDomain *rd = NULL;
766*dd1de374Slin wang - Sun Microsystems - Beijing China 		struct RegDmnFreqBand *fband = NULL, *freqs;
767*dd1de374Slin wang - Sun Microsystems - Beijing China 		int8_t low_adj = 0, hi_adj = 0;
768*dd1de374Slin wang - Sun Microsystems - Beijing China 
769*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (!is_set(cm->mode, modes_avail)) {
770*dd1de374Slin wang - Sun Microsystems - Beijing China 			ARN_DBG((ARN_DBG_REGULATORY,
771*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "%s: !avail mode %d flags 0x%x\n",
772*dd1de374Slin wang - Sun Microsystems - Beijing China 			    __func__, cm->mode, cm->flags));
773*dd1de374Slin wang - Sun Microsystems - Beijing China 			continue;
774*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
775*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (!ath9k_get_channel_edges(ah, cm->flags, &c_lo, &c_hi)) {
776*dd1de374Slin wang - Sun Microsystems - Beijing China 			ARN_DBG((ARN_DBG_REGULATORY,
777*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "arn: ath9k_regd_init_channels(): "
778*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "channels 0x%x not supported "
779*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "by hardware\n", cm->flags));
780*dd1de374Slin wang - Sun Microsystems - Beijing China 			continue;
781*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
782*dd1de374Slin wang - Sun Microsystems - Beijing China 
783*dd1de374Slin wang - Sun Microsystems - Beijing China 		switch (cm->mode) {
784*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11A:
785*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11NA_HT20:
786*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11NA_HT40PLUS:
787*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11NA_HT40MINUS:
788*dd1de374Slin wang - Sun Microsystems - Beijing China 			rd = &rd5GHz;
789*dd1de374Slin wang - Sun Microsystems - Beijing China 			channelBM = rd->chan11a;
790*dd1de374Slin wang - Sun Microsystems - Beijing China 			freqs = &regDmn5GhzFreq[0];
791*dd1de374Slin wang - Sun Microsystems - Beijing China 			ctl = rd->conformanceTestLimit;
792*dd1de374Slin wang - Sun Microsystems - Beijing China 			break;
793*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11B:
794*dd1de374Slin wang - Sun Microsystems - Beijing China 			rd = &rd2GHz;
795*dd1de374Slin wang - Sun Microsystems - Beijing China 			channelBM = rd->chan11b;
796*dd1de374Slin wang - Sun Microsystems - Beijing China 			freqs = &regDmn2GhzFreq[0];
797*dd1de374Slin wang - Sun Microsystems - Beijing China 			ctl = rd->conformanceTestLimit | CTL_11B;
798*dd1de374Slin wang - Sun Microsystems - Beijing China 			break;
799*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11G:
800*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11NG_HT20:
801*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11NG_HT40PLUS:
802*dd1de374Slin wang - Sun Microsystems - Beijing China 		case ATH9K_MODE_11NG_HT40MINUS:
803*dd1de374Slin wang - Sun Microsystems - Beijing China 			rd = &rd2GHz;
804*dd1de374Slin wang - Sun Microsystems - Beijing China 			channelBM = rd->chan11g;
805*dd1de374Slin wang - Sun Microsystems - Beijing China 			freqs = &regDmn2Ghz11gFreq[0];
806*dd1de374Slin wang - Sun Microsystems - Beijing China 			ctl = rd->conformanceTestLimit | CTL_11G;
807*dd1de374Slin wang - Sun Microsystems - Beijing China 			break;
808*dd1de374Slin wang - Sun Microsystems - Beijing China 		default:
809*dd1de374Slin wang - Sun Microsystems - Beijing China 			ARN_DBG((ARN_DBG_REGULATORY,
810*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "arn: ath9k_regd_init_channels(): "
811*dd1de374Slin wang - Sun Microsystems - Beijing China 			    "Unknown HAL mode 0x%x\n", cm->mode));
812*dd1de374Slin wang - Sun Microsystems - Beijing China 			continue;
813*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
814*dd1de374Slin wang - Sun Microsystems - Beijing China 
815*dd1de374Slin wang - Sun Microsystems - Beijing China 		if (ath9k_regd_is_chan_bm_zero(channelBM))
816*dd1de374Slin wang - Sun Microsystems - Beijing China 			continue;
817*dd1de374Slin wang - Sun Microsystems - Beijing China 
818*dd1de374Slin wang - Sun Microsystems - Beijing China 		if ((cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
819*dd1de374Slin wang - Sun Microsystems - Beijing China 		    (cm->mode == ATH9K_MODE_11NG_HT40PLUS)) {
820*dd1de374Slin wang - Sun Microsystems - Beijing China 			hi_adj = -20;
821*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
822*dd1de374Slin wang - Sun Microsystems - Beijing China 
823*dd1de374Slin wang - Sun Microsystems - Beijing China 		if ((cm->mode == ATH9K_MODE_11NA_HT40MINUS) ||
824*dd1de374Slin wang - Sun Microsystems - Beijing China 		    (cm->mode == ATH9K_MODE_11NG_HT40MINUS)) {
825*dd1de374Slin wang - Sun Microsystems - Beijing China 			low_adj = 20;
826*dd1de374Slin wang - Sun Microsystems - Beijing China 		}
827*dd1de374Slin wang - Sun Microsystems - Beijing China 
828*dd1de374Slin wang - Sun Microsystems - Beijing China 		/* XXX: Add a helper here instead */
829*dd1de374Slin wang - Sun Microsystems - Beijing China 		for (b = 0; b < 64 * BMLEN; b++) {
830*dd1de374Slin wang - Sun Microsystems - Beijing China 			if (ath9k_regd_is_bit_set(b, channelBM)) {
831*dd1de374Slin wang - Sun Microsystems - Beijing China 				fband = &freqs[b];
832*dd1de374Slin wang - Sun Microsystems - Beijing China 				if (rd5GHz.regDmnEnum == MKK1 ||
833*dd1de374Slin wang - Sun Microsystems - Beijing China 				    rd5GHz.regDmnEnum == MKK2) {
834*dd1de374Slin wang - Sun Microsystems - Beijing China 					if (ath9k_regd_japan_check(ah,
835*dd1de374Slin wang - Sun Microsystems - Beijing China 					    b, &rd5GHz))
836*dd1de374Slin wang - Sun Microsystems - Beijing China 						continue;
837*dd1de374Slin wang - Sun Microsystems - Beijing China 				}
838*dd1de374Slin wang - Sun Microsystems - Beijing China 
839*dd1de374Slin wang - Sun Microsystems - Beijing China 				ath9k_regd_add_reg_classid(regclassids,
840