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

📄 wl3501_cs.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		wrqu->txpower.value = txpow;		wrqu->txpower.disabled = 0;		/*		 * From the MIB values I think this can be configurable,		 * as it lists several tx power levels -acme		 */		wrqu->txpower.fixed = 0;		wrqu->txpower.flags = IW_TXPOW_MWATT;	}	return rc;}static int wl3501_get_retry(struct net_device *dev,			    struct iw_request_info *info,			    union iwreq_data *wrqu, char *extra){	u8 retry; /* size checked: it is u8 */	struct wl3501_card *this = dev->priv;	int rc = wl3501_get_mib_value(this,				      WL3501_MIB_ATTR_LONG_RETRY_LIMIT,				      &retry, sizeof(retry));	if (rc)		goto out;	if (wrqu->retry.flags & IW_RETRY_MAX) {		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;		goto set_value;	}	rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_SHORT_RETRY_LIMIT,				  &retry, sizeof(retry));	if (rc)		goto out;	wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;set_value:	wrqu->retry.value = retry;	wrqu->retry.disabled = 0;out:	return rc;}static int wl3501_get_encode(struct net_device *dev,			     struct iw_request_info *info,			     union iwreq_data *wrqu, char *extra){	u8 implemented, restricted, keys[100], len_keys, tocopy;	struct wl3501_card *this = dev->priv;	int rc = wl3501_get_mib_value(this,				      WL3501_MIB_ATTR_PRIV_OPT_IMPLEMENTED,				      &implemented, sizeof(implemented));	if (rc)		goto out;	if (!implemented) {		wrqu->encoding.flags = IW_ENCODE_DISABLED;		goto out;	}	rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_EXCLUDE_UNENCRYPTED,				  &restricted, sizeof(restricted));	if (rc)		goto out;	wrqu->encoding.flags = restricted ? IW_ENCODE_RESTRICTED :					    IW_ENCODE_OPEN;	rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_KEY_MAPPINGS_LEN,				  &len_keys, sizeof(len_keys));	if (rc)		goto out;	rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_KEY_MAPPINGS,				  keys, len_keys);	if (rc)		goto out;	tocopy = min_t(u8, len_keys, wrqu->encoding.length);	tocopy = min_t(u8, tocopy, 100);	wrqu->encoding.length = tocopy;	memset(extra, 0, tocopy);	memcpy(extra, keys, tocopy);out:	return rc;}static int wl3501_get_power(struct net_device *dev,			    struct iw_request_info *info,			    union iwreq_data *wrqu, char *extra){	u8 pwr_state;	struct wl3501_card *this = dev->priv;	int rc = wl3501_get_mib_value(this,				      WL3501_MIB_ATTR_CURRENT_PWR_STATE,				      &pwr_state, sizeof(pwr_state));	if (rc)		goto out;	wrqu->power.disabled = !pwr_state;	wrqu->power.flags = IW_POWER_ON;out:	return rc;}static const iw_handler	wl3501_handler[] = {	[SIOCGIWNAME	- SIOCIWFIRST] = wl3501_get_name,	[SIOCSIWFREQ	- SIOCIWFIRST] = wl3501_set_freq,	[SIOCGIWFREQ	- SIOCIWFIRST] = wl3501_get_freq,	[SIOCSIWMODE	- SIOCIWFIRST] = wl3501_set_mode,	[SIOCGIWMODE	- SIOCIWFIRST] = wl3501_get_mode,	[SIOCGIWSENS	- SIOCIWFIRST] = wl3501_get_sens,	[SIOCGIWRANGE	- SIOCIWFIRST] = wl3501_get_range,	[SIOCSIWSPY	- SIOCIWFIRST] = iw_handler_set_spy,	[SIOCGIWSPY	- SIOCIWFIRST] = iw_handler_get_spy,	[SIOCSIWTHRSPY	- SIOCIWFIRST] = iw_handler_set_thrspy,	[SIOCGIWTHRSPY	- SIOCIWFIRST] = iw_handler_get_thrspy,	[SIOCSIWAP	- SIOCIWFIRST] = wl3501_set_wap,	[SIOCGIWAP	- SIOCIWFIRST] = wl3501_get_wap,	[SIOCSIWSCAN	- SIOCIWFIRST] = wl3501_set_scan,	[SIOCGIWSCAN	- SIOCIWFIRST] = wl3501_get_scan,	[SIOCSIWESSID	- SIOCIWFIRST] = wl3501_set_essid,	[SIOCGIWESSID	- SIOCIWFIRST] = wl3501_get_essid,	[SIOCSIWNICKN	- SIOCIWFIRST] = wl3501_set_nick,	[SIOCGIWNICKN	- SIOCIWFIRST] = wl3501_get_nick,	[SIOCGIWRATE	- SIOCIWFIRST] = wl3501_get_rate,	[SIOCGIWRTS	- SIOCIWFIRST] = wl3501_get_rts_threshold,	[SIOCGIWFRAG	- SIOCIWFIRST] = wl3501_get_frag_threshold,	[SIOCGIWTXPOW	- SIOCIWFIRST] = wl3501_get_txpow,	[SIOCGIWRETRY	- SIOCIWFIRST] = wl3501_get_retry,	[SIOCGIWENCODE	- SIOCIWFIRST] = wl3501_get_encode,	[SIOCGIWPOWER	- SIOCIWFIRST] = wl3501_get_power,};static const struct iw_handler_def wl3501_handler_def = {	.num_standard	= sizeof(wl3501_handler) / sizeof(iw_handler),	.standard	= (iw_handler *)wl3501_handler,	.spy_offset	= offsetof(struct wl3501_card, spy_data),};/** * wl3501_attach - creates an "instance" of the driver * * Creates an "instance" of the driver, allocating local data structures for * one device.  The device is registered with Card Services. * * The dev_link structure is initialized, but we don't actually configure the * card at this point -- we wait until we receive a card insertion event. */static dev_link_t *wl3501_attach(void){	client_reg_t client_reg;	dev_link_t *link;	struct net_device *dev;	int ret;	/* Initialize the dev_link_t structure */	link = kmalloc(sizeof(*link), GFP_KERNEL);	if (!link)		goto out;	memset(link, 0, sizeof(struct dev_link_t));	/* The io structure describes IO port mapping */	link->io.NumPorts1	= 16;	link->io.Attributes1	= IO_DATA_PATH_WIDTH_8;	link->io.IOAddrLines	= 5;	/* Interrupt setup */	link->irq.Attributes	= IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;	link->irq.IRQInfo1	= IRQ_LEVEL_ID;	link->irq.Handler = wl3501_interrupt;	/* General socket configuration */	link->conf.Attributes	= CONF_ENABLE_IRQ;	link->conf.Vcc		= 50;	link->conf.IntType	= INT_MEMORY_AND_IO;	link->conf.ConfigIndex	= 1;	link->conf.Present	= PRESENT_OPTION;	dev = alloc_etherdev(sizeof(struct wl3501_card));	if (!dev)		goto out_link;	dev->open		= wl3501_open;	dev->stop		= wl3501_close;	dev->hard_start_xmit	= wl3501_hard_start_xmit;	dev->tx_timeout		= wl3501_tx_timeout;	dev->watchdog_timeo	= 5 * HZ;	dev->get_stats		= wl3501_get_stats;	dev->get_wireless_stats = wl3501_get_wireless_stats;	dev->wireless_handlers	= (struct iw_handler_def *)&wl3501_handler_def;	SET_ETHTOOL_OPS(dev, &ops);	netif_stop_queue(dev);	link->priv = link->irq.Instance = dev;	/* Register with Card Services */	link->next		 = wl3501_dev_list;	wl3501_dev_list		 = link;	client_reg.dev_info	 = &wl3501_dev_info;	client_reg.EventMask	 = CS_EVENT_CARD_INSERTION |				   CS_EVENT_RESET_PHYSICAL |				   CS_EVENT_CARD_RESET |				   CS_EVENT_CARD_REMOVAL |				   CS_EVENT_PM_SUSPEND |				   CS_EVENT_PM_RESUME;	client_reg.event_handler = wl3501_event;	client_reg.Version	 = 0x0210;	client_reg.event_callback_args.client_data = link;	ret = pcmcia_register_client(&link->handle, &client_reg);	if (ret) {		cs_error(link->handle, RegisterClient, ret);		wl3501_detach(link);		link = NULL;	}out:	return link;out_link:	kfree(link);	link = NULL;	goto out;}#define CS_CHECK(fn, ret) \do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)/** * wl3501_config - configure the PCMCIA socket and make eth device available * @link - FILL_IN * * wl3501_config() is scheduled to run after a CARD_INSERTION event is * received, to configure the PCMCIA socket, and to make the ethernet device * available to the system. */static void wl3501_config(dev_link_t *link){	tuple_t tuple;	cisparse_t parse;	client_handle_t handle = link->handle;	struct net_device *dev = link->priv;	int i = 0, j, last_fn, last_ret;	unsigned char bf[64];	struct wl3501_card *this;	/* This reads the card's CONFIG tuple to find its config registers. */	tuple.Attributes	= 0;	tuple.DesiredTuple	= CISTPL_CONFIG;	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));	tuple.TupleData		= bf;	tuple.TupleDataMax	= sizeof(bf);	tuple.TupleOffset	= 0;	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));	link->conf.ConfigBase	= parse.config.base;	link->conf.Present	= parse.config.rmask[0];	/* Configure card */	link->state |= DEV_CONFIG;	/* Try allocating IO ports.  This tries a few fixed addresses.  If you	 * want, you can also read the card's config table to pick addresses --	 * see the serial driver for an example. */	for (j = 0x280; j < 0x400; j += 0x20) {		/* The '^0x300' is so that we probe 0x300-0x3ff first, then		 * 0x200-0x2ff, and so on, because this seems safer */		link->io.BasePort1 = j;		link->io.BasePort2 = link->io.BasePort1 + 0x10;		i = pcmcia_request_io(link->handle, &link->io);		if (i == CS_SUCCESS)			break;	}	if (i != CS_SUCCESS) {		cs_error(link->handle, RequestIO, i);		goto failed;	}	/* Now allocate an interrupt line. Note that this does not actually	 * assign a handler to the interrupt. */	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));	/* This actually configures the PCMCIA socket -- setting up the I/O	 * windows and the interrupt mapping.  */	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));	dev->irq = link->irq.AssignedIRQ;	dev->base_addr = link->io.BasePort1;	SET_NETDEV_DEV(dev, &handle_to_dev(handle));	if (register_netdev(dev)) {		printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");		goto failed;	}	SET_MODULE_OWNER(dev);	this = dev->priv;	/*	 * At this point, the dev_node_t structure(s) should be initialized and	 * arranged in a linked list at link->dev.	 */	link->dev = &this->node;	link->state &= ~DEV_CONFIG_PENDING;	this->base_addr = dev->base_addr;	if (!wl3501_get_flash_mac_addr(this)) {		printk(KERN_WARNING "%s: Cant read MAC addr in flash ROM?\n",		       dev->name);		goto failed;	}	strcpy(this->node.dev_name, dev->name);	/* print probe information */	printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, MAC addr in flash ROM:",	       dev->name, this->base_addr, (int)dev->irq);	for (i = 0; i < 6; i++) {		dev->dev_addr[i] = ((char *)&this->mac_addr)[i];		printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);	}	printk("\n");	/*	 * Initialize card parameters - added by jss	 */	this->net_type		= IW_MODE_INFRA;	this->bss_cnt		= 0;	this->join_sta_bss	= 0;	this->adhoc_times	= 0;	iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID, &this->essid.el,				 "ANY", 3);	this->card_name[0]	= '\0';	this->firmware_date[0]	= '\0';	this->rssi		= 255;	this->chan		= iw_default_channel(this->reg_domain);	strlcpy(this->nick, "Planet WL3501", sizeof(this->nick));	spin_lock_init(&this->lock);	init_waitqueue_head(&this->wait);	netif_start_queue(dev);	goto out;cs_failed:	cs_error(link->handle, last_fn, last_ret);failed:	wl3501_release(link);out:	return;}/** * wl3501_release - unregister the net, release PCMCIA configuration * @arg - link * * After a card is removed, wl3501_release() will unregister the net device, * and release the PCMCIA configuration.  If the device is still open, this * will be postponed until it is closed. */static void wl3501_release(dev_link_t *link){	struct net_device *dev = link->priv;	/* Unlink the device chain */	if (link->dev) {		unregister_netdev(dev);		link->dev = NULL;	}	/* Don't bother checking to see if these succeed or not */	pcmcia_release_configuration(link->handle);	pcmcia_release_io(link->handle, &link->io);	pcmcia_release_irq(link->handle, &link->irq);	link->state &= ~DEV_CONFIG;}/** * wl3501_event - The card status event handler * @event - event * @pri - priority * @args - arguments for this event * * The card status event handler. Mostly, this schedules other stuff to run * after an event is received. A CARD_REMOVAL event also sets some flags to * discourage the net drivers from trying to talk to the card any more. * * When a CARD_REMOVAL event is received, we immediately set a flag to block * future accesses to this device. All the functions that actually access the * device should check this flag to make sure the card is still present. */static int wl3501_event(event_t event, int pri, event_callback_args_t *args){	dev_link_t *link = args->client_data;	struct net_device *dev = link->priv;	switch (event) {	case CS_EVENT_CARD_REMOVAL:		link->state &= ~DEV_PRESENT;		if (link->state & DEV_CONFIG) {			while (link->open > 0)				wl3501_close(dev);			netif_device_detach(dev);			wl3501_release(link);		}		break;	case CS_EVENT_CARD_INSERTION:		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;		wl3501_config(link);		break;	case CS_EVENT_PM_SUSPEND:		link->state |= DEV_SUSPEND;		wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);		/* Fall through... */	case CS_EVENT_RESET_PHYSICAL:		if (link->state & DEV_CONFIG) {			if (link->open)				netif_device_detach(dev);			pcmcia_release_configuration(link->handle);		}		break;	case CS_EVENT_PM_RESUME:		link->state &= ~DEV_SUSPEND;		wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);		/* Fall through... */	case CS_EVENT_CARD_RESET:		if (link->state & DEV_CONFIG) {			pcmcia_request_configuration(link->handle, &link->conf);			if (link->open) {				wl3501_reset(dev);				netif_device_attach(dev);			}		}		break;	}	return 0;}static struct pcmcia_driver wl3501_driver = {	.owner          = THIS_MODULE,	.drv            = {		.name   = "wl3501_cs",	},	.attach         = wl3501_attach,	.detach         = wl3501_detach,};static int __init wl3501_init_module(void){	return pcmcia_register_driver(&wl3501_driver);}static void __exit wl3501_exit_module(void){	dprintk(0, ": unloading");	pcmcia_unregister_driver(&wl3501_driver);	BUG_ON(wl3501_dev_list != NULL);}module_init(wl3501_init_module);module_exit(wl3501_exit_module);MODULE_AUTHOR("Fox Chen <mhchen@golf.ccl.itri.org.tw>, "	      "Arnaldo Carvalho de Melo <acme@conectiva.com.br>,"	      "Gustavo Niemeyer <niemeyer@conectiva.com>");MODULE_DESCRIPTION("Planet wl3501 wireless driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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