/*
 * 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;
}
示例#2
0
/*
 * 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;
}
示例#3
0
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;
}