/* * Return whether or not the regulatory domain/country in EEPROM * is acceptable. */ static HAL_BOOL isEepromValid(struct ath_hal *ah) { uint16_t rd = getEepromRD(ah); int i; if (rd & COUNTRY_ERD_FLAG) { uint16_t cc = rd &~ COUNTRY_ERD_FLAG; for (i = 0; i < N(allCountries); i++) if (allCountries[i].countryCode == cc) return AH_TRUE; } else { for (i = 0; i < N(regDomainPairs); i++) if (regDomainPairs[i].regDmnEnum == rd) return AH_TRUE; } if (rd == FCC_UBNT) { return AH_TRUE; } HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd); return AH_FALSE; }
/* * Calculate a default country based on the EEPROM setting. */ static HAL_CTRY_CODE getDefaultCountry(struct ath_hal *ah) { REG_DMN_PAIR_MAPPING *regpair; uint16_t rd; rd = getEepromRD(ah); if (rd & COUNTRY_ERD_FLAG) { COUNTRY_CODE_TO_ENUM_RD *country; uint16_t cc = rd & ~COUNTRY_ERD_FLAG; country = findCountry(cc); if (country != AH_NULL) return cc; } /* * Check reg domains that have only one country */ regpair = findRegDmnPair(rd); return (regpair != AH_NULL) ? regpair->singleCC : CTRY_DEFAULT; }
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) { COUNTRY_CODE_TO_ENUM_RD *country; REG_DOMAIN *rd5GHz, *rd2GHz; if (cc == CTRY_DEFAULT && regDmn == SKU_NONE) { /* * Validate the EEPROM setting and setup defaults */ if (!isEepromValid(ah)) { /* * Don't return any channels if the EEPROM has an * invalid regulatory domain/country code setting. */ HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: invalid EEPROM contents\n",__func__); return HAL_EEBADREG; } cc = getDefaultCountry(ah); country = findCountry(cc); if (country == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "NULL Country!, cc %d\n", cc); return HAL_EEBADCC; } regDmn = country->regDmnEnum; HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: EEPROM cc %u rd 0x%x\n", __func__, cc, regDmn); if (country->countryCode == CTRY_DEFAULT) { /* * Check EEPROM; SKU may be for a country, single * domain, or multiple domains (WWR). */ uint16_t rdnum = getEepromRD(ah); if ((rdnum & COUNTRY_ERD_FLAG) == 0 && (findRegDmn(rdnum) != AH_NULL || findRegDmnPair(rdnum) != AH_NULL)) { regDmn = rdnum; HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: EEPROM rd 0x%x\n", __func__, rdnum); } } } else { country = findCountry(cc); if (country == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "unknown country, cc %d\n", cc); return HAL_EINVAL; } if (regDmn == SKU_NONE) regDmn = country->regDmnEnum; HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u rd 0x%x\n", __func__, cc, regDmn); } /* * Setup per-band state. */ if ((regDmn & MULTI_DOMAIN_MASK) == 0) { REG_DMN_PAIR_MAPPING *regpair = findRegDmnPair(regDmn); if (regpair == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: no reg domain pair %u for country %u\n", __func__, regDmn, country->countryCode); return HAL_EINVAL; } rd5GHz = findRegDmn(regpair->regDmn5GHz); if (rd5GHz == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: no 5GHz reg domain %u for country %u\n", __func__, regpair->regDmn5GHz, country->countryCode); return HAL_EINVAL; } rd2GHz = findRegDmn(regpair->regDmn2GHz); if (rd2GHz == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: no 2GHz reg domain %u for country %u\n", __func__, regpair->regDmn2GHz, country->countryCode); return HAL_EINVAL; } } else { rd5GHz = rd2GHz = findRegDmn(regDmn); if (rd2GHz == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: no unitary reg domain %u for country %u\n", __func__, regDmn, country->countryCode); return HAL_EINVAL; } } if (pcountry != AH_NULL) *pcountry = country; *prd2GHz = rd2GHz; *prd5GHz = rd5GHz; return HAL_OK; }