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

📄 wl3501_cs.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Return : 0 - OK *	    1 - Could not transmit (dev_queue_xmit will queue it) *		and try to sent it later */static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev){	int enabled, rc;	struct wl3501_card *this = dev->priv;	unsigned long flags;	spin_lock_irqsave(&this->lock, flags);	enabled = wl3501_block_interrupt(this);	dev->trans_start = jiffies;	rc = wl3501_send_pkt(this, skb->data, skb->len);	if (enabled)		wl3501_unblock_interrupt(this);	if (rc) {		++this->stats.tx_dropped;		netif_stop_queue(dev);	} else {		++this->stats.tx_packets;		this->stats.tx_bytes += skb->len;		kfree_skb(skb);		if (this->tx_buffer_cnt < 2)			netif_stop_queue(dev);	}	spin_unlock_irqrestore(&this->lock, flags);	return rc;}static int wl3501_open(struct net_device *dev){	int rc = -ENODEV;	struct wl3501_card *this = dev->priv;	unsigned long flags;	dev_link_t *link;	spin_lock_irqsave(&this->lock, flags);	/* Check if the device is in wl3501_dev_list */	for (link = wl3501_dev_list; link; link = link->next)		if (link->priv == dev)			break;	if (!DEV_OK(link))		goto out;	netif_device_attach(dev);	link->open++;	/* Initial WL3501 firmware */	dprintk(1, "%s: Initialize WL3501 firmware...", dev->name);	if (wl3501_init_firmware(this))		goto fail;	/* Initial device variables */	this->adhoc_times = 0;	/* Acknowledge Interrupt, for cleaning last state */	wl3501_ack_interrupt(this);	/* Enable interrupt from card after all */	wl3501_unblock_interrupt(this);	wl3501_mgmt_scan(this, 100);	rc = 0;	dprintk(1, "%s: WL3501 opened", dev->name);	printk(KERN_INFO "%s: Card Name: %s\n"			 "%s: Firmware Date: %s\n",			 dev->name, this->card_name,			 dev->name, this->firmware_date);out:	spin_unlock_irqrestore(&this->lock, flags);	return rc;fail:	printk(KERN_WARNING "%s: Can't initialize firmware!\n", dev->name);	goto out;}struct net_device_stats *wl3501_get_stats(struct net_device *dev){	struct wl3501_card *this = dev->priv;	return &this->stats;}struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev){	struct wl3501_card *this = dev->priv;	struct iw_statistics *wstats = &this->wstats;	u32 value; /* size checked: it is u32 */	memset(wstats, 0, sizeof(*wstats));	wstats->status = netif_running(dev);	if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_ICV_ERROR_COUNT,				  &value, sizeof(value)))		wstats->discard.code += value;	if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_UNDECRYPTABLE_COUNT,				  &value, sizeof(value)))		wstats->discard.code += value;	if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_EXCLUDED_COUNT,				  &value, sizeof(value)))		wstats->discard.code += value;	if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_RETRY_COUNT,				  &value, sizeof(value)))		wstats->discard.retries	= value;	if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_FAILED_COUNT,				  &value, sizeof(value)))		wstats->discard.misc += value;	if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_RTS_FAILURE_COUNT,				  &value, sizeof(value)))		wstats->discard.misc += value;	if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_ACK_FAILURE_COUNT,				  &value, sizeof(value)))		wstats->discard.misc += value;	if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_FRAME_DUPLICATE_COUNT,				  &value, sizeof(value)))		wstats->discard.misc += value;	return wstats;}static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info){	strlcpy(info->driver, wl3501_dev_info, sizeof(info->driver));}static struct ethtool_ops ops = {	.get_drvinfo = wl3501_get_drvinfo};/** * wl3501_detach - deletes a driver "instance" * @link - FILL_IN * * This deletes a driver "instance". The device is de-registered with Card * Services. If it has been released, all local data structures are freed. * Otherwise, the structures will be freed when the device is released. */static void wl3501_detach(dev_link_t *link){	dev_link_t **linkp;	/* Locate device structure */	for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)		if (*linkp == link)			break;	if (!*linkp)		goto out;	/* If the device is currently configured and active, we won't actually	 * delete it yet.  Instead, it is marked so that when the release()	 * function is called, that will trigger a proper detach(). */	if (link->state & DEV_CONFIG) {#ifdef PCMCIA_DEBUG		printk(KERN_DEBUG "wl3501_cs: detach postponed, '%s' "		       "still locked\n", link->dev->dev_name);#endif		goto out;	}	/* Break the link with Card Services */	if (link->handle)		pcmcia_deregister_client(link->handle);	/* Unlink device structure, free pieces */	*linkp = link->next;	if (link->priv)		free_netdev(link->priv);	kfree(link);out:	return;}static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	strlcpy(wrqu->name, "IEEE 802.11-DS", sizeof(wrqu->name));	return 0;}static int wl3501_set_freq(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	int channel = wrqu->freq.m;	int rc = -EINVAL;	if (iw_valid_channel(this->reg_domain, channel)) {		this->chan = channel;		rc = wl3501_reset(dev);	}	return rc;}static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	wrqu->freq.m = wl3501_chan2freq[this->chan - 1] * 100000;	wrqu->freq.e = 1;	return 0;}static int wl3501_set_mode(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	int rc = -EINVAL;	if (wrqu->mode == IW_MODE_INFRA ||	    wrqu->mode == IW_MODE_ADHOC ||	    wrqu->mode == IW_MODE_AUTO) {		struct wl3501_card *this = dev->priv;		this->net_type = wrqu->mode;		rc = wl3501_reset(dev);	}	return rc;}static int wl3501_get_mode(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	wrqu->mode = this->net_type;	return 0;}static int wl3501_get_sens(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	wrqu->sens.value = this->rssi;	wrqu->sens.disabled = !wrqu->sens.value;	wrqu->sens.fixed = 1;	return 0;}static int wl3501_get_range(struct net_device *dev,			    struct iw_request_info *info,			    union iwreq_data *wrqu, char *extra){	struct iw_range *range = (struct iw_range *)extra;	/* Set the length (very important for backward compatibility) */	wrqu->data.length = sizeof(*range);	/* Set all the info we don't care or don't know about to zero */	memset(range, 0, sizeof(*range));	/* Set the Wireless Extension versions */	range->we_version_compiled	= WIRELESS_EXT;	range->we_version_source	= 1;	range->throughput		= 2 * 1000 * 1000;     /* ~2 Mb/s */	/* FIXME: study the code to fill in more fields... */	return 0;}static int wl3501_set_wap(struct net_device *dev, struct iw_request_info *info,			  union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	static const u8 bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };	int rc = -EINVAL;	/* FIXME: we support other ARPHRDs...*/	if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)		goto out;	if (!memcmp(bcast, wrqu->ap_addr.sa_data, ETH_ALEN)) {		/* FIXME: rescan? */	} else		memcpy(this->bssid, wrqu->ap_addr.sa_data, ETH_ALEN);		/* FIXME: rescan? deassoc & scan? */	rc = 0;out:	return rc;}static int wl3501_get_wap(struct net_device *dev, struct iw_request_info *info,			  union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	wrqu->ap_addr.sa_family = ARPHRD_ETHER;	memcpy(wrqu->ap_addr.sa_data, this->bssid, ETH_ALEN);	return 0;}static int wl3501_set_scan(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	/*	 * FIXME: trigger scanning with a reset, yes, I'm lazy	 */	return wl3501_reset(dev);}static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	int i;	char *current_ev = extra;	struct iw_event iwe;	for (i = 0; i < this->bss_cnt; ++i) {		iwe.cmd			= SIOCGIWAP;		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;		memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN);		current_ev = iwe_stream_add_event(current_ev,						  extra + IW_SCAN_MAX_DATA,						  &iwe, IW_EV_ADDR_LEN);		iwe.cmd		  = SIOCGIWESSID;		iwe.u.data.flags  = 1;		iwe.u.data.length = this->bss_set[i].ssid.el.len;		current_ev = iwe_stream_add_point(current_ev,						  extra + IW_SCAN_MAX_DATA,						  &iwe,						  this->bss_set[i].ssid.essid);		iwe.cmd	   = SIOCGIWMODE;		iwe.u.mode = this->bss_set[i].bss_type;		current_ev = iwe_stream_add_event(current_ev,						  extra + IW_SCAN_MAX_DATA,						  &iwe, IW_EV_UINT_LEN);		iwe.cmd = SIOCGIWFREQ;		iwe.u.freq.m = this->bss_set[i].ds_pset.chan;		iwe.u.freq.e = 0;		current_ev = iwe_stream_add_event(current_ev,						  extra + IW_SCAN_MAX_DATA,						  &iwe, IW_EV_FREQ_LEN);		iwe.cmd = SIOCGIWENCODE;		if (this->bss_set[i].cap_info & WL3501_MGMT_CAPABILITY_PRIVACY)			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;		else			iwe.u.data.flags = IW_ENCODE_DISABLED;		iwe.u.data.length = 0;		current_ev = iwe_stream_add_point(current_ev,						  extra + IW_SCAN_MAX_DATA,						  &iwe, NULL);	}	/* Length of data */	wrqu->data.length = (current_ev - extra);	wrqu->data.flags = 0; /* FIXME: set properly these flags */	return 0;}static int wl3501_set_essid(struct net_device *dev,			    struct iw_request_info *info,			    union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	if (wrqu->data.flags) {		iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID,					 &this->essid.el,					 extra, wrqu->data.length);	} else { /* We accept any ESSID */		iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID,					 &this->essid.el, "ANY", 3);	}	return wl3501_reset(dev);}static int wl3501_get_essid(struct net_device *dev,			    struct iw_request_info *info,			    union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	unsigned long flags;	spin_lock_irqsave(&this->lock, flags);	wrqu->essid.flags  = 1;	wrqu->essid.length = this->essid.el.len;	memcpy(extra, this->essid.essid, this->essid.el.len);	spin_unlock_irqrestore(&this->lock, flags);	return 0;}static int wl3501_set_nick(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	if (wrqu->data.length > sizeof(this->nick))		return -E2BIG;	strlcpy(this->nick, extra, wrqu->data.length);	return 0;}static int wl3501_get_nick(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wl3501_card *this = dev->priv;	strlcpy(extra, this->nick, 32);	wrqu->data.length = strlen(extra);	return 0;}static int wl3501_get_rate(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	/*	 * FIXME: have to see from where to get this info, perhaps this card	 * works at 1 Mbit/s too... for now leave at 2 Mbit/s that is the most	 * common with the Planet Access Points. -acme	 */	wrqu->bitrate.value = 2000000;	wrqu->bitrate.fixed = 1;	return 0;}static int wl3501_get_rts_threshold(struct net_device *dev,				    struct iw_request_info *info,				    union iwreq_data *wrqu, char *extra){	u16 threshold; /* size checked: it is u16 */	struct wl3501_card *this = dev->priv;	int rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_RTS_THRESHOLD,				      &threshold, sizeof(threshold));	if (!rc) {		wrqu->rts.value = threshold;		wrqu->rts.disabled = threshold >= 2347;		wrqu->rts.fixed = 1;	}	return rc;}static int wl3501_get_frag_threshold(struct net_device *dev,				     struct iw_request_info *info,				     union iwreq_data *wrqu, char *extra){	u16 threshold; /* size checked: it is u16 */	struct wl3501_card *this = dev->priv;	int rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_FRAG_THRESHOLD,				      &threshold, sizeof(threshold));	if (!rc) {		wrqu->frag.value = threshold;		wrqu->frag.disabled = threshold >= 2346;		wrqu->frag.fixed = 1;	}	return rc;}static int wl3501_get_txpow(struct net_device *dev,			    struct iw_request_info *info,			    union iwreq_data *wrqu, char *extra){	u16 txpow;	struct wl3501_card *this = dev->priv;	int rc = wl3501_get_mib_value(this,				      WL3501_MIB_ATTR_CURRENT_TX_PWR_LEVEL,				      &txpow, sizeof(txpow));	if (!rc) {

⌨️ 快捷键说明

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