130db0ca8SKalle Valo /*======================================================================
230db0ca8SKalle Valo 
330db0ca8SKalle Valo     Aironet driver for 4500 and 4800 series cards
430db0ca8SKalle Valo 
530db0ca8SKalle Valo     This code is released under both the GPL version 2 and BSD licenses.
630db0ca8SKalle Valo     Either license may be used.  The respective licenses are found at
730db0ca8SKalle Valo     the end of this file.
830db0ca8SKalle Valo 
930db0ca8SKalle Valo     This code was developed by Benjamin Reed <breed@users.sourceforge.net>
1030db0ca8SKalle Valo     including portions of which come from the Aironet PC4500
1130db0ca8SKalle Valo     Developer's Reference Manual and used with permission.  Copyright
1230db0ca8SKalle Valo     (C) 1999 Benjamin Reed.  All Rights Reserved.  Permission to use
1330db0ca8SKalle Valo     code in the Developer's manual was granted for this driver by
1430db0ca8SKalle Valo     Aironet.
1530db0ca8SKalle Valo 
1630db0ca8SKalle Valo     In addition this module was derived from dummy_cs.
1730db0ca8SKalle Valo     The initial developer of dummy_cs is David A. Hinds
1830db0ca8SKalle Valo     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
1930db0ca8SKalle Valo     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
2030db0ca8SKalle Valo 
2130db0ca8SKalle Valo ======================================================================*/
2230db0ca8SKalle Valo 
2330db0ca8SKalle Valo #ifdef __IN_PCMCIA_PACKAGE__
2430db0ca8SKalle Valo #include <pcmcia/k_compat.h>
2530db0ca8SKalle Valo #endif
2630db0ca8SKalle Valo #include <linux/kernel.h>
2730db0ca8SKalle Valo #include <linux/module.h>
2830db0ca8SKalle Valo #include <linux/ptrace.h>
2930db0ca8SKalle Valo #include <linux/slab.h>
3030db0ca8SKalle Valo #include <linux/string.h>
3130db0ca8SKalle Valo #include <linux/timer.h>
3230db0ca8SKalle Valo #include <linux/netdevice.h>
3330db0ca8SKalle Valo 
3430db0ca8SKalle Valo #include <pcmcia/cistpl.h>
3530db0ca8SKalle Valo #include <pcmcia/cisreg.h>
3630db0ca8SKalle Valo #include <pcmcia/ds.h>
3730db0ca8SKalle Valo 
3830db0ca8SKalle Valo #include <linux/io.h>
3930db0ca8SKalle Valo 
4030db0ca8SKalle Valo #include "airo.h"
4130db0ca8SKalle Valo 
4230db0ca8SKalle Valo 
4330db0ca8SKalle Valo /*====================================================================*/
4430db0ca8SKalle Valo 
4530db0ca8SKalle Valo MODULE_AUTHOR("Benjamin Reed");
4630db0ca8SKalle Valo MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet "
4730db0ca8SKalle Valo 		   "cards.  This is the module that links the PCMCIA card "
4830db0ca8SKalle Valo 		   "with the airo module.");
4930db0ca8SKalle Valo MODULE_LICENSE("Dual BSD/GPL");
5030db0ca8SKalle Valo 
5130db0ca8SKalle Valo /*====================================================================*/
5230db0ca8SKalle Valo 
5330db0ca8SKalle Valo static int airo_config(struct pcmcia_device *link);
5430db0ca8SKalle Valo static void airo_release(struct pcmcia_device *link);
5530db0ca8SKalle Valo 
5630db0ca8SKalle Valo static void airo_detach(struct pcmcia_device *p_dev);
5730db0ca8SKalle Valo 
5830db0ca8SKalle Valo struct local_info {
5930db0ca8SKalle Valo 	struct net_device *eth_dev;
6030db0ca8SKalle Valo };
6130db0ca8SKalle Valo 
airo_probe(struct pcmcia_device * p_dev)6230db0ca8SKalle Valo static int airo_probe(struct pcmcia_device *p_dev)
6330db0ca8SKalle Valo {
6430db0ca8SKalle Valo 	struct local_info *local;
6530db0ca8SKalle Valo 
6630db0ca8SKalle Valo 	dev_dbg(&p_dev->dev, "airo_attach()\n");
6730db0ca8SKalle Valo 
6830db0ca8SKalle Valo 	/* Allocate space for private device-specific data */
6930db0ca8SKalle Valo 	local = kzalloc(sizeof(*local), GFP_KERNEL);
7030db0ca8SKalle Valo 	if (!local)
7130db0ca8SKalle Valo 		return -ENOMEM;
7230db0ca8SKalle Valo 
7330db0ca8SKalle Valo 	p_dev->priv = local;
7430db0ca8SKalle Valo 
7530db0ca8SKalle Valo 	return airo_config(p_dev);
7630db0ca8SKalle Valo } /* airo_attach */
7730db0ca8SKalle Valo 
airo_detach(struct pcmcia_device * link)7830db0ca8SKalle Valo static void airo_detach(struct pcmcia_device *link)
7930db0ca8SKalle Valo {
8030db0ca8SKalle Valo 	dev_dbg(&link->dev, "airo_detach\n");
8130db0ca8SKalle Valo 
8230db0ca8SKalle Valo 	airo_release(link);
8330db0ca8SKalle Valo 
8430db0ca8SKalle Valo 	if (((struct local_info *)link->priv)->eth_dev) {
8530db0ca8SKalle Valo 		stop_airo_card(((struct local_info *)link->priv)->eth_dev,
8630db0ca8SKalle Valo 			       0);
8730db0ca8SKalle Valo 	}
8830db0ca8SKalle Valo 	((struct local_info *)link->priv)->eth_dev = NULL;
8930db0ca8SKalle Valo 
9030db0ca8SKalle Valo 	kfree(link->priv);
9130db0ca8SKalle Valo } /* airo_detach */
9230db0ca8SKalle Valo 
airo_cs_config_check(struct pcmcia_device * p_dev,void * priv_data)9330db0ca8SKalle Valo static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
9430db0ca8SKalle Valo {
9530db0ca8SKalle Valo 	if (p_dev->config_index == 0)
9630db0ca8SKalle Valo 		return -EINVAL;
9730db0ca8SKalle Valo 
9830db0ca8SKalle Valo 	return pcmcia_request_io(p_dev);
9930db0ca8SKalle Valo }
10030db0ca8SKalle Valo 
10130db0ca8SKalle Valo 
airo_config(struct pcmcia_device * link)10230db0ca8SKalle Valo static int airo_config(struct pcmcia_device *link)
10330db0ca8SKalle Valo {
10430db0ca8SKalle Valo 	int ret;
10530db0ca8SKalle Valo 
10630db0ca8SKalle Valo 	dev_dbg(&link->dev, "airo_config\n");
10730db0ca8SKalle Valo 
10830db0ca8SKalle Valo 	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
10930db0ca8SKalle Valo 		CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
11030db0ca8SKalle Valo 
11130db0ca8SKalle Valo 	ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
11230db0ca8SKalle Valo 	if (ret)
11330db0ca8SKalle Valo 		goto failed;
11430db0ca8SKalle Valo 
11530db0ca8SKalle Valo 	if (!link->irq)
11630db0ca8SKalle Valo 		goto failed;
11730db0ca8SKalle Valo 
11830db0ca8SKalle Valo 	ret = pcmcia_enable_device(link);
11930db0ca8SKalle Valo 	if (ret)
12030db0ca8SKalle Valo 		goto failed;
12130db0ca8SKalle Valo 	((struct local_info *)link->priv)->eth_dev =
12230db0ca8SKalle Valo 		init_airo_card(link->irq,
12330db0ca8SKalle Valo 			       link->resource[0]->start, 1, &link->dev);
12430db0ca8SKalle Valo 	if (!((struct local_info *)link->priv)->eth_dev)
12530db0ca8SKalle Valo 		goto failed;
12630db0ca8SKalle Valo 
12730db0ca8SKalle Valo 	return 0;
12830db0ca8SKalle Valo 
12930db0ca8SKalle Valo  failed:
13030db0ca8SKalle Valo 	airo_release(link);
13130db0ca8SKalle Valo 	return -ENODEV;
13230db0ca8SKalle Valo } /* airo_config */
13330db0ca8SKalle Valo 
airo_release(struct pcmcia_device * link)13430db0ca8SKalle Valo static void airo_release(struct pcmcia_device *link)
13530db0ca8SKalle Valo {
13630db0ca8SKalle Valo 	dev_dbg(&link->dev, "airo_release\n");
13730db0ca8SKalle Valo 	pcmcia_disable_device(link);
13830db0ca8SKalle Valo }
13930db0ca8SKalle Valo 
airo_suspend(struct pcmcia_device * link)14030db0ca8SKalle Valo static int airo_suspend(struct pcmcia_device *link)
14130db0ca8SKalle Valo {
14230db0ca8SKalle Valo 	struct local_info *local = link->priv;
14330db0ca8SKalle Valo 
14430db0ca8SKalle Valo 	netif_device_detach(local->eth_dev);
14530db0ca8SKalle Valo 
14630db0ca8SKalle Valo 	return 0;
14730db0ca8SKalle Valo }
14830db0ca8SKalle Valo 
airo_resume(struct pcmcia_device * link)14930db0ca8SKalle Valo static int airo_resume(struct pcmcia_device *link)
15030db0ca8SKalle Valo {
15130db0ca8SKalle Valo 	struct local_info *local = link->priv;
15230db0ca8SKalle Valo 
15330db0ca8SKalle Valo 	if (link->open) {
15430db0ca8SKalle Valo 		reset_airo_card(local->eth_dev);
15530db0ca8SKalle Valo 		netif_device_attach(local->eth_dev);
15630db0ca8SKalle Valo 	}
15730db0ca8SKalle Valo 
15830db0ca8SKalle Valo 	return 0;
15930db0ca8SKalle Valo }
16030db0ca8SKalle Valo 
16130db0ca8SKalle Valo static const struct pcmcia_device_id airo_ids[] = {
16230db0ca8SKalle Valo 	PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
16330db0ca8SKalle Valo 	PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005),
16430db0ca8SKalle Valo 	PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007),
16530db0ca8SKalle Valo 	PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007),
16630db0ca8SKalle Valo 	PCMCIA_DEVICE_NULL,
16730db0ca8SKalle Valo };
16830db0ca8SKalle Valo MODULE_DEVICE_TABLE(pcmcia, airo_ids);
16930db0ca8SKalle Valo 
17030db0ca8SKalle Valo static struct pcmcia_driver airo_driver = {
17130db0ca8SKalle Valo 	.owner		= THIS_MODULE,
17230db0ca8SKalle Valo 	.name		= "airo_cs",
17330db0ca8SKalle Valo 	.probe		= airo_probe,
17430db0ca8SKalle Valo 	.remove		= airo_detach,
17530db0ca8SKalle Valo 	.id_table       = airo_ids,
17630db0ca8SKalle Valo 	.suspend	= airo_suspend,
17730db0ca8SKalle Valo 	.resume		= airo_resume,
17830db0ca8SKalle Valo };
17930db0ca8SKalle Valo module_pcmcia_driver(airo_driver);
18030db0ca8SKalle Valo 
18130db0ca8SKalle Valo /*
18230db0ca8SKalle Valo     This program is free software; you can redistribute it and/or
18330db0ca8SKalle Valo     modify it under the terms of the GNU General Public License
18430db0ca8SKalle Valo     as published by the Free Software Foundation; either version 2
18530db0ca8SKalle Valo     of the License, or (at your option) any later version.
18630db0ca8SKalle Valo 
18730db0ca8SKalle Valo     This program is distributed in the hope that it will be useful,
18830db0ca8SKalle Valo     but WITHOUT ANY WARRANTY; without even the implied warranty of
18930db0ca8SKalle Valo     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19030db0ca8SKalle Valo     GNU General Public License for more details.
19130db0ca8SKalle Valo 
19230db0ca8SKalle Valo     In addition:
19330db0ca8SKalle Valo 
19430db0ca8SKalle Valo     Redistribution and use in source and binary forms, with or without
19530db0ca8SKalle Valo     modification, are permitted provided that the following conditions
19630db0ca8SKalle Valo     are met:
19730db0ca8SKalle Valo 
19830db0ca8SKalle Valo     1. Redistributions of source code must retain the above copyright
19930db0ca8SKalle Valo        notice, this list of conditions and the following disclaimer.
20030db0ca8SKalle Valo     2. Redistributions in binary form must reproduce the above copyright
20130db0ca8SKalle Valo        notice, this list of conditions and the following disclaimer in the
20230db0ca8SKalle Valo        documentation and/or other materials provided with the distribution.
20330db0ca8SKalle Valo     3. The name of the author may not be used to endorse or promote
20430db0ca8SKalle Valo        products derived from this software without specific prior written
20530db0ca8SKalle Valo        permission.
20630db0ca8SKalle Valo 
20730db0ca8SKalle Valo     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20830db0ca8SKalle Valo     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20930db0ca8SKalle Valo     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21030db0ca8SKalle Valo     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21130db0ca8SKalle Valo     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21230db0ca8SKalle Valo     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21330db0ca8SKalle Valo     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21430db0ca8SKalle Valo     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21530db0ca8SKalle Valo     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
21630db0ca8SKalle Valo     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21730db0ca8SKalle Valo     POSSIBILITY OF SUCH DAMAGE.
21830db0ca8SKalle Valo */
219