static inline void ar9300_init_rate_txpower_cck(struct ath_hal *ah, const HAL_RATE_TABLE *rt, u_int8_t rates_array[], u_int8_t chainmask) { struct ath_hal_9300 *ahp = AH9300(ah); /* * Pick the lower of the long-preamble txpower, and short-preamble tx power. * Unfortunately, the rate table doesn't have separate entries for these!. */ switch (chainmask) { case OSPREY_1_CHAINMASK: ahp->txpower[0][0] = rates_array[ALL_TARGET_LEGACY_1L_5L]; ahp->txpower[1][0] = rates_array[ALL_TARGET_LEGACY_1L_5L]; ahp->txpower[2][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L], rates_array[ALL_TARGET_LEGACY_5S]); ahp->txpower[3][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L], rates_array[ALL_TARGET_LEGACY_11S]); break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: ahp->txpower[0][1] = rates_array[ALL_TARGET_LEGACY_1L_5L]; ahp->txpower[1][1] = rates_array[ALL_TARGET_LEGACY_1L_5L]; ahp->txpower[2][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L], rates_array[ALL_TARGET_LEGACY_5S]); ahp->txpower[3][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L], rates_array[ALL_TARGET_LEGACY_11S]); break; case OSPREY_3_CHAINMASK: ahp->txpower[0][2] = rates_array[ALL_TARGET_LEGACY_1L_5L]; ahp->txpower[1][2] = rates_array[ALL_TARGET_LEGACY_1L_5L]; ahp->txpower[2][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L], rates_array[ALL_TARGET_LEGACY_5S]); ahp->txpower[3][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L], rates_array[ALL_TARGET_LEGACY_11S]); break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } }
/* * Sets the transmit power in the baseband for the given * operating channel and mode. */ static HAL_BOOL setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan, int16_t tpcScaleReduction, int16_t powerLimit, int16_t *pMinPower, int16_t *pMaxPower) { u_int16_t ratesArray[16]; u_int16_t *rpow = ratesArray; u_int16_t twiceMaxRDPower, twiceMaxEdgePower, twiceMaxEdgePowerCck; int8_t twiceAntennaGain, twiceAntennaReduction; TRGT_POWER_INFO targetPowerOfdm, targetPowerCck; RD_EDGES_POWER *rep; int16_t scaledPower; u_int8_t cfgCtl; twiceMaxRDPower = chan->ic_maxregpower * 2; *pMaxPower = -MAX_RATE_POWER; *pMinPower = MAX_RATE_POWER; /* Get conformance test limit maximum for this channel */ cfgCtl = ath_hal_getctl(ah, chan); rep = findEdgePower(ah, cfgCtl); if (rep != AH_NULL) twiceMaxEdgePower = ar5212GetMaxEdgePower(chan->ic_freq, rep); else twiceMaxEdgePower = MAX_RATE_POWER; if (IEEE80211_IS_CHAN_G(chan)) { /* Check for a CCK CTL for 11G CCK powers */ cfgCtl = (cfgCtl & 0xFC) | 0x01; rep = findEdgePower(ah, cfgCtl); if (rep != AH_NULL) twiceMaxEdgePowerCck = ar5212GetMaxEdgePower(chan->ic_freq, rep); else twiceMaxEdgePowerCck = MAX_RATE_POWER; } else { /* Set the 11B cck edge power to the one found before */ twiceMaxEdgePowerCck = twiceMaxEdgePower; } /* Get Antenna Gain reduction */ if (IEEE80211_IS_CHAN_5GHZ(chan)) { twiceAntennaGain = antennaGainMax[0]; } else { twiceAntennaGain = antennaGainMax[1]; } twiceAntennaReduction = ath_hal_getantennareduction(ah, chan, twiceAntennaGain); if (IEEE80211_IS_CHAN_OFDM(chan)) { /* Get final OFDM target powers */ if (IEEE80211_IS_CHAN_G(chan)) { /* TODO - add Turbo 2.4 to this mode check */ ar5212GetTargetPowers(ah, chan, trgtPwr_11g, numTargetPwr_11g, &targetPowerOfdm); } else { ar5212GetTargetPowers(ah, chan, trgtPwr_11a, numTargetPwr_11a, &targetPowerOfdm); } /* Get Maximum OFDM power */ /* Minimum of target and edge powers */ scaledPower = AH_MIN(twiceMaxEdgePower, twiceMaxRDPower - twiceAntennaReduction); /* * If turbo is set, reduce power to keep power * consumption under 2 Watts. Note that we always do * this unless specially configured. Then we limit * power only for non-AP operation. */ if (IEEE80211_IS_CHAN_TURBO(chan) #ifdef AH_ENABLE_AP_SUPPORT && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP #endif ) { /* * If turbo is set, reduce power to keep power * consumption under 2 Watts */ if (eeversion >= AR_EEPROM_VER3_1) scaledPower = AH_MIN(scaledPower, turbo2WMaxPower5); /* * EEPROM version 4.0 added an additional * constraint on 2.4GHz channels. */ if (eeversion >= AR_EEPROM_VER4_0 && IEEE80211_IS_CHAN_2GHZ(chan)) scaledPower = AH_MIN(scaledPower, turbo2WMaxPower2); } /* Reduce power by max regulatory domain allowed restrictions */ scaledPower -= (tpcScaleReduction * 2); scaledPower = (scaledPower < 0) ? 0 : scaledPower; scaledPower = AH_MIN(scaledPower, powerLimit); scaledPower = AH_MIN(scaledPower, targetPowerOfdm.twicePwr6_24); /* Set OFDM rates 9, 12, 18, 24, 36, 48, 54, XR */ rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower; rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36); rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48); rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54); #ifdef notyet if (eeversion >= AR_EEPROM_VER4_0) { /* Setup XR target power from EEPROM */ rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ? xrTargetPower2 : xrTargetPower5); } else { /* XR uses 6mb power */ rpow[15] = rpow[0]; } #else rpow[15] = rpow[0]; #endif *pMinPower = rpow[7]; *pMaxPower = rpow[0]; #if 0 ahp->ah_ofdmTxPower = rpow[0]; #endif HALDEBUG(ah, HAL_DEBUG_ANY, "%s: MaxRD: %d TurboMax: %d MaxCTL: %d " "TPC_Reduction %d\n", __func__, twiceMaxRDPower, turbo2WMaxPower5, twiceMaxEdgePower, tpcScaleReduction * 2); } if (IEEE80211_IS_CHAN_CCK(chan)) { /* Get final CCK target powers */ ar5212GetTargetPowers(ah, chan, trgtPwr_11b, numTargetPwr_11b, &targetPowerCck); /* Reduce power by max regulatory domain allowed restrictions */ scaledPower = AH_MIN(twiceMaxEdgePowerCck, twiceMaxRDPower - twiceAntennaReduction); scaledPower -= (tpcScaleReduction * 2); scaledPower = (scaledPower < 0) ? 0 : scaledPower; scaledPower = AH_MIN(scaledPower, powerLimit); rpow[8] = (scaledPower < 1) ? 1 : scaledPower; /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */ rpow[8] = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24); rpow[9] = AH_MIN(scaledPower, targetPowerCck.twicePwr36); rpow[10] = rpow[9]; rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48); rpow[12] = rpow[11]; rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54); rpow[14] = rpow[13]; /* Set min/max power based off OFDM values or initialization */ if (rpow[13] < *pMinPower) *pMinPower = rpow[13]; if (rpow[9] > *pMaxPower) *pMaxPower = rpow[9]; } #if 0 ahp->ah_tx6PowerInHalfDbm = *pMaxPower; #endif return AH_TRUE; }
static inline void ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, const HAL_RATE_TABLE *rt, HAL_BOOL is40, int rt_ss_offset, int rt_ds_offset, int rt_ts_offset, u_int8_t chainmask) { struct ath_hal_9300 *ahp = AH9300(ah); int i; int16_t twice_array_gain, cdd_power = 0; u_int8_t mcs_index = 0; /* * Adjust the upper limit for CDD factoring in the array gain . * The array gain is the same as TxBF, hence reuse the same defines. */ switch (chainmask) { case OSPREY_1_CHAINMASK: cdd_power = ahp->upper_limit[0]; break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? -(AR9300_TXBF_2TX_ARRAY_GAIN) : ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0)); cdd_power = ahp->upper_limit[1] + twice_array_gain; break; case OSPREY_3_CHAINMASK: twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? -(AR9300_TXBF_3TX_ARRAY_GAIN) : ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0)); cdd_power = ahp->upper_limit[2] + twice_array_gain; break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) { switch (chainmask) { case OSPREY_1_CHAINMASK: break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: /* 2 TX/1 stream CDD gain adjustment */ if (ahp->txpower[i][1] > cdd_power){ ahp->txpower[i][1] = cdd_power; } break; case OSPREY_3_CHAINMASK: /* 3 TX/1 stream CDD gain adjustment */ if (ahp->txpower[i][2] > cdd_power){ ahp->txpower[i][2] = cdd_power; } break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } mcs_index++; } for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) { switch (chainmask) { case OSPREY_1_CHAINMASK: case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: break; case OSPREY_3_CHAINMASK: /* 3 TX/2 stream TxBF gain adjustment */ if (ahp->txpower[i][2] > cdd_power){ ahp->txpower[i][2] = cdd_power; } break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } mcs_index++; } return; }
static inline void ar9300_init_rate_txpower_stbc(struct ath_hal *ah, const HAL_RATE_TABLE *rt, HAL_BOOL is40, int rt_ss_offset, int rt_ds_offset, int rt_ts_offset, u_int8_t chainmask) { struct ath_hal_9300 *ahp = AH9300(ah); int i; int16_t twice_array_gain, stbc_power = 0; u_int8_t mcs_index = 0; /* Upper Limit with STBC */ switch (chainmask) { case OSPREY_1_CHAINMASK: stbc_power = ahp->upper_limit[0]; break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: stbc_power = ahp->upper_limit[1]; break; case OSPREY_3_CHAINMASK: stbc_power = ahp->upper_limit[2]; /* Ony FCC requires that we back off with 3 transmit chains */ if (is_reg_dmn_fcc(ahp->reg_dmn)) { twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? -(AR9300_STBC_3TX_ARRAY_GAIN) : ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_STBC_3TX_ARRAY_GAIN)), 0)); stbc_power = ahp->upper_limit[2] + twice_array_gain; } break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) { switch (chainmask) { case OSPREY_1_CHAINMASK: ahp->txpower_stbc[i][0] = ahp->txpower[i][0]; break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: ahp->txpower_stbc[i][1] = ahp->txpower[i][1]; break; case OSPREY_3_CHAINMASK: ahp->txpower_stbc[i][2] = ahp->txpower[i][2]; /* 3 TX/1 stream STBC gain adjustment */ if (ahp->txpower_stbc[i][2] > stbc_power){ ahp->txpower_stbc[i][2] = stbc_power; } break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } mcs_index++; } for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) { switch (chainmask) { case OSPREY_1_CHAINMASK: ahp->txpower_stbc[i][0] = ahp->txpower[i][0]; break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: ahp->txpower_stbc[i][1] = ahp->txpower[i][1]; break; case OSPREY_3_CHAINMASK: ahp->txpower_stbc[i][2] = ahp->txpower[i][2]; /* 3 TX/2 stream STBC gain adjustment */ if (ahp->txpower_stbc[i][2] > stbc_power){ ahp->txpower_stbc[i][2] = stbc_power; } break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } mcs_index++; } for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) { switch (chainmask) { case OSPREY_1_CHAINMASK: ahp->txpower_stbc[i][0] = ahp->txpower[i][0]; break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: ahp->txpower_stbc[i][1] = ahp->txpower[i][1]; break; case OSPREY_3_CHAINMASK: ahp->txpower_stbc[i][2] = ahp->txpower[i][2]; break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } mcs_index++; } return; }
static inline void ar9300_init_rate_txpower_ofdm(struct ath_hal *ah, const HAL_RATE_TABLE *rt, u_int8_t rates_array[], int rt_offset, u_int8_t chainmask) { struct ath_hal_9300 *ahp = AH9300(ah); int16_t twice_array_gain, cdd_power = 0; int i, j; u_int8_t ofdm_rt_2_pwr_idx[8] = { ALL_TARGET_LEGACY_6_24, ALL_TARGET_LEGACY_6_24, ALL_TARGET_LEGACY_6_24, ALL_TARGET_LEGACY_6_24, ALL_TARGET_LEGACY_6_24, ALL_TARGET_LEGACY_36, ALL_TARGET_LEGACY_48, ALL_TARGET_LEGACY_54, }; /* * For FCC adjust the upper limit for CDD factoring in the array gain. * The array gain is the same as TxBF, hence reuse the same defines. */ for (i = rt_offset; i < rt_offset + AR9300_NUM_OFDM_RATES; i++) { /* Get the correct OFDM rate to Power table Index */ j = ofdm_rt_2_pwr_idx[i- rt_offset]; switch (chainmask) { case OSPREY_1_CHAINMASK: ahp->txpower[i][0] = rates_array[j]; break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: ahp->txpower[i][1] = rates_array[j]; if (is_reg_dmn_fcc(ahp->reg_dmn)){ twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? -(AR9300_TXBF_2TX_ARRAY_GAIN) : ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0)); cdd_power = ahp->upper_limit[1] + twice_array_gain; if (ahp->txpower[i][1] > cdd_power){ ahp->txpower[i][1] = cdd_power; } } break; case OSPREY_3_CHAINMASK: ahp->txpower[i][2] = rates_array[j]; if (is_reg_dmn_fcc(ahp->reg_dmn)) { twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? -(AR9300_TXBF_3TX_ARRAY_GAIN): ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0)); cdd_power = ahp->upper_limit[2] + twice_array_gain; if (ahp->txpower[i][2] > cdd_power){ ahp->txpower[i][2] = cdd_power; } } break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, chainmask); break; } } }
extern void ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah, u_int8_t power_per_rate[]) { struct ath_hal_9300 *ahp = AH9300(ah); int16_t twice_array_gain, cdd_power = 0; int i; /* * Adjust the upper limit for CDD factoring in the array gain . * The array gain is the same as TxBF, hence reuse the same defines. */ switch (ahp->ah_tx_chainmask) { case OSPREY_1_CHAINMASK: cdd_power = ahp->upper_limit[0]; break; case OSPREY_2LOHI_CHAINMASK: case OSPREY_2LOMID_CHAINMASK: twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? -(AR9300_TXBF_2TX_ARRAY_GAIN) : ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0)); cdd_power = ahp->upper_limit[1] + twice_array_gain; /* Adjust OFDM legacy rates as well */ for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) { if (power_per_rate[i] > cdd_power) { power_per_rate[i] = cdd_power; } } /* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7 HT 20*/ for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_7; i++) { if (power_per_rate[i] > cdd_power) { power_per_rate[i] = cdd_power; } } /* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7 HT 40*/ for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_7; i++) { if (power_per_rate[i] > cdd_power) { power_per_rate[i] = cdd_power; } } break; case OSPREY_3_CHAINMASK: twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? -(AR9300_TXBF_3TX_ARRAY_GAIN) : ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0)); cdd_power = ahp->upper_limit[2] + twice_array_gain; /* Adjust OFDM legacy rates as well */ for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) { if (power_per_rate[i] > cdd_power) { power_per_rate[i] = cdd_power; } } /* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT20 */ for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_15; i++) { if (power_per_rate[i] > cdd_power) { power_per_rate[i] = cdd_power; } } /* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT40 */ for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_15; i++) { if (power_per_rate[i] > cdd_power) { power_per_rate[i] = cdd_power; } } break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", __func__, ahp->ah_tx_chainmask); break; } return; }
HAL_STATUS ath_hal_v4kEepromAttach(struct ath_hal *ah) { #define NW(a) (sizeof(a) / sizeof(uint16_t)) HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; uint16_t *eep_data, magic; HAL_BOOL need_swap; u_int w, off, len; uint32_t sum; HALASSERT(ee == AH_NULL); /* * Don't check magic if we're supplied with an EEPROM block, * typically this is from Howl but it may also be from later * boards w/ an embedded WMAC. */ if (ah->ah_eepromdata == NULL) { if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s Error reading Eeprom MAGIC\n", __func__); return HAL_EEREAD; } } HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n", __func__, magic); if (magic != AR5416_EEPROM_MAGIC) { HALDEBUG(ah, HAL_DEBUG_ANY, "Bad magic number\n"); return HAL_EEMAGIC; } ee = ath_hal_malloc(sizeof(HAL_EEPROM_v4k)); if (ee == AH_NULL) { /* XXX message */ return HAL_ENOMEM; } eep_data = (uint16_t *)&ee->ee_base; for (w = 0; w < NW(struct ar5416eeprom_4k); w++) { off = owl_eep_start_loc + w; /* NB: AP71 starts at 0 */ if (!ath_hal_eepromRead(ah, off, &eep_data[w])) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s eeprom read error at offset 0x%x\n", __func__, off); return HAL_EEREAD; } } /* Convert to eeprom native eeprom endian format */ /* * XXX this is likely incorrect but will do for now * XXX to get embedded boards working. */ if (ah->ah_eepromdata == NULL && isBigEndian()) { for (w = 0; w < NW(struct ar5416eeprom_4k); w++) eep_data[w] = __bswap16(eep_data[w]); } /* * At this point, we're in the native eeprom endian format * Now, determine the eeprom endian by looking at byte 26?? */ need_swap = ((ee->ee_base.baseEepHeader.eepMisc & AR5416_EEPMISC_BIG_ENDIAN) != 0) ^ isBigEndian(); if (need_swap) { HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, "Byte swap EEPROM contents.\n"); len = __bswap16(ee->ee_base.baseEepHeader.length); } else { len = ee->ee_base.baseEepHeader.length; } len = AH_MIN(len, sizeof(struct ar5416eeprom_4k)) / sizeof(uint16_t); /* Apply the checksum, done in native eeprom format */ /* XXX - Need to check to make sure checksum calculation is done * in the correct endian format. Right now, it seems it would * cast the raw data to host format and do the calculation, which may * not be correct as the calculation may need to be done in the native * eeprom format */ sum = 0; for (w = 0; w < len; w++) { sum ^= eep_data[w]; } /* Check CRC - Attach should fail on a bad checksum */ if (sum != 0xffff) { HALDEBUG(ah, HAL_DEBUG_ANY, "Bad EEPROM checksum 0x%x (Len=%u)\n", sum, len); return HAL_EEBADSUM; } if (need_swap) eepromSwap(&ee->ee_base); /* byte swap multi-byte data */ /* swap words 0+2 so version is at the front */ magic = eep_data[0]; eep_data[0] = eep_data[2]; eep_data[2] = magic; HALDEBUG(ah, HAL_DEBUG_ATTACH | HAL_DEBUG_EEPROM, "%s Eeprom Version %u.%u\n", __func__, owl_get_eep_ver(ee), owl_get_eep_rev(ee)); /* NB: must be after all byte swapping */ if (owl_get_eep_ver(ee) != AR5416_EEP_VER) { HALDEBUG(ah, HAL_DEBUG_ANY, "Bad EEPROM version 0x%x\n", owl_get_eep_ver(ee)); return HAL_EEBADSUM; } v4kEepromReadCTLInfo(ah, ee); /* Get CTLs */ AH_PRIVATE(ah)->ah_eeprom = ee; AH_PRIVATE(ah)->ah_eeversion = ee->ee_base.baseEepHeader.version; AH_PRIVATE(ah)->ah_eepromDetach = v4kEepromDetach; AH_PRIVATE(ah)->ah_eepromGet = v4kEepromGet; AH_PRIVATE(ah)->ah_eepromSet = v4kEepromSet; AH_PRIVATE(ah)->ah_getSpurChan = v4kEepromGetSpurChan; AH_PRIVATE(ah)->ah_eepromDiag = v4kEepromDiag; return HAL_OK; #undef NW }
void ar5416Set11nRateScenario(struct ath_hal *ah, void *ds, void *lastds, u_int dur_update_en, u_int rts_cts_rate, u_int rts_cts_duration, HAL_11N_RATE_SERIES series[], u_int nseries, u_int flags, u_int32_t smartAntenna) #endif { struct ath_hal_private *ap = AH_PRIVATE(ah); struct ar5416_desc *ads = AR5416DESC(ds); struct ar5416_desc *last_ads = AR5416DESC(lastds); u_int32_t ds_ctl0; u_int mode; HALASSERT(nseries == 4); (void)nseries; (void)rts_cts_duration; /* use H/W to calculate RTSCTSDuration */ /* * Rate control settings override */ ds_ctl0 = ads->ds_ctl0; if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) { if (flags & HAL_TXDESC_RTSENA) { ds_ctl0 &= ~AR_CTSEnable; ds_ctl0 |= AR_RTSEnable; } else { ds_ctl0 &= ~AR_RTSEnable; ds_ctl0 |= AR_CTSEnable; } } else { ds_ctl0 = (ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); } mode = ath_hal_get_curmode(ah, ap->ah_curchan); if (ap->ah_config.ath_hal_desc_tpc) { int16_t txpower; txpower = ar5416GetRateTxPower(ah, mode, series[0].rate_index, series[0].ch_sel); if(series[0].tx_power_cap == 0) { /*For short range mode, set txpower to MAX to put series[0].TxPowerCap into the descriptor*/ txpower = HAL_TXPOWER_MAX; } ds_ctl0 &= ~AR_XmitPower0; if (AR_SREV_MERLIN_10_OR_LATER(ah)) { u_int count; for (count=0; count < nseries; count++) { series[count].tx_power_cap -= AR5416_PWR_TABLE_OFFSET_DB * 2; } } ds_ctl0 |= set11nTxPower(0, AH_MIN(txpower, series[0].tx_power_cap)); } ads->ds_ctl0 = ds_ctl0; ads->ds_ctl2 = set11nTries(series, 0) | set11nTries(series, 1) | set11nTries(series, 2) | set11nTries(series, 3) | (dur_update_en ? AR_DurUpdateEna : 0) | SM(0, AR_BurstDur); ads->ds_ctl3 = set11nRate(series, 0) | set11nRate(series, 1) | set11nRate(series, 2) | set11nRate(series, 3); ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) | set11nPktDurRTSCTS(series, 1); ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) | set11nPktDurRTSCTS(series, 3); ads->ds_ctl7 = set11nRateFlags(series, 0) | set11nRateFlags(series, 1) | set11nRateFlags(series, 2) | set11nRateFlags(series, 3) | SM(rts_cts_rate, AR_RTSCTSRate); if (ap->ah_config.ath_hal_desc_tpc && AR_SREV_OWL_20_OR_LATER(ah)) { int16_t txpower; txpower = ar5416GetRateTxPower( ah, mode, series[1].rate_index, series[1].ch_sel); ads->ds_ctl9 = set11nTxPower(1, AH_MIN(txpower, series[1].tx_power_cap)); txpower = ar5416GetRateTxPower( ah, mode, series[2].rate_index, series[2].ch_sel); ads->ds_ctl10 = set11nTxPower(2, AH_MIN(txpower, series[2].tx_power_cap)); txpower = ar5416GetRateTxPower( ah, mode, series[3].rate_index, series[3].ch_sel); ads->ds_ctl11 = set11nTxPower(3, AH_MIN(txpower, series[3].tx_power_cap)); } #ifdef AH_NEED_DESC_SWAP last_ads->ds_ctl2 = __bswap32(ads->ds_ctl2); last_ads->ds_ctl3 = __bswap32(ads->ds_ctl3); #else last_ads->ds_ctl2 = ads->ds_ctl2; last_ads->ds_ctl3 = ads->ds_ctl3; #endif }