⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iwl-3945.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 {51, 118},	 {51, 111},	 {51, 104},	 {51, 98},	 {19, 116},	 {19, 109},	 {19, 102},	 {19, 98},	 {19, 93},	 {171, 113},	 {171, 107},	 {171, 99},	 {139, 120},	 {139, 113},	 {139, 107},	 {139, 99},	 {107, 120},	 {107, 113},	 {107, 107},	 {107, 99},	 {75, 120},	 {75, 113},	 {75, 107},	 {75, 99},	 {43, 120},	 {43, 113},	 {43, 107},	 {43, 99},	 {11, 120},	 {11, 113},	 {11, 107},	 {11, 99},	 {131, 107},	 {131, 99},	 {99, 120},	 {99, 113},	 {99, 107},	 {99, 99},	 {67, 120},	 {67, 113},	 {67, 107},	 {67, 99},	 {35, 120},	 {35, 113},	 {35, 107},	 {35, 99},	 {3, 120} }		/* 5.x GHz, lowest power */};static inline u8 iwl_hw_reg_fix_power_index(int index){	if (index < 0)		return 0;	if (index >= IWL_MAX_GAIN_ENTRIES)		return IWL_MAX_GAIN_ENTRIES - 1;	return (u8) index;}/* Kick off thermal recalibration check every 60 seconds */#define REG_RECALIB_PERIOD (60)/** * iwl_hw_reg_set_scan_power - Set Tx power for scan probe requests * * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK) * or 6 Mbit (OFDM) rates. */static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,			       s32 rate_index, const s8 *clip_pwrs,			       struct iwl_channel_info *ch_info,			       int band_index){	struct iwl_scan_power_info *scan_power_info;	s8 power;	u8 power_index;	scan_power_info = &ch_info->scan_pwr_info[scan_tbl_index];	/* use this channel group's 6Mbit clipping/saturation pwr,	 *   but cap at regulatory scan power restriction (set during init	 *   based on eeprom channel data) for this channel.  */	power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]);	/* further limit to user's max power preference.	 * FIXME:  Other spectrum management power limitations do not	 *   seem to apply?? */	power = min(power, priv->user_txpower_limit);	scan_power_info->requested_power = power;	/* find difference between new scan *power* and current "normal"	 *   Tx *power* for 6Mb.  Use this difference (x2) to adjust the	 *   current "normal" temperature-compensated Tx power *index* for	 *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power	 *   *index*. */	power_index = ch_info->power_info[rate_index].power_table_index	    - (power - ch_info->power_info	       [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2;	/* store reference index that we use when adjusting *all* scan	 *   powers.  So we can accommodate user (all channel) or spectrum	 *   management (single channel) power changes "between" temperature	 *   feedback compensation procedures.	 * don't force fit this reference index into gain table; it may be a	 *   negative number.  This will help avoid errors when we're at	 *   the lower bounds (highest gains, for warmest temperatures)	 *   of the table. */	/* don't exceed table bounds for "real" setting */	power_index = iwl_hw_reg_fix_power_index(power_index);	scan_power_info->power_table_index = power_index;	scan_power_info->tpc.tx_gain =	    power_gain_table[band_index][power_index].tx_gain;	scan_power_info->tpc.dsp_atten =	    power_gain_table[band_index][power_index].dsp_atten;}/** * iwl_hw_reg_send_txpower - fill in Tx Power command with gain settings * * Configures power settings for all rates for the current channel, * using values from channel info struct, and send to NIC */int iwl_hw_reg_send_txpower(struct iwl_priv *priv){	int rate_idx, i;	const struct iwl_channel_info *ch_info = NULL;	struct iwl_txpowertable_cmd txpower = {		.channel = priv->active_rxon.channel,	};	txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1;	ch_info = iwl_get_channel_info(priv,				       priv->phymode,				       le16_to_cpu(priv->active_rxon.channel));	if (!ch_info) {		IWL_ERROR		    ("Failed to get channel info for channel %d [%d]\n",		     le16_to_cpu(priv->active_rxon.channel), priv->phymode);		return -EINVAL;	}	if (!is_channel_valid(ch_info)) {		IWL_DEBUG_POWER("Not calling TX_PWR_TABLE_CMD on "				"non-Tx channel.\n");		return 0;	}	/* fill cmd with power settings for all rates for current channel */	/* Fill OFDM rate */	for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;	     rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) {		txpower.power[i].tpc = ch_info->power_info[i].tpc;		txpower.power[i].rate = iwl_rates[rate_idx].plcp;		IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",				le16_to_cpu(txpower.channel),				txpower.band,				txpower.power[i].tpc.tx_gain,				txpower.power[i].tpc.dsp_atten,				txpower.power[i].rate);	}	/* Fill CCK rates */	for (rate_idx = IWL_FIRST_CCK_RATE;	     rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {		txpower.power[i].tpc = ch_info->power_info[i].tpc;		txpower.power[i].rate = iwl_rates[rate_idx].plcp;		IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",				le16_to_cpu(txpower.channel),				txpower.band,				txpower.power[i].tpc.tx_gain,				txpower.power[i].tpc.dsp_atten,				txpower.power[i].rate);	}	return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,			sizeof(struct iwl_txpowertable_cmd), &txpower);}/** * iwl_hw_reg_set_new_power - Configures power tables at new levels * @ch_info: Channel to update.  Uses power_info.requested_power. * * Replace requested_power and base_power_index ch_info fields for * one channel. * * Called if user or spectrum management changes power preferences. * Takes into account h/w and modulation limitations (clip power). * * This does *not* send anything to NIC, just sets up ch_info for one channel. * * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to *	 properly fill out the scan powers, and actual h/w gain settings, *	 and send changes to NIC */static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,			     struct iwl_channel_info *ch_info){	struct iwl_channel_power_info *power_info;	int power_changed = 0;	int i;	const s8 *clip_pwrs;	int power;	/* Get this chnlgrp's rate-to-max/clip-powers table */	clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers;	/* Get this channel's rate-to-current-power settings table */	power_info = ch_info->power_info;	/* update OFDM Txpower settings */	for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE;	     i++, ++power_info) {		int delta_idx;		/* limit new power to be no more than h/w capability */		power = min(ch_info->curr_txpow, clip_pwrs[i]);		if (power == power_info->requested_power)			continue;		/* find difference between old and new requested powers,		 *    update base (non-temp-compensated) power index */		delta_idx = (power - power_info->requested_power) * 2;		power_info->base_power_index -= delta_idx;		/* save new requested power value */		power_info->requested_power = power;		power_changed = 1;	}	/* update CCK Txpower settings, based on OFDM 12M setting ...	 *    ... all CCK power settings for a given channel are the *same*. */	if (power_changed) {		power =		    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].		    requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;		/* do all CCK rates' iwl_channel_power_info structures */		for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {			power_info->requested_power = power;			power_info->base_power_index =			    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].			    base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF;			++power_info;		}	}	return 0;}/** * iwl_hw_reg_get_ch_txpower_limit - returns new power limit for channel * * NOTE: Returned power limit may be less (but not more) than requested, *	 based strictly on regulatory (eeprom and spectrum mgt) limitations *	 (no consideration for h/w clipping limitations). */static int iwl_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info){	s8 max_power;#if 0	/* if we're using TGd limits, use lower of TGd or EEPROM */	if (ch_info->tgd_data.max_power != 0)		max_power = min(ch_info->tgd_data.max_power,				ch_info->eeprom.max_power_avg);	/* else just use EEPROM limits */	else#endif		max_power = ch_info->eeprom.max_power_avg;	return min(max_power, ch_info->max_power_avg);}/** * iwl_hw_reg_comp_txpower_temp - Compensate for temperature * * Compensate txpower settings of *all* channels for temperature. * This only accounts for the difference between current temperature *   and the factory calibration temperatures, and bases the new settings *   on the channel's base_power_index. * * If RxOn is "associated", this sends the new Txpower to NIC! */static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv){	struct iwl_channel_info *ch_info = NULL;	int delta_index;	const s8 *clip_pwrs; /* array of h/w max power levels for each rate */	u8 a_band;	u8 rate_index;	u8 scan_tbl_index;	u8 i;	int ref_temp;	int temperature = priv->temperature;	/* set up new Tx power info for each and every channel, 2.4 and 5.x */	for (i = 0; i < priv->channel_count; i++) {		ch_info = &priv->channel_info[i];		a_band = is_channel_a_band(ch_info);		/* Get this chnlgrp's factory calibration temperature */		ref_temp = (s16)priv->eeprom.groups[ch_info->group_index].		    temperature;		/* get power index adjustment based on curr and factory		 * temps */		delta_index = iwl_hw_reg_adjust_power_by_temp(temperature,							      ref_temp);		/* set tx power value for all rates, OFDM and CCK */		for (rate_index = 0; rate_index < IWL_RATE_COUNT;		     rate_index++) {			int power_idx =			    ch_info->power_info[rate_index].base_power_index;			/* temperature compensate */			power_idx += delta_index;			/* stay within table range */			power_idx = iwl_hw_reg_fix_power_index(power_idx);			ch_info->power_info[rate_index].			    power_table_index = (u8) power_idx;			ch_info->power_info[rate_index].tpc =			    power_gain_table[a_band][power_idx];		}		/* Get this chnlgrp's rate-to-max/clip-powers table */		clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers;		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */		for (scan_tbl_index = 0;		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {			s32 actual_index = (scan_tbl_index == 0) ?			    IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;			iwl_hw_reg_set_scan_power(priv, scan_tbl_index,					   actual_index, clip_pwrs,					   ch_info, a_band);		}	}	/* send Txpower command for current channel to ucode */	return iwl_hw_reg_send_txpower(priv);}int iwl_hw_reg_set_txpower(struct iwl_priv *priv, s8 power){	struct iwl_channel_info *ch_info;	s8 max_power;	u8 a_band;	u8 i;	if (priv->user_txpower_limit == power) {		IWL_DEBUG_POWER("Requested Tx power same as current "				"limit: %ddBm.\n", power);		return 0;	}	IWL_DEBUG_POWER("Setting upper limit clamp to %ddBm.\n", power);	priv->user_txpower_limit = power;	/* set up new Tx powers for each and every channel, 2.4 and 5.x */	for (i = 0; i < priv->channel_count; i++) {		ch_info = &priv->channel_info[i];		a_band = is_channel_a_band(ch_info);		/* find minimum power of all user and regulatory constraints		 *    (does not consider h/w clipping limitations) */		max_power = iwl_hw_reg_get_ch_txpower_limit(ch_info);		max_power = min(power, max_power);		if (max_power != ch_info->curr_txpow) {			ch_info->curr_txpow = max_power;			/* this considers the h/w clipping limitations */			iwl_hw_reg_set_new_power(priv, ch_info);		}	}	/* update txpower settings for all channels,	 *   send to NIC if associated. */	is_temp_calib_needed(priv);	iwl_hw_reg_comp_txpower_temp(priv);	return 0;}/* will add 3945 channel switch cmd handling later */int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel){	return 0;}/** * iwl3945_reg_txpower_periodic -  called when time to check our temperature. * * -- reset periodic timer * -- see if temp has changed enough to warrant re-calibration ... if so: *     -- correct coeffs for temp (can reset temp timer) *     -- save this temp as "last", *     -- send new set of gain settings to NIC * NOTE:  This should continue working, even when we're not associated, *   so we can keep our internal table of scan powers current. */void iwl3945_reg_txpower_periodic(struct iwl_priv *priv){	/* This will kick in the "brute force"	 * iwl_hw_reg_comp_txpower_temp() below */	if (!is_temp_calib_needed(priv))		goto reschedule;	/* Set up a new set of temp-adjusted TxPowers, send to NIC.	 * This is based *only* on current temperature,	 * ignoring any previous power measurements */	iwl_hw_reg_comp_txpower_temp(priv); reschedule:	queue_delayed_work(priv->workqueue,			   &priv->thermal_periodic, REG_RECALIB_PERIOD * HZ);}void iwl3945_bg_reg_txpower_periodic(struct work_struct *work){	struct iwl_priv *priv = container_of(work, struct iwl_priv,					     thermal_periodic.work);	if (test_bit(STATUS_EXIT_PENDING, &priv->status))		return;	mutex_lock(&priv->mutex);	iwl3945_reg_txpower_periodic(priv);	mutex_unlock(&priv->mutex);}/** * iwl_hw_reg_get_ch_grp_index - find the channel-group index (0-4) * 				   for the channel. * * This function is used when initializing channel-info structs. * * NOTE: These channel groups do *NOT* match the bands above! *	 These channel groups are based on factory-tested channels; *	 on A-band, EEPROM's "group frequency" entries represent the top *	 channel in each group 1-4.  Group 5 All B/G channels are in group 0. */static u16 iwl_hw_reg_get_ch_grp_index(struct iwl_priv *priv,				       const struct iwl_channel_info *ch_info){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -