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

📄 iwl-3945.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct iwl_eeprom_txpower_group *ch_grp = &priv->eeprom.groups[0];	u8 group;	u16 group_index = 0;	/* based on factory calib frequencies */	u8 grp_channel;	/* Find the group index for the channel ... don't use index 1(?) */	if (is_channel_a_band(ch_info)) {		for (group = 1; group < 5; group++) {			grp_channel = ch_grp[group].group_channel;			if (ch_info->channel <= grp_channel) {				group_index = group;				break;			}		}		/* group 4 has a few channels *above* its factory cal freq */		if (group == 5)			group_index = 4;	} else		group_index = 0;	/* 2.4 GHz, group 0 */	IWL_DEBUG_POWER("Chnl %d mapped to grp %d\n", ch_info->channel,			group_index);	return group_index;}/** * iwl_hw_reg_get_matched_power_index - Interpolate to get nominal index * * Interpolate to get nominal (i.e. at factory calibration temperature) index *   into radio/DSP gain settings table for requested power. */static int iwl_hw_reg_get_matched_power_index(struct iwl_priv *priv,				       s8 requested_power,				       s32 setting_index, s32 *new_index){	const struct iwl_eeprom_txpower_group *chnl_grp = NULL;	s32 index0, index1;	s32 power = 2 * requested_power;	s32 i;	const struct iwl_eeprom_txpower_sample *samples;	s32 gains0, gains1;	s32 res;	s32 denominator;	chnl_grp = &priv->eeprom.groups[setting_index];	samples = chnl_grp->samples;	for (i = 0; i < 5; i++) {		if (power == samples[i].power) {			*new_index = samples[i].gain_index;			return 0;		}	}	if (power > samples[1].power) {		index0 = 0;		index1 = 1;	} else if (power > samples[2].power) {		index0 = 1;		index1 = 2;	} else if (power > samples[3].power) {		index0 = 2;		index1 = 3;	} else {		index0 = 3;		index1 = 4;	}	denominator = (s32) samples[index1].power - (s32) samples[index0].power;	if (denominator == 0)		return -EINVAL;	gains0 = (s32) samples[index0].gain_index * (1 << 19);	gains1 = (s32) samples[index1].gain_index * (1 << 19);	res = gains0 + (gains1 - gains0) *	    ((s32) power - (s32) samples[index0].power) / denominator +	    (1 << 18);	*new_index = res >> 19;	return 0;}static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv){	u32 i;	s32 rate_index;	const struct iwl_eeprom_txpower_group *group;	IWL_DEBUG_POWER("Initializing factory calib info from EEPROM\n");	for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) {		s8 *clip_pwrs;	/* table of power levels for each rate */		s8 satur_pwr;	/* saturation power for each chnl group */		group = &priv->eeprom.groups[i];		/* sanity check on factory saturation power value */		if (group->saturation_power < 40) {			IWL_WARNING("Error: saturation power is %d, "				    "less than minimum expected 40\n",				    group->saturation_power);			return;		}		/*		 * Derive requested power levels for each rate, based on		 *   hardware capabilities (saturation power for band).		 * Basic value is 3dB down from saturation, with further		 *   power reductions for highest 3 data rates.  These		 *   backoffs provide headroom for high rate modulation		 *   power peaks, without too much distortion (clipping).		 */		/* we'll fill in this array with h/w max power levels */		clip_pwrs = (s8 *) priv->clip_groups[i].clip_powers;		/* divide factory saturation power by 2 to find -3dB level */		satur_pwr = (s8) (group->saturation_power >> 1);		/* fill in channel group's nominal powers for each rate */		for (rate_index = 0;		     rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) {			switch (rate_index) {			case IWL_RATE_36M_INDEX_TABLE:				if (i == 0)	/* B/G */					*clip_pwrs = satur_pwr;				else	/* A */					*clip_pwrs = satur_pwr - 5;				break;			case IWL_RATE_48M_INDEX_TABLE:				if (i == 0)					*clip_pwrs = satur_pwr - 7;				else					*clip_pwrs = satur_pwr - 10;				break;			case IWL_RATE_54M_INDEX_TABLE:				if (i == 0)					*clip_pwrs = satur_pwr - 9;				else					*clip_pwrs = satur_pwr - 12;				break;			default:				*clip_pwrs = satur_pwr;				break;			}		}	}}/** * iwl3945_txpower_set_from_eeprom - Set channel power info based on EEPROM * * Second pass (during init) to set up priv->channel_info * * Set up Tx-power settings in our channel info database for each VALID * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values * and current temperature. * * Since this is based on current temperature (at init time), these values may * not be valid for very long, but it gives us a starting/default point, * and allows us to active (i.e. using Tx) scan. * * This does *not* write values to NIC, just sets up our internal table. */int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv){	struct iwl_channel_info *ch_info = NULL;	struct iwl_channel_power_info *pwr_info;	int delta_index;	u8 rate_index;	u8 scan_tbl_index;	const s8 *clip_pwrs;	/* array of power levels for each rate */	u8 gain, dsp_atten;	s8 power;	u8 pwr_index, base_pwr_index, a_band;	u8 i;	int temperature;	/* save temperature reference,	 *   so we can determine next time to calibrate */	temperature = iwl_hw_reg_txpower_get_temperature(priv);	priv->last_temperature = temperature;	iwl_hw_reg_init_channel_groups(priv);	/* initialize Tx power info for each and every channel, 2.4 and 5.x */	for (i = 0, ch_info = priv->channel_info; i < priv->channel_count;	     i++, ch_info++) {		a_band = is_channel_a_band(ch_info);		if (!is_channel_valid(ch_info))			continue;		/* find this channel's channel group (*not* "band") index */		ch_info->group_index =			iwl_hw_reg_get_ch_grp_index(priv, ch_info);		/* Get this chnlgrp's rate->max/clip-powers table */		clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers;		/* calculate power index *adjustment* value according to		 *  diff between current temperature and factory temperature */		delta_index = iwl_hw_reg_adjust_power_by_temp(temperature,				priv->eeprom.groups[ch_info->group_index].				temperature);		IWL_DEBUG_POWER("Delta index for channel %d: %d [%d]\n",				ch_info->channel, delta_index, temperature +				IWL_TEMP_CONVERT);		/* set tx power value for all OFDM rates */		for (rate_index = 0; rate_index < IWL_OFDM_RATES;		     rate_index++) {			s32 power_idx;			int rc;			/* use channel group's clip-power table,			 *   but don't exceed channel's max power */			s8 pwr = min(ch_info->max_power_avg,				     clip_pwrs[rate_index]);			pwr_info = &ch_info->power_info[rate_index];			/* get base (i.e. at factory-measured temperature)			 *    power table index for this rate's power */			rc = iwl_hw_reg_get_matched_power_index(priv, pwr,							 ch_info->group_index,							 &power_idx);			if (rc) {				IWL_ERROR("Invalid power index\n");				return rc;			}			pwr_info->base_power_index = (u8) power_idx;			/* temperature compensate */			power_idx += delta_index;			/* stay within range of gain table */			power_idx = iwl_hw_reg_fix_power_index(power_idx);			/* fill 1 OFDM rate's iwl_channel_power_info struct */			pwr_info->requested_power = pwr;			pwr_info->power_table_index = (u8) power_idx;			pwr_info->tpc.tx_gain =			    power_gain_table[a_band][power_idx].tx_gain;			pwr_info->tpc.dsp_atten =			    power_gain_table[a_band][power_idx].dsp_atten;		}		/* set tx power for CCK rates, based on OFDM 12 Mbit settings*/		pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE];		power = pwr_info->requested_power +			IWL_CCK_FROM_OFDM_POWER_DIFF;		pwr_index = pwr_info->power_table_index +			IWL_CCK_FROM_OFDM_INDEX_DIFF;		base_pwr_index = pwr_info->base_power_index +			IWL_CCK_FROM_OFDM_INDEX_DIFF;		/* stay within table range */		pwr_index = iwl_hw_reg_fix_power_index(pwr_index);		gain = power_gain_table[a_band][pwr_index].tx_gain;		dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten;		/* fill each CCK rate's iwl_channel_power_info structure		 * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!		 * NOTE:  CCK rates start at end of OFDM rates! */		for (rate_index = 0;		     rate_index < IWL_CCK_RATES; rate_index++) {			pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES];			pwr_info->requested_power = power;			pwr_info->power_table_index = pwr_index;			pwr_info->base_power_index = base_pwr_index;			pwr_info->tpc.tx_gain = gain;			pwr_info->tpc.dsp_atten = dsp_atten;		}		/* 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);		}	}	return 0;}int iwl_hw_rxq_stop(struct iwl_priv *priv){	int rc;	unsigned long flags;	spin_lock_irqsave(&priv->lock, flags);	rc = iwl_grab_restricted_access(priv);	if (rc) {		spin_unlock_irqrestore(&priv->lock, flags);		return rc;	}	iwl_write_restricted(priv, FH_RCSR_CONFIG(0), 0);	rc = iwl_poll_restricted_bit(priv, FH_RSSR_STATUS, (1 << 24), 1000);	if (rc < 0)		IWL_ERROR("Can't stop Rx DMA.\n");	iwl_release_restricted_access(priv);	spin_unlock_irqrestore(&priv->lock, flags);	return 0;}int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq){	int rc;	unsigned long flags;	int txq_id = txq->q.id;	struct iwl_shared *shared_data = priv->hw_setting.shared_virt;	shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);	spin_lock_irqsave(&priv->lock, flags);	rc = iwl_grab_restricted_access(priv);	if (rc) {		spin_unlock_irqrestore(&priv->lock, flags);		return rc;	}	iwl_write_restricted(priv, FH_CBCC_CTRL(txq_id), 0);	iwl_write_restricted(priv, FH_CBCC_BASE(txq_id), 0);	iwl_write_restricted(priv, FH_TCSR_CONFIG(txq_id),		ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |		ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |		ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |		ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |		ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);	iwl_release_restricted_access(priv);	/* fake read to flush all prev. writes */	iwl_read32(priv, FH_TSSR_CBB_BASE);	spin_unlock_irqrestore(&priv->lock, flags);	return 0;}int iwl_hw_get_rx_read(struct iwl_priv *priv){	struct iwl_shared *shared_data = priv->hw_setting.shared_virt;	return le32_to_cpu(shared_data->rx_read_ptr[0]);}/** * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table */int iwl3945_init_hw_rate_table(struct iwl_priv *priv){	int rc, i, index, prev_index;	struct iwl_rate_scaling_cmd rate_cmd = {		.reserved = {0, 0, 0},	};	struct iwl_rate_scaling_info *table = rate_cmd.table;	for (i = 0; i < ARRAY_SIZE(iwl_rates); i++) {		index = iwl_rates[i].table_rs_index;		table[index].rate_n_flags =			iwl_hw_set_rate_n_flags(iwl_rates[i].plcp, 0);		table[index].try_cnt = priv->retry_rate;		prev_index = iwl_get_prev_ieee_rate(i);		table[index].next_rate_index = iwl_rates[prev_index].table_rs_index;	}	switch (priv->phymode) {	case MODE_IEEE80211A:		IWL_DEBUG_RATE("Select A mode rate scale\n");		/* If one of the following CCK rates is used,		 * have it fall back to the 6M OFDM rate */		for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++)			table[i].next_rate_index = iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index;		/* Don't fall back to CCK rates */		table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = IWL_RATE_9M_INDEX_TABLE;		/* Don't drop out of OFDM rates */		table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =		    iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index;		break;	case MODE_IEEE80211B:		IWL_DEBUG_RATE("Select B mode rate scale\n");		/* If an OFDM rate is used, have it fall back to the		 * 1M CCK rates */		for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)			table[i].next_rate_index = iwl_rates[IWL_FIRST_CCK_RATE].table_rs_index;		/* CCK shouldn't fall back to OFDM... */		table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE;		break;	default:		IWL_DEBUG_RATE("Select G mode rate scale\n");		break;	}	/* Update the rate scaling for control frame Tx */	rate_cmd.table_id = 0;	rc = iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),			      &rate_cmd);	if (rc)		return rc;	/* Update the rate scaling for data frame Tx */	rate_cmd.table_id = 1;	return iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),				&rate_cmd);}int iwl_hw_set_hw_setting(struct iwl_priv *priv){	memset((void *)&priv->hw_setting, 0,	       sizeof(struct iwl_driver_hw_info));	priv->hw_setting.shared_virt =	    pci_alloc_consistent(priv->pci_dev,				 sizeof(struct iwl_shared),				 &priv->hw_setting.shared_phys);	if (!priv->hw_setting.shared_virt) {		IWL_ERROR("failed to allocate pci memory\n");		mutex_unlock(&priv->mutex);		return -ENOMEM;	}	priv->hw_setting.ac_queue_count = AC_NUM;	priv->hw_setting.rx_buffer_size = IWL_RX_BUF_SIZE;	priv->hw_setting.tx_cmd_len = sizeof(struct iwl_tx_cmd);	priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;	priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;	priv->hw_setting.cck_flag = 0;	priv->hw_setting.max_stations = IWL3945_STATION_COUNT;	priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID;	return 0;}unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,			  struct iwl_frame *frame, u8 rate){	struct iwl_tx_beacon_cmd *tx_beacon_cmd;	unsigned int frame_size;	tx_beacon_cmd = (struct iwl_tx_beacon_cmd *)&frame->u;	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));	tx_beacon_cmd->tx.sta_id = IWL394

⌨️ 快捷键说明

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