18c2ecf20Sopenharmony_ci/*======================================================================
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci    Aironet driver for 4500 and 4800 series cards
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci    This code is released under both the GPL version 2 and BSD licenses.
68c2ecf20Sopenharmony_ci    Either license may be used.  The respective licenses are found at
78c2ecf20Sopenharmony_ci    the end of this file.
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci    This code was developed by Benjamin Reed <breed@users.sourceforge.net>
108c2ecf20Sopenharmony_ci    including portions of which come from the Aironet PC4500
118c2ecf20Sopenharmony_ci    Developer's Reference Manual and used with permission.  Copyright
128c2ecf20Sopenharmony_ci    (C) 1999 Benjamin Reed.  All Rights Reserved.  Permission to use
138c2ecf20Sopenharmony_ci    code in the Developer's manual was granted for this driver by
148c2ecf20Sopenharmony_ci    Aironet.
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci    In addition this module was derived from dummy_cs.
178c2ecf20Sopenharmony_ci    The initial developer of dummy_cs is David A. Hinds
188c2ecf20Sopenharmony_ci    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
198c2ecf20Sopenharmony_ci    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci======================================================================*/
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#ifdef __IN_PCMCIA_PACKAGE__
248c2ecf20Sopenharmony_ci#include <pcmcia/k_compat.h>
258c2ecf20Sopenharmony_ci#endif
268c2ecf20Sopenharmony_ci#include <linux/kernel.h>
278c2ecf20Sopenharmony_ci#include <linux/module.h>
288c2ecf20Sopenharmony_ci#include <linux/ptrace.h>
298c2ecf20Sopenharmony_ci#include <linux/slab.h>
308c2ecf20Sopenharmony_ci#include <linux/string.h>
318c2ecf20Sopenharmony_ci#include <linux/timer.h>
328c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include <pcmcia/cistpl.h>
358c2ecf20Sopenharmony_ci#include <pcmcia/cisreg.h>
368c2ecf20Sopenharmony_ci#include <pcmcia/ds.h>
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#include <linux/io.h>
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#include "airo.h"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/*====================================================================*/
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ciMODULE_AUTHOR("Benjamin Reed");
468c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet "
478c2ecf20Sopenharmony_ci		   "cards.  This is the module that links the PCMCIA card "
488c2ecf20Sopenharmony_ci		   "with the airo module.");
498c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
508c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/*====================================================================*/
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic int airo_config(struct pcmcia_device *link);
558c2ecf20Sopenharmony_cistatic void airo_release(struct pcmcia_device *link);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic void airo_detach(struct pcmcia_device *p_dev);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistruct local_info {
608c2ecf20Sopenharmony_ci	struct net_device *eth_dev;
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic int airo_probe(struct pcmcia_device *p_dev)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	struct local_info *local;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	dev_dbg(&p_dev->dev, "airo_attach()\n");
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	/* Allocate space for private device-specific data */
708c2ecf20Sopenharmony_ci	local = kzalloc(sizeof(*local), GFP_KERNEL);
718c2ecf20Sopenharmony_ci	if (!local)
728c2ecf20Sopenharmony_ci		return -ENOMEM;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	p_dev->priv = local;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	return airo_config(p_dev);
778c2ecf20Sopenharmony_ci} /* airo_attach */
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic void airo_detach(struct pcmcia_device *link)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	dev_dbg(&link->dev, "airo_detach\n");
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	airo_release(link);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	if (((struct local_info *)link->priv)->eth_dev) {
868c2ecf20Sopenharmony_ci		stop_airo_card(((struct local_info *)link->priv)->eth_dev,
878c2ecf20Sopenharmony_ci			       0);
888c2ecf20Sopenharmony_ci	}
898c2ecf20Sopenharmony_ci	((struct local_info *)link->priv)->eth_dev = NULL;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	kfree(link->priv);
928c2ecf20Sopenharmony_ci} /* airo_detach */
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	if (p_dev->config_index == 0)
978c2ecf20Sopenharmony_ci		return -EINVAL;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	return pcmcia_request_io(p_dev);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic int airo_config(struct pcmcia_device *link)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	int ret;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	dev_dbg(&link->dev, "airo_config\n");
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
1108c2ecf20Sopenharmony_ci		CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
1138c2ecf20Sopenharmony_ci	if (ret)
1148c2ecf20Sopenharmony_ci		goto failed;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	if (!link->irq)
1178c2ecf20Sopenharmony_ci		goto failed;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	ret = pcmcia_enable_device(link);
1208c2ecf20Sopenharmony_ci	if (ret)
1218c2ecf20Sopenharmony_ci		goto failed;
1228c2ecf20Sopenharmony_ci	((struct local_info *)link->priv)->eth_dev =
1238c2ecf20Sopenharmony_ci		init_airo_card(link->irq,
1248c2ecf20Sopenharmony_ci			       link->resource[0]->start, 1, &link->dev);
1258c2ecf20Sopenharmony_ci	if (!((struct local_info *)link->priv)->eth_dev)
1268c2ecf20Sopenharmony_ci		goto failed;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	return 0;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci failed:
1318c2ecf20Sopenharmony_ci	airo_release(link);
1328c2ecf20Sopenharmony_ci	return -ENODEV;
1338c2ecf20Sopenharmony_ci} /* airo_config */
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic void airo_release(struct pcmcia_device *link)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	dev_dbg(&link->dev, "airo_release\n");
1388c2ecf20Sopenharmony_ci	pcmcia_disable_device(link);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic int airo_suspend(struct pcmcia_device *link)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	struct local_info *local = link->priv;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	netif_device_detach(local->eth_dev);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	return 0;
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistatic int airo_resume(struct pcmcia_device *link)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	struct local_info *local = link->priv;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	if (link->open) {
1558c2ecf20Sopenharmony_ci		reset_airo_card(local->eth_dev);
1568c2ecf20Sopenharmony_ci		netif_device_attach(local->eth_dev);
1578c2ecf20Sopenharmony_ci	}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	return 0;
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic const struct pcmcia_device_id airo_ids[] = {
1638c2ecf20Sopenharmony_ci	PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
1648c2ecf20Sopenharmony_ci	PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005),
1658c2ecf20Sopenharmony_ci	PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007),
1668c2ecf20Sopenharmony_ci	PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007),
1678c2ecf20Sopenharmony_ci	PCMCIA_DEVICE_NULL,
1688c2ecf20Sopenharmony_ci};
1698c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pcmcia, airo_ids);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistatic struct pcmcia_driver airo_driver = {
1728c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
1738c2ecf20Sopenharmony_ci	.name		= "airo_cs",
1748c2ecf20Sopenharmony_ci	.probe		= airo_probe,
1758c2ecf20Sopenharmony_ci	.remove		= airo_detach,
1768c2ecf20Sopenharmony_ci	.id_table       = airo_ids,
1778c2ecf20Sopenharmony_ci	.suspend	= airo_suspend,
1788c2ecf20Sopenharmony_ci	.resume		= airo_resume,
1798c2ecf20Sopenharmony_ci};
1808c2ecf20Sopenharmony_cimodule_pcmcia_driver(airo_driver);
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci/*
1838c2ecf20Sopenharmony_ci    This program is free software; you can redistribute it and/or
1848c2ecf20Sopenharmony_ci    modify it under the terms of the GNU General Public License
1858c2ecf20Sopenharmony_ci    as published by the Free Software Foundation; either version 2
1868c2ecf20Sopenharmony_ci    of the License, or (at your option) any later version.
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci    This program is distributed in the hope that it will be useful,
1898c2ecf20Sopenharmony_ci    but WITHOUT ANY WARRANTY; without even the implied warranty of
1908c2ecf20Sopenharmony_ci    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1918c2ecf20Sopenharmony_ci    GNU General Public License for more details.
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci    In addition:
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci    Redistribution and use in source and binary forms, with or without
1968c2ecf20Sopenharmony_ci    modification, are permitted provided that the following conditions
1978c2ecf20Sopenharmony_ci    are met:
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci    1. Redistributions of source code must retain the above copyright
2008c2ecf20Sopenharmony_ci       notice, this list of conditions and the following disclaimer.
2018c2ecf20Sopenharmony_ci    2. Redistributions in binary form must reproduce the above copyright
2028c2ecf20Sopenharmony_ci       notice, this list of conditions and the following disclaimer in the
2038c2ecf20Sopenharmony_ci       documentation and/or other materials provided with the distribution.
2048c2ecf20Sopenharmony_ci    3. The name of the author may not be used to endorse or promote
2058c2ecf20Sopenharmony_ci       products derived from this software without specific prior written
2068c2ecf20Sopenharmony_ci       permission.
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2098c2ecf20Sopenharmony_ci    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2108c2ecf20Sopenharmony_ci    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2118c2ecf20Sopenharmony_ci    ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2128c2ecf20Sopenharmony_ci    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2138c2ecf20Sopenharmony_ci    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2148c2ecf20Sopenharmony_ci    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2158c2ecf20Sopenharmony_ci    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2168c2ecf20Sopenharmony_ci    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
2178c2ecf20Sopenharmony_ci    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2188c2ecf20Sopenharmony_ci    POSSIBILITY OF SUCH DAMAGE.
2198c2ecf20Sopenharmony_ci*/
220