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 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 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 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* 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 * 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 * 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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