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