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