1 /*
2  * Copyright (c) 2008-2009 Atheros Communications Inc.
3  *
4  * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
5  * Original from Linux kernel 3.0.1
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "regd.h"
21 #include "regd_common.h"
22 
23 /*
24  * This is a set of common rules used by our world regulatory domains.
25  * We have 12 world regulatory domains. To save space we consolidate
26  * the regulatory domains in 5 structures by frequency and change
27  * the flags on our reg_notifier() on a case by case basis.
28  */
29 
30 /* Only these channels all allow active scan on all world regulatory domains */
31 #define ATH9K_2GHZ_CH01_11	REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
32 
33 /* We enable active scan on these a case by case basis by regulatory domain */
34 #define ATH9K_2GHZ_CH12_13	REG_RULE(2467-10, 2472+10, 40, 0, 20,\
35 					NL80211_RRF_PASSIVE_SCAN)
36 #define ATH9K_2GHZ_CH14		REG_RULE(2484-10, 2484+10, 40, 0, 20,\
37 				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
38 
39 /* We allow IBSS on these on a case by case basis by regulatory domain */
40 #define ATH9K_5GHZ_5150_5350	REG_RULE(5150-10, 5350+10, 40, 0, 30,\
41 				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
42 #define ATH9K_5GHZ_5470_5850	REG_RULE(5470-10, 5850+10, 40, 0, 30,\
43 				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
44 #define ATH9K_5GHZ_5725_5850	REG_RULE(5725-10, 5850+10, 40, 0, 30,\
45 				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
46 
47 #define ATH9K_2GHZ_ALL		ATH9K_2GHZ_CH01_11, \
48 				ATH9K_2GHZ_CH12_13, \
49 				ATH9K_2GHZ_CH14
50 
51 #define ATH9K_5GHZ_ALL		ATH9K_5GHZ_5150_5350, \
52 				ATH9K_5GHZ_5470_5850
53 
54 /* This one skips what we call "mid band" */
55 #define ATH9K_5GHZ_NO_MIDBAND	ATH9K_5GHZ_5150_5350, \
56 				ATH9K_5GHZ_5725_5850
57 
58 ///* Can be used for:
59 // * 0x60, 0x61, 0x62 */
60 //static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
61 //	.n_reg_rules = 5,
62 //	.alpha2 =  "99",
63 //	.reg_rules = {
64 //		ATH9K_2GHZ_ALL,
65 //		ATH9K_5GHZ_ALL,
66 //	}
67 //};
68 //
69 ///* Can be used by 0x63 and 0x65 */
70 //static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
71 //	.n_reg_rules = 4,
72 //	.alpha2 =  "99",
73 //	.reg_rules = {
74 //		ATH9K_2GHZ_CH01_11,
75 //		ATH9K_2GHZ_CH12_13,
76 //		ATH9K_5GHZ_NO_MIDBAND,
77 //	}
78 //};
79 //
80 ///* Can be used by 0x64 only */
81 //static const struct ieee80211_regdomain ath_world_regdom_64 = {
82 //	.n_reg_rules = 3,
83 //	.alpha2 =  "99",
84 //	.reg_rules = {
85 //		ATH9K_2GHZ_CH01_11,
86 //		ATH9K_5GHZ_NO_MIDBAND,
87 //	}
88 //};
89 //
90 ///* Can be used by 0x66 and 0x69 */
91 //static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
92 //	.n_reg_rules = 3,
93 //	.alpha2 =  "99",
94 //	.reg_rules = {
95 //		ATH9K_2GHZ_CH01_11,
96 //		ATH9K_5GHZ_ALL,
97 //	}
98 //};
99 //
100 ///* Can be used by 0x67, 0x68, 0x6A and 0x6C */
101 //static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
102 //	.n_reg_rules = 4,
103 //	.alpha2 =  "99",
104 //	.reg_rules = {
105 //		ATH9K_2GHZ_CH01_11,
106 //		ATH9K_2GHZ_CH12_13,
107 //		ATH9K_5GHZ_ALL,
108 //	}
109 //};
110 //
111 //static inline int is_wwr_sku(u16 regd)
112 //{
113 //	return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) &&
114 //		(((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
115 //		(regd == WORLD));
116 //}
117 //
118 //static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
119 //{
120 //	return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
121 //}
122 //
123 //int ath_is_world_regd(struct ath_regulatory *reg)
124 //{
125 //	return is_wwr_sku(ath_regd_get_eepromRD(reg));
126 //}
127 //
128 //static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
129 //{
130 //	/* this is the most restrictive */
131 //	return &ath_world_regdom_64;
132 //}
133 //
134 //static const struct
135 //ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
136 //{
137 //	switch (reg->regpair->regDmnEnum) {
138 //	case 0x60:
139 //	case 0x61:
140 //	case 0x62:
141 //		return &ath_world_regdom_60_61_62;
142 //	case 0x63:
143 //	case 0x65:
144 //		return &ath_world_regdom_63_65;
145 //	case 0x64:
146 //		return &ath_world_regdom_64;
147 //	case 0x66:
148 //	case 0x69:
149 //		return &ath_world_regdom_66_69;
150 //	case 0x67:
151 //	case 0x68:
152 //	case 0x6A:
153 //	case 0x6C:
154 //		return &ath_world_regdom_67_68_6A_6C;
155 //	default:
156 //		WARN_ON(1);
157 //		return ath_default_world_regdomain();
158 //	}
159 //}
160 //
161 //int ath_is_49ghz_allowed(u16 regdomain)
162 //{
163 //	/* possibly more */
164 //	return regdomain == MKK9_MKKC;
165 //}
166 //
167 ///* Frequency is one where radar detection is required */
168 //static int ath_is_radar_freq(u16 center_freq)
169 //{
170 //	return (center_freq >= 5260 && center_freq <= 5700);
171 //}
172 //
173 ///*
174 // * N.B: These exception rules do not apply radar freqs.
175 // *
176 // * - We enable adhoc (or beaconing) if allowed by 11d
177 // * - We enable active scan if the channel is allowed by 11d
178 // * - If no country IE has been processed and a we determine we have
179 // *   received a beacon on a channel we can enable active scan and
180 // *   adhoc (or beaconing).
181 // */
182 //static void
183 //ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
184 //			      enum nl80211_reg_initiator initiator)
185 //{
186 //	int band;
187 //	struct ieee80211_supported_band *sband;
188 //	const struct ieee80211_reg_rule *reg_rule;
189 //	struct net80211_channel *ch;
190 //	unsigned int i;
191 //	u32 bandwidth = 0;
192 //	int r;
193 //
194 //	for (band = 0; band < NET80211_NR_BANDS; band++) {
195 //
196 //		if (!wiphy->bands[band])
197 //			continue;
198 //
199 //		sband = wiphy->bands[band];
200 //
201 //		for (i = 0; i < sband->n_channels; i++) {
202 //
203 //			ch = &sband->channels[i];
204 //
205 //			if (ath_is_radar_freq(ch->center_freq) ||
206 //			    (ch->flags & IEEE80211_CHAN_RADAR))
207 //				continue;
208 //
209 //			if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
210 //				r = freq_reg_info(wiphy,
211 //						  ch->center_freq,
212 //						  bandwidth,
213 //						  &reg_rule);
214 //				if (r)
215 //					continue;
216 //				/*
217 //				 * If 11d had a rule for this channel ensure
218 //				 * we enable adhoc/beaconing if it allows us to
219 //				 * use it. Note that we would have disabled it
220 //				 * by applying our static world regdomain by
221 //				 * default during init, prior to calling our
222 //				 * regulatory_hint().
223 //				 */
224 //				if (!(reg_rule->flags &
225 //				    NL80211_RRF_NO_IBSS))
226 //					ch->flags &=
227 //					  ~IEEE80211_CHAN_NO_IBSS;
228 //				if (!(reg_rule->flags &
229 //				    NL80211_RRF_PASSIVE_SCAN))
230 //					ch->flags &=
231 //					  ~IEEE80211_CHAN_PASSIVE_SCAN;
232 //			} else {
233 //				if (ch->beacon_found)
234 //					ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
235 //					  IEEE80211_CHAN_PASSIVE_SCAN);
236 //			}
237 //		}
238 //	}
239 //
240 //}
241 //
242 ///* Allows active scan scan on Ch 12 and 13 */
243 //static void
244 //ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
245 //				enum nl80211_reg_initiator initiator)
246 //{
247 //	struct ieee80211_supported_band *sband;
248 //	struct net80211_channel *ch;
249 //	const struct ieee80211_reg_rule *reg_rule;
250 //	u32 bandwidth = 0;
251 //	int r;
252 //
253 //	sband = wiphy->bands[NET80211_BAND_2GHZ];
254 //
255 //	/*
256 //	 * If no country IE has been received always enable active scan
257 //	 * on these channels. This is only done for specific regulatory SKUs
258 //	 */
259 //	if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
260 //		ch = &sband->channels[11]; /* CH 12 */
261 //		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
262 //			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
263 //		ch = &sband->channels[12]; /* CH 13 */
264 //		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
265 //			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
266 //		return;
267 //	}
268 //
269 //	/*
270 //	 * If a country IE has been received check its rule for this
271 //	 * channel first before enabling active scan. The passive scan
272 //	 * would have been enforced by the initial processing of our
273 //	 * custom regulatory domain.
274 //	 */
275 //
276 //	ch = &sband->channels[11]; /* CH 12 */
277 //	r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
278 //	if (!r) {
279 //		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
280 //			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
281 //				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
282 //	}
283 //
284 //	ch = &sband->channels[12]; /* CH 13 */
285 //	r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
286 //	if (!r) {
287 //		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
288 //			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
289 //				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
290 //	}
291 //}
292 //
293 ///* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
294 //static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
295 //{
296 //	struct ieee80211_supported_band *sband;
297 //	struct net80211_channel *ch;
298 //	unsigned int i;
299 //
300 //	if (!wiphy->bands[NET80211_BAND_5GHZ])
301 //		return;
302 //
303 //	sband = wiphy->bands[NET80211_BAND_5GHZ];
304 //
305 //	for (i = 0; i < sband->n_channels; i++) {
306 //		ch = &sband->channels[i];
307 //		if (!ath_is_radar_freq(ch->center_freq))
308 //			continue;
309 //		/* We always enable radar detection/DFS on this
310 //		 * frequency range. Additionally we also apply on
311 //		 * this frequency range:
312 //		 * - If STA mode does not yet have DFS supports disable
313 //		 *   active scanning
314 //		 * - If adhoc mode does not support DFS yet then
315 //		 *   disable adhoc in the frequency.
316 //		 * - If AP mode does not yet support radar detection/DFS
317 //		 *   do not allow AP mode
318 //		 */
319 //		if (!(ch->flags & IEEE80211_CHAN_DISABLED))
320 //			ch->flags |= IEEE80211_CHAN_RADAR |
321 //				     IEEE80211_CHAN_NO_IBSS |
322 //				     IEEE80211_CHAN_PASSIVE_SCAN;
323 //	}
324 //}
325 //
326 //static void ath_reg_apply_world_flags(struct wiphy *wiphy,
327 //				      enum nl80211_reg_initiator initiator,
328 //				      struct ath_regulatory *reg)
329 //{
330 //	switch (reg->regpair->regDmnEnum) {
331 //	case 0x60:
332 //	case 0x63:
333 //	case 0x66:
334 //	case 0x67:
335 //	case 0x6C:
336 //		ath_reg_apply_beaconing_flags(wiphy, initiator);
337 //		break;
338 //	case 0x68:
339 //		ath_reg_apply_beaconing_flags(wiphy, initiator);
340 //		ath_reg_apply_active_scan_flags(wiphy, initiator);
341 //		break;
342 //	}
343 //}
344 //
345 //int ath_reg_notifier_apply(struct wiphy *wiphy,
346 //			   struct regulatory_request *request,
347 //			   struct ath_regulatory *reg)
348 //{
349 //	/* We always apply this */
350 //	ath_reg_apply_radar_flags(wiphy);
351 //
352 //	/*
353 //	 * This would happen when we have sent a custom regulatory request
354 //	 * a world regulatory domain and the scheduler hasn't yet processed
355 //	 * any pending requests in the queue.
356 //	 */
357 //	if (!request)
358 //		return 0;
359 //
360 //	switch (request->initiator) {
361 //	case NL80211_REGDOM_SET_BY_DRIVER:
362 //	case NL80211_REGDOM_SET_BY_CORE:
363 //	case NL80211_REGDOM_SET_BY_USER:
364 //		break;
365 //	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
366 //		if (ath_is_world_regd(reg))
367 //			ath_reg_apply_world_flags(wiphy, request->initiator,
368 //						  reg);
369 //		break;
370 //	}
371 //
372 //	return 0;
373 //}
374 //
375 //static int ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
376 //{
377 //	u16 rd = ath_regd_get_eepromRD(reg);
378 //	int i;
379 //
380 //	if (rd & COUNTRY_ERD_FLAG) {
381 //		/* EEPROM value is a country code */
382 //		u16 cc = rd & ~COUNTRY_ERD_FLAG;
383 //		DBG2(
384 //		       "ath: EEPROM indicates we should expect "
385 //			"a country code\n");
386 //		for (i = 0; i < ARRAY_SIZE(allCountries); i++)
387 //			if (allCountries[i].countryCode == cc)
388 //				return 1;
389 //	} else {
390 //		/* EEPROM value is a regpair value */
391 //		if (rd != CTRY_DEFAULT)
392 //			DBG2("ath: EEPROM indicates we "
393 //			       "should expect a direct regpair map\n");
394 //		for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
395 //			if (regDomainPairs[i].regDmnEnum == rd)
396 //				return 1;
397 //	}
398 //	DBG(
399 //		 "ath: invalid regulatory domain/country code 0x%x\n", rd);
400 //	return 0;
401 //}
402 //
403 ///* EEPROM country code to regpair mapping */
404 //static struct country_code_to_enum_rd*
405 //ath_regd_find_country(u16 countryCode)
406 //{
407 //	int i;
408 //
409 //	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
410 //		if (allCountries[i].countryCode == countryCode)
411 //			return &allCountries[i];
412 //	}
413 //	return NULL;
414 //}
415 //
416 ///* EEPROM rd code to regpair mapping */
417 //static struct country_code_to_enum_rd*
418 //ath_regd_find_country_by_rd(int regdmn)
419 //{
420 //	int i;
421 //
422 //	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
423 //		if (allCountries[i].regDmnEnum == regdmn)
424 //			return &allCountries[i];
425 //	}
426 //	return NULL;
427 //}
428 //
429 ///* Returns the map of the EEPROM set RD to a country code */
430 //static u16 ath_regd_get_default_country(u16 rd)
431 //{
432 //	if (rd & COUNTRY_ERD_FLAG) {
433 //		struct country_code_to_enum_rd *country = NULL;
434 //		u16 cc = rd & ~COUNTRY_ERD_FLAG;
435 //
436 //		country = ath_regd_find_country(cc);
437 //		if (country != NULL)
438 //			return cc;
439 //	}
440 //
441 //	return CTRY_DEFAULT;
442 //}
443 //
444 //static struct reg_dmn_pair_mapping*
445 //ath_get_regpair(int regdmn)
446 //{
447 //	int i;
448 //
449 //	if (regdmn == NO_ENUMRD)
450 //		return NULL;
451 //	for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
452 //		if (regDomainPairs[i].regDmnEnum == regdmn)
453 //			return &regDomainPairs[i];
454 //	}
455 //	return NULL;
456 //}
457 //
458 //static int
459 //ath_regd_init_wiphy(struct ath_regulatory *reg,
460 //		    struct wiphy *wiphy,
461 //		    int (*reg_notifier)(struct wiphy *wiphy,
462 //					struct regulatory_request *request))
463 //{
464 //	const struct ieee80211_regdomain *regd;
465 //
466 //	wiphy->reg_notifier = reg_notifier;
467 //	wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
468 //
469 //	if (ath_is_world_regd(reg)) {
470 //		/*
471 //		 * Anything applied here (prior to wiphy registration) gets
472 //		 * saved on the wiphy orig_* parameters
473 //		 */
474 //		regd = ath_world_regdomain(reg);
475 //		wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
476 //	} else {
477 //		/*
478 //		 * This gets applied in the case of the absence of CRDA,
479 //		 * it's our own custom world regulatory domain, similar to
480 //		 * cfg80211's but we enable passive scanning.
481 //		 */
482 //		regd = ath_default_world_regdomain();
483 //	}
484 //	wiphy_apply_custom_regulatory(wiphy, regd);
485 //	ath_reg_apply_radar_flags(wiphy);
486 //	ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
487 //	return 0;
488 //}
489 //
490 ///*
491 // * Some users have reported their EEPROM programmed with
492 // * 0x8000 set, this is not a supported regulatory domain
493 // * but since we have more than one user with it we need
494 // * a solution for them. We default to 0x64, which is the
495 // * default Atheros world regulatory domain.
496 // */
497 //static void ath_regd_sanitize(struct ath_regulatory *reg)
498 //{
499 //	if (reg->current_rd != COUNTRY_ERD_FLAG)
500 //		return;
501 //	DBG2("ath: EEPROM regdomain sanitized\n");
502 //	reg->current_rd = 0x64;
503 //}
504 //
505 //int
506 //ath_regd_init(struct ath_regulatory *reg,
507 //	      struct wiphy *wiphy,
508 //	      int (*reg_notifier)(struct wiphy *wiphy,
509 //				  struct regulatory_request *request))
510 //{
511 //	struct country_code_to_enum_rd *country = NULL;
512 //	u16 regdmn;
513 //
514 //	if (!reg)
515 //		return -EINVAL;
516 //
517 //	ath_regd_sanitize(reg);
518 //
519 //	DBG2("ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
520 //
521 //	if (!ath_regd_is_eeprom_valid(reg)) {
522 //		DBG("ath: Invalid EEPROM contents\n");
523 //		return -EINVAL;
524 //	}
525 //
526 //	regdmn = ath_regd_get_eepromRD(reg);
527 //	reg->country_code = ath_regd_get_default_country(regdmn);
528 //
529 //	if (reg->country_code == CTRY_DEFAULT &&
530 //	    regdmn == CTRY_DEFAULT) {
531 //		DBG2("ath: EEPROM indicates default "
532 //		       "country code should be used\n");
533 //		reg->country_code = CTRY_UNITED_STATES;
534 //	}
535 //
536 //	if (reg->country_code == CTRY_DEFAULT) {
537 //		country = NULL;
538 //	} else {
539 //		DBG2("ath: doing EEPROM country->regdmn "
540 //		       "map search\n");
541 //		country = ath_regd_find_country(reg->country_code);
542 //		if (country == NULL) {
543 //			DBG(
544 //				"ath: no valid country maps found for "
545 //				"country code: 0x%0x\n",
546 //				reg->country_code);
547 //			return -EINVAL;
548 //		} else {
549 //			regdmn = country->regDmnEnum;
550 //			DBG2("ath: country maps to "
551 //			       "regdmn code: 0x%0x\n",
552 //			       regdmn);
553 //		}
554 //	}
555 //
556 //	reg->regpair = ath_get_regpair(regdmn);
557 //
558 //	if (!reg->regpair) {
559 //		DBG("ath: "
560 //			"No regulatory domain pair found, cannot continue\n");
561 //		return -EINVAL;
562 //	}
563 //
564 //	if (!country)
565 //		country = ath_regd_find_country_by_rd(regdmn);
566 //
567 //	if (country) {
568 //		reg->alpha2[0] = country->isoName[0];
569 //		reg->alpha2[1] = country->isoName[1];
570 //	} else {
571 //		reg->alpha2[0] = '0';
572 //		reg->alpha2[1] = '0';
573 //	}
574 //
575 //	DBG2("ath: Country alpha2 being used: %c%c\n",
576 //		reg->alpha2[0], reg->alpha2[1]);
577 //	DBG2("ath: Regpair used: 0x%0x\n",
578 //		reg->regpair->regDmnEnum);
579 //
580 //	ath_regd_init_wiphy(reg, wiphy, reg_notifier);
581 //	return 0;
582 //}
583 
ath_regd_get_band_ctl(struct ath_regulatory * reg,int band)584 u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
585 			  int band)
586 {
587 	/* TODO Cottsay: reg */
588 //	if (!reg->regpair ||
589 //	    (reg->country_code == CTRY_DEFAULT &&
590 //	     is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
591 //		return SD_NO_CTL;
592 //	}
593 
594 	switch (band) {
595 	case NET80211_BAND_2GHZ:
596 		return reg->regpair->reg_2ghz_ctl;
597 	case NET80211_BAND_5GHZ:
598 		return reg->regpair->reg_5ghz_ctl;
599 	default:
600 		return NO_CTL;
601 	}
602 }
603