示例#1
0
static int adm8211_write_bbp(struct ieee80211_hw *dev, u8 addr, u8 data)
{
	struct adm8211_priv *priv = dev->priv;
	unsigned int timeout;
	u32 reg;

	timeout = 10;
	while (timeout > 0) {
		reg = ADM8211_CSR_READ(BBPCTL);
		if (!(reg & (ADM8211_BBPCTL_WR | ADM8211_BBPCTL_RD)))
			break;
		timeout--;
		msleep(2);
	}

	if (timeout == 0) {
		wiphy_debug(dev->wiphy,
			    "adm8211_write_bbp(%d,%d) failed prewrite (reg=0x%08x)\n",
			    addr, data, reg);
		return -ETIMEDOUT;
	}

	switch (priv->bbp_type) {
	case ADM8211_TYPE_INTERSIL:
		reg = ADM8211_BBPCTL_MMISEL;	/* three wire interface */
		break;
	case ADM8211_TYPE_RFMD:
		reg = (0x20 << 24) | ADM8211_BBPCTL_TXCE | ADM8211_BBPCTL_CCAP |
		      (0x01 << 18);
		break;
	case ADM8211_TYPE_ADMTEK:
		reg = (0x20 << 24) | ADM8211_BBPCTL_TXCE | ADM8211_BBPCTL_CCAP |
		      (0x05 << 18);
		break;
	}
	reg |= ADM8211_BBPCTL_WR | (addr << 8) | data;

	ADM8211_CSR_WRITE(BBPCTL, reg);

	timeout = 10;
	while (timeout > 0) {
		reg = ADM8211_CSR_READ(BBPCTL);
		if (!(reg & ADM8211_BBPCTL_WR))
			break;
		timeout--;
		msleep(2);
	}

	if (timeout == 0) {
		ADM8211_CSR_WRITE(BBPCTL, ADM8211_CSR_READ(BBPCTL) &
				  ~ADM8211_BBPCTL_WR);
		wiphy_debug(dev->wiphy,
			    "adm8211_write_bbp(%d,%d) failed postwrite (reg=0x%08x)\n",
			    addr, data, reg);
		return -ETIMEDOUT;
	}

	return 0;
}
示例#2
0
static int mwl_mac80211_config(struct ieee80211_hw *hw,
			       u32 changed)
{
	struct ieee80211_conf *conf = &hw->conf;
	int rc;

	wiphy_debug(hw->wiphy, "change: 0x%x\n", changed);

	if (conf->flags & IEEE80211_CONF_IDLE)
		rc = mwl_fwcmd_radio_disable(hw);
	else
		rc = mwl_fwcmd_radio_enable(hw);

	if (rc)
		goto out;

	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
		int rate = 0;

		if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
			mwl_fwcmd_set_apmode(hw, AP_MODE_2_4GHZ_11AC_MIXED);
			mwl_fwcmd_set_linkadapt_cs_mode(hw,
							LINK_CS_STATE_CONSERV);
			rate = mwl_rates_24[0].hw_value;
		} else if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) {
			mwl_fwcmd_set_apmode(hw, AP_MODE_11AC);
			mwl_fwcmd_set_linkadapt_cs_mode(hw,
							LINK_CS_STATE_AUTO);
			rate = mwl_rates_50[0].hw_value;

			if (conf->radar_enabled)
				mwl_fwcmd_set_radar_detect(hw, MONITOR_START);
			else
				mwl_fwcmd_set_radar_detect(hw,
							   STOP_DETECT_RADAR);
		}

		rc = mwl_fwcmd_set_rf_channel(hw, conf);
		if (rc)
			goto out;
		rc = mwl_fwcmd_use_fixed_rate(hw, rate, rate);
		if (rc)
			goto out;
		rc = mwl_fwcmd_max_tx_power(hw, conf, 0);
		if (rc)
			goto out;
		rc = mwl_fwcmd_tx_power(hw, conf, 0);
		if (rc)
			goto out;
		rc = mwl_fwcmd_set_cdd(hw);
	}

out:

	return rc;
}
示例#3
0
/*
 * CFG802.11 operation handler for setting bit rates.
 *
 * Function selects legacy bang B/G/BG from corresponding bitrates selection.
 * Currently only 2.4GHz band is supported.
 */
static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
				struct net_device *dev,
				const u8 *peer,
				const struct cfg80211_bitrate_mask *mask)
{
	struct mwifiex_ds_band_cfg band_cfg;
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
	int index = 0, mode = 0, i;

	/* Currently only 2.4GHz is supported */
	for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
		/*
		 * Rates below 6 Mbps in the table are CCK rates; 802.11b
		 * and from 6 they are OFDM; 802.11G
		 */
		if (mwifiex_rates[i].bitrate == 60) {
			index = 1 << i;
			break;
		}
	}

	if (mask->control[IEEE80211_BAND_2GHZ].legacy < index) {
		mode = BAND_B;
	} else {
		mode = BAND_G;
		if (mask->control[IEEE80211_BAND_2GHZ].legacy % index)
			mode |=  BAND_B;
	}

	memset(&band_cfg, 0, sizeof(band_cfg));
	band_cfg.config_bands = mode;

	if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
		band_cfg.adhoc_start_band = mode;

	band_cfg.sec_chan_offset = NO_SEC_CHANNEL;

	if (mwifiex_set_radio_band_cfg(priv, &band_cfg))
		return -EFAULT;

	wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",
				(mode & BAND_B) ? "b" : "",
				(mode & BAND_G) ? "g" : "");

	return 0;
}
示例#4
0
/*
 * CFG802.11 operation handler for setting bit rates.
 *
 * Function selects legacy bang B/G/BG from corresponding bitrates selection.
 * Currently only 2.4GHz band is supported.
 */
static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
				struct net_device *dev,
				const u8 *peer,
				const struct cfg80211_bitrate_mask *mask)
{
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
	int index = 0, mode = 0, i;
	struct mwifiex_adapter *adapter = priv->adapter;

	/* Currently only 2.4GHz is supported */
	for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
		/*
		 * Rates below 6 Mbps in the table are CCK rates; 802.11b
		 * and from 6 they are OFDM; 802.11G
		 */
		if (mwifiex_rates[i].bitrate == 60) {
			index = 1 << i;
			break;
		}
	}

	if (mask->control[IEEE80211_BAND_2GHZ].legacy < index) {
		mode = BAND_B;
	} else {
		mode = BAND_G;
		if (mask->control[IEEE80211_BAND_2GHZ].legacy % index)
			mode |=  BAND_B;
	}

	if (!((mode | adapter->fw_bands) & ~adapter->fw_bands)) {
		adapter->config_bands = mode;
		if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
			adapter->adhoc_start_band = mode;
			adapter->adhoc_11n_enabled = false;
		}
	}
	adapter->sec_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
	adapter->channel_type = NL80211_CHAN_NO_HT;

	wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",
		    (mode & BAND_B) ? "b" : "", (mode & BAND_G) ? "g" : "");

	return 0;
}
示例#5
0
文件: fwdl.c 项目: donadonny/mwlwifi
int mwl_fwdl_download_firmware(struct ieee80211_hw *hw)
{
	struct mwl_priv *priv = hw->priv;
	const struct firmware *fw;
	u32 curr_iteration = 0;
	u32 size_fw_downloaded = 0;
	u32 int_code = 0;
	u32 len = 0;
	u32 fwreadysignature = HOSTCMD_SOFTAP_FWRDY_SIGNATURE;

	fw = priv->fw_ucode;

	mwl_fwcmd_reset(hw);

	/* FW before jumping to boot rom, it will enable PCIe transaction retry,
	 * wait for boot code to stop it.
	 */
	usleep_range(FW_CHECK_MSECS * 1000, FW_CHECK_MSECS * 2000);

	writel(MACREG_A2HRIC_BIT_MASK,
	       priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CLEAR_SEL);
	writel(0x00, priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE);
	writel(0x00, priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK);
	writel(MACREG_A2HRIC_BIT_MASK,
	       priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK);

	/* this routine interacts with SC2 bootrom to download firmware binary
	 * to the device. After DMA'd to SC2, the firmware could be deflated to
	 * reside on its respective blocks such as ITCM, DTCM, SQRAM,
	 * (or even DDR, AFTER DDR is init'd before fw download
	 */
	wiphy_debug(hw->wiphy, "fw download start\n");

	/* Disable PFU before FWDL */
	writel(0x100, priv->iobase1 + 0xE0E4);

	/* make sure SCRATCH2 C40 is clear, in case we are too quick */
	while (readl(priv->iobase1 + 0xc40) == 0)
		cond_resched();

	while (size_fw_downloaded < fw->size) {
		len = readl(priv->iobase1 + 0xc40);

		if (!len)
			break;

		/* this copies the next chunk of fw binary to be delivered */
		memcpy((char *)&priv->pcmd_buf[0],
		       (fw->data + size_fw_downloaded), len);

		/* this function writes pdata to c10, then write 2 to c18 */
		mwl_fwdl_trig_pcicmd_bootcode(priv);

		/* this is arbitrary per your platform; we use 0xffff */
		curr_iteration = FW_MAX_NUM_CHECKS;

		/* NOTE: the following back to back checks on C1C is time
		 * sensitive, hence may need to be tweaked dependent on host
		 * processor. Time for SC2 to go from the write of event 2 to
		 * C1C == 2 is ~1300 nSec. Hence the checkings on host has to
		 * consider how efficient your code can be to meet this timing,
		 * or you can alternatively tweak this routines to fit your
		 * platform
		 */
		do {
			int_code = readl(priv->iobase1 + 0xc1c);
			if (int_code != 0)
				break;
			cond_resched();
			curr_iteration--;
		} while (curr_iteration);

		do {
			int_code = readl(priv->iobase1 + 0xc1c);
			if ((int_code & MACREG_H2ARIC_BIT_DOOR_BELL) !=
			    MACREG_H2ARIC_BIT_DOOR_BELL)
				break;
			cond_resched();
			curr_iteration--;
		} while (curr_iteration);

		if (curr_iteration == 0) {
			/* This limited loop check allows you to exit gracefully
			 * without locking up your entire system just because fw
			 * download failed
			 */
			wiphy_err(hw->wiphy,
				  "Exhausted curr_iteration for fw download\n");
			goto err_download;
		}

		size_fw_downloaded += len;
	}

	wiphy_debug(hw->wiphy,
		    "FwSize = %d downloaded Size = %d curr_iteration %d\n",
		    (int)fw->size, size_fw_downloaded, curr_iteration);

	/* Now firware is downloaded successfully, so this part is to check
	 * whether fw can properly execute to an extent that write back
	 * signature to indicate its readiness to the host. NOTE: if your
	 * downloaded fw crashes, this signature checking will fail. This
	 * part is similar as SC1
	 */
	*((u32 *)&priv->pcmd_buf[1]) = 0;
	mwl_fwdl_trig_pcicmd(priv);
	curr_iteration = FW_MAX_NUM_CHECKS;
	do {
		curr_iteration--;
		writel(HOSTCMD_SOFTAP_MODE,
		       priv->iobase1 + MACREG_REG_GEN_PTR);
		usleep_range(FW_CHECK_MSECS * 1000, FW_CHECK_MSECS * 2000);
		int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE);
		if (!(curr_iteration % 0xff) && (int_code != 0))
			wiphy_err(hw->wiphy, "%x;", int_code);
	} while ((curr_iteration) &&
		 (int_code != fwreadysignature));

	if (curr_iteration == 0) {
		wiphy_err(hw->wiphy,
			  "Exhausted curr_iteration for fw signature\n");
		goto err_download;
	}

	wiphy_debug(hw->wiphy, "fw download complete\n");
	writel(0x00, priv->iobase1 + MACREG_REG_INT_CODE);

	return 0;

err_download:

	mwl_fwcmd_reset(hw);

	return -EIO;
}
示例#6
0
文件: main.c 项目: dnlove/maica
int ieee80211_register_hw(struct ieee80211_hw *hw)
{
	struct ieee80211_local *local = hw_to_local(hw);
	int result, i;
	enum ieee80211_band band;
	int channels, max_bitrates;
	bool supp_ht;
	static const u32 cipher_suites[] = {
		/* keep WEP first, it may be removed below */
		WLAN_CIPHER_SUITE_WEP40,
		WLAN_CIPHER_SUITE_WEP104,
		WLAN_CIPHER_SUITE_TKIP,
		WLAN_CIPHER_SUITE_CCMP,

		/* keep last -- depends on hw flags! */
		WLAN_CIPHER_SUITE_AES_CMAC
	};

	if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns)
#ifdef CONFIG_PM
	    && (!local->ops->suspend || !local->ops->resume)
#endif
	    )
		return -EINVAL;

	if (hw->max_report_rates == 0)
		hw->max_report_rates = hw->max_rates;

	/*
	 * generic code guarantees at least one band,
	 * set this very early because much code assumes
	 * that hw.conf.channel is assigned
	 */
	channels = 0;
	max_bitrates = 0;
	supp_ht = false;
	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
		struct ieee80211_supported_band *sband;

		sband = local->hw.wiphy->bands[band];
		if (!sband)
			continue;
		if (!local->oper_channel) {
			/* init channel we're on */
			local->hw.conf.channel =
			local->oper_channel = &sband->channels[0];
			local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
		}
		channels += sband->n_channels;

		if (max_bitrates < sband->n_bitrates)
			max_bitrates = sband->n_bitrates;
		supp_ht = supp_ht || sband->ht_cap.ht_supported;
	}

	local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
				      sizeof(void *) * channels, GFP_KERNEL);
	if (!local->int_scan_req)
		return -ENOMEM;

	/* if low-level driver supports AP, we also support VLAN */
	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
		hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
	}

	/* mac80211 always supports monitor */
	hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
	hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);

	/*
	 * mac80211 doesn't support more than 1 channel, and also not more
	 * than one IBSS interface
	 */
	for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
		const struct ieee80211_iface_combination *c;
		int j;

		c = &hw->wiphy->iface_combinations[i];

		if (c->num_different_channels > 1)
			return -EINVAL;

		for (j = 0; j < c->n_limits; j++)
			if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
			    c->limits[j].max > 1)
				return -EINVAL;
	}

#ifndef CONFIG_MAC80211_MESH
	/* mesh depends on Kconfig, but drivers should set it if they want */
	local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
#endif

	/* if the underlying driver supports mesh, mac80211 will (at least)
	 * provide routing of mesh authentication frames to userspace */
	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
		local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH;

	/* mac80211 supports control port protocol changing */
	local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;

	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;

	WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
	     && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
	     "U-APSD not supported with HW_PS_NULLFUNC_STACK\n");

	/*
	 * Calculate scan IE length -- we need this to alloc
	 * memory and to subtract from the driver limit. It
	 * includes the DS Params, (extended) supported rates, and HT
	 * information -- SSID is the driver's responsibility.
	 */
	local->scan_ies_len = 4 + max_bitrates /* (ext) supp rates */ +
		3 /* DS Params */;
	if (supp_ht)
		local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);

	if (!local->ops->hw_scan) {
		/* For hw_scan, driver needs to set these up. */
		local->hw.wiphy->max_scan_ssids = 4;
		local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
	}

	/*
	 * If the driver supports any scan IEs, then assume the
	 * limit includes the IEs mac80211 will add, otherwise
	 * leave it at zero and let the driver sort it out; we
	 * still pass our IEs to the driver but userspace will
	 * not be allowed to in that case.
	 */
	if (local->hw.wiphy->max_scan_ie_len)
		local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;

	/* Set up cipher suites unless driver already did */
	if (!local->hw.wiphy->cipher_suites) {
		local->hw.wiphy->cipher_suites = cipher_suites;
		local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
		if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
			local->hw.wiphy->n_cipher_suites--;
	}
	if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
		if (local->hw.wiphy->cipher_suites == cipher_suites) {
			local->hw.wiphy->cipher_suites += 2;
			local->hw.wiphy->n_cipher_suites -= 2;
		} else {
			u32 *suites;
			int r, w = 0;

			/* Filter out WEP */

			suites = kmemdup(
				local->hw.wiphy->cipher_suites,
				sizeof(u32) * local->hw.wiphy->n_cipher_suites,
				GFP_KERNEL);
			if (!suites)
				return -ENOMEM;
			for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
				u32 suite = local->hw.wiphy->cipher_suites[r];
				if (suite == WLAN_CIPHER_SUITE_WEP40 ||
				    suite == WLAN_CIPHER_SUITE_WEP104)
					continue;
				suites[w++] = suite;
			}
			local->hw.wiphy->cipher_suites = suites;
			local->hw.wiphy->n_cipher_suites = w;
			local->wiphy_ciphers_allocated = true;
		}
	}

	if (!local->ops->remain_on_channel)
		local->hw.wiphy->max_remain_on_channel_duration = 5000;

	if (local->ops->sched_scan_start)
		local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;

	result = wiphy_register(local->hw.wiphy);
	if (result < 0)
		goto fail_wiphy_register;

	/*
	 * We use the number of queues for feature tests (QoS, HT) internally
	 * so restrict them appropriately.
	 */
	if (hw->queues > IEEE80211_MAX_QUEUES)
		hw->queues = IEEE80211_MAX_QUEUES;

	local->workqueue =
		alloc_ordered_workqueue(wiphy_name(local->hw.wiphy), 0);
	if (!local->workqueue) {
		result = -ENOMEM;
		goto fail_workqueue;
	}

	/*
	 * The hardware needs headroom for sending the frame,
	 * and we need some headroom for passing the frame to monitor
	 * interfaces, but never both at the same time.
	 */
#ifndef __CHECKER__
	BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
			sizeof(struct ieee80211_tx_status_rtap_hdr));
#endif
	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
				   sizeof(struct ieee80211_tx_status_rtap_hdr));

	debugfs_hw_add(local);

	/*
	 * if the driver doesn't specify a max listen interval we
	 * use 5 which should be a safe default
	 */
	if (local->hw.max_listen_interval == 0)
		local->hw.max_listen_interval = 5;

	local->hw.conf.listen_interval = local->hw.max_listen_interval;

	local->dynamic_ps_forced_timeout = -1;

	result = ieee80211_wep_init(local);
	if (result < 0)
		wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
			    result);

	rtnl_lock();

	result = ieee80211_init_rate_ctrl_alg(local,
					      hw->rate_control_algorithm);
	if (result < 0) {
		wiphy_debug(local->hw.wiphy,
			    "Failed to initialize rate control algorithm\n");
		goto fail_rate;
	}

	/* add one default STA interface if supported */
	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
		result = ieee80211_if_add(local, "wlan%d", NULL,
					  NL80211_IFTYPE_STATION, NULL);
		if (result)
			wiphy_warn(local->hw.wiphy,
				   "Failed to add default virtual iface\n");
	}

	rtnl_unlock();

	ieee80211_led_init(local);

	local->network_latency_notifier.notifier_call =
		ieee80211_max_network_latency;
	result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
				     &local->network_latency_notifier);
	if (result) {
		rtnl_lock();
		goto fail_pm_qos;
	}

#ifdef CONFIG_INET
	local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
	result = register_inetaddr_notifier(&local->ifa_notifier);
	if (result)
		goto fail_ifa;
#endif

	netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
			local->hw.napi_weight);

	return 0;

#ifdef CONFIG_INET
 fail_ifa:
	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
			       &local->network_latency_notifier);
	rtnl_lock();
#endif
 fail_pm_qos:
	ieee80211_led_exit(local);
	ieee80211_remove_interfaces(local);
 fail_rate:
	rtnl_unlock();
	ieee80211_wep_free(local);
	sta_info_stop(local);
	destroy_workqueue(local->workqueue);
 fail_workqueue:
	wiphy_unregister(local->hw.wiphy);
 fail_wiphy_register:
	if (local->wiphy_ciphers_allocated)
		kfree(local->hw.wiphy->cipher_suites);
	kfree(local->int_scan_req);
	return result;
}
示例#7
0
static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan)
{
	static const u32 adm8211_rfmd2958_reg5[] =
		{0x22BD, 0x22D2, 0x22E8, 0x22FE, 0x2314, 0x232A, 0x2340,
		 0x2355, 0x236B, 0x2381, 0x2397, 0x23AD, 0x23C2, 0x23F7};
	static const u32 adm8211_rfmd2958_reg6[] =
		{0x05D17, 0x3A2E8, 0x2E8BA, 0x22E8B, 0x1745D, 0x0BA2E, 0x00000,
		 0x345D1, 0x28BA2, 0x1D174, 0x11745, 0x05D17, 0x3A2E8, 0x11745};

	struct adm8211_priv *priv = dev->priv;
	u8 ant_power = priv->ant_power > 0x3F ?
		priv->eeprom->antenna_power[chan - 1] : priv->ant_power;
	u8 tx_power = priv->tx_power > 0x3F ?
		priv->eeprom->tx_power[chan - 1] : priv->tx_power;
	u8 lpf_cutoff = priv->lpf_cutoff == 0xFF ?
		priv->eeprom->lpf_cutoff[chan - 1] : priv->lpf_cutoff;
	u8 lnags_thresh = priv->lnags_threshold == 0xFF ?
		priv->eeprom->lnags_threshold[chan - 1] : priv->lnags_threshold;
	u32 reg;

	ADM8211_IDLE();

	/* Program synthesizer to new channel */
	switch (priv->transceiver_type) {
	case ADM8211_RFMD2958:
	case ADM8211_RFMD2958_RF3000_CONTROL_POWER:
		adm8211_rf_write_syn_rfmd2958(dev, 0x00, 0x04007);
		adm8211_rf_write_syn_rfmd2958(dev, 0x02, 0x00033);

		adm8211_rf_write_syn_rfmd2958(dev, 0x05,
			adm8211_rfmd2958_reg5[chan - 1]);
		adm8211_rf_write_syn_rfmd2958(dev, 0x06,
			adm8211_rfmd2958_reg6[chan - 1]);
		break;

	case ADM8211_RFMD2948:
		adm8211_rf_write_syn_rfmd2948(dev, SI4126_MAIN_CONF,
					      SI4126_MAIN_XINDIV2);
		adm8211_rf_write_syn_rfmd2948(dev, SI4126_POWERDOWN,
					      SI4126_POWERDOWN_PDIB |
					      SI4126_POWERDOWN_PDRB);
		adm8211_rf_write_syn_rfmd2948(dev, SI4126_PHASE_DET_GAIN, 0);
		adm8211_rf_write_syn_rfmd2948(dev, SI4126_RF2_N_DIV,
					      (chan == 14 ?
					       2110 : (2033 + (chan * 5))));
		adm8211_rf_write_syn_rfmd2948(dev, SI4126_IF_N_DIV, 1496);
		adm8211_rf_write_syn_rfmd2948(dev, SI4126_RF2_R_DIV, 44);
		adm8211_rf_write_syn_rfmd2948(dev, SI4126_IF_R_DIV, 44);
		break;

	case ADM8211_MAX2820:
		adm8211_rf_write_syn_max2820(dev, 0x3,
			(chan == 14 ? 0x054 : (0x7 + (chan * 5))));
		break;

	case ADM8211_AL2210L:
		adm8211_rf_write_syn_al2210l(dev, 0x0,
			(chan == 14 ? 0x229B4 : (0x22967 + (chan * 5))));
		break;

	default:
		wiphy_debug(dev->wiphy, "unsupported transceiver type %d\n",
			    priv->transceiver_type);
		break;
	}

	/* write BBP regs */
	if (priv->bbp_type == ADM8211_TYPE_RFMD) {

	/* SMC 2635W specific? adm8211b doesn't use the 2948 though.. */
	/* TODO: remove if SMC 2635W doesn't need this */
	if (priv->transceiver_type == ADM8211_RFMD2948) {
		reg = ADM8211_CSR_READ(GPIO);
		reg &= 0xfffc0000;
		reg |= ADM8211_CSR_GPIO_EN0;
		if (chan != 14)
			reg |= ADM8211_CSR_GPIO_O0;
		ADM8211_CSR_WRITE(GPIO, reg);
	}

	if (priv->transceiver_type == ADM8211_RFMD2958) {
		/* set PCNT2 */
		adm8211_rf_write_syn_rfmd2958(dev, 0x0B, 0x07100);
		/* set PCNT1 P_DESIRED/MID_BIAS */
		reg = le16_to_cpu(priv->eeprom->cr49);
		reg >>= 13;
		reg <<= 15;
		reg |= ant_power << 9;
		adm8211_rf_write_syn_rfmd2958(dev, 0x0A, reg);
		/* set TXRX TX_GAIN */
		adm8211_rf_write_syn_rfmd2958(dev, 0x09, 0x00050 |
			(priv->pdev->revision < ADM8211_REV_CA ? tx_power : 0));
	} else {
示例#8
0
static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
{
	struct adm8211_priv *priv = dev->priv;
	unsigned int entry = priv->cur_rx % priv->rx_ring_size;
	u32 status;
	unsigned int pktlen;
	struct sk_buff *skb, *newskb;
	unsigned int limit = priv->rx_ring_size;
	u8 rssi, rate;

	while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) {
		if (!limit--)
			break;

		status = le32_to_cpu(priv->rx_ring[entry].status);
		rate = (status & RDES0_STATUS_RXDR) >> 12;
		rssi = le32_to_cpu(priv->rx_ring[entry].length) &
			RDES1_STATUS_RSSI;

		pktlen = status & RDES0_STATUS_FL;
		if (pktlen > RX_PKT_SIZE) {
			if (net_ratelimit())
				wiphy_debug(dev->wiphy, "frame too long (%d)\n",
					    pktlen);
			pktlen = RX_PKT_SIZE;
		}

		if (!priv->soft_rx_crc && status & RDES0_STATUS_ES) {
			skb = NULL; /* old buffer will be reused */
			/* TODO: update RX error stats */
			/* TODO: check RDES0_STATUS_CRC*E */
		} else if (pktlen < RX_COPY_BREAK) {
			skb = dev_alloc_skb(pktlen);
			if (skb) {
				pci_dma_sync_single_for_cpu(
					priv->pdev,
					priv->rx_buffers[entry].mapping,
					pktlen, PCI_DMA_FROMDEVICE);
				memcpy(skb_put(skb, pktlen),
				       skb_tail_pointer(priv->rx_buffers[entry].skb),
				       pktlen);
				pci_dma_sync_single_for_device(
					priv->pdev,
					priv->rx_buffers[entry].mapping,
					RX_PKT_SIZE, PCI_DMA_FROMDEVICE);
			}
		} else {
			newskb = dev_alloc_skb(RX_PKT_SIZE);
			if (newskb) {
				skb = priv->rx_buffers[entry].skb;
				skb_put(skb, pktlen);
				pci_unmap_single(
					priv->pdev,
					priv->rx_buffers[entry].mapping,
					RX_PKT_SIZE, PCI_DMA_FROMDEVICE);
				priv->rx_buffers[entry].skb = newskb;
				priv->rx_buffers[entry].mapping =
					pci_map_single(priv->pdev,
						       skb_tail_pointer(newskb),
						       RX_PKT_SIZE,
						       PCI_DMA_FROMDEVICE);
			} else {
				skb = NULL;
				/* TODO: update rx dropped stats */
			}

			priv->rx_ring[entry].buffer1 =
				cpu_to_le32(priv->rx_buffers[entry].mapping);
		}

		priv->rx_ring[entry].status = cpu_to_le32(RDES0_STATUS_OWN |
							  RDES0_STATUS_SQL);
		priv->rx_ring[entry].length =
			cpu_to_le32(RX_PKT_SIZE |
				    (entry == priv->rx_ring_size - 1 ?
				     RDES1_CONTROL_RER : 0));

		if (skb) {
			struct ieee80211_rx_status rx_status = {0};

			if (priv->pdev->revision < ADM8211_REV_CA)
				rx_status.signal = rssi;
			else
				rx_status.signal = 100 - rssi;

			rx_status.rate_idx = rate;

			rx_status.freq = adm8211_channels[priv->channel - 1].center_freq;
			rx_status.band = IEEE80211_BAND_2GHZ;

			memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
			ieee80211_rx_irqsafe(dev, skb);
		}

		entry = (++priv->cur_rx) % priv->rx_ring_size;
	}

	/* TODO: check LPC and update stats? */
}