1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#ifdef __IN_PCMCIA_PACKAGE__
24#include <pcmcia/k_compat.h>
25#endif
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/ptrace.h>
29#include <linux/slab.h>
30#include <linux/string.h>
31#include <linux/timer.h>
32#include <linux/netdevice.h>
33
34#include <pcmcia/cistpl.h>
35#include <pcmcia/cisreg.h>
36#include <pcmcia/ds.h>
37
38#include <linux/io.h>
39
40#include "airo.h"
41
42
43
44
45MODULE_AUTHOR("Benjamin Reed");
46MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet "
47 "cards. This is the module that links the PCMCIA card "
48 "with the airo module.");
49MODULE_LICENSE("Dual BSD/GPL");
50MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
51
52
53
54static int airo_config(struct pcmcia_device *link);
55static void airo_release(struct pcmcia_device *link);
56
57static void airo_detach(struct pcmcia_device *p_dev);
58
59struct local_info {
60 struct net_device *eth_dev;
61};
62
63static int airo_probe(struct pcmcia_device *p_dev)
64{
65 struct local_info *local;
66
67 dev_dbg(&p_dev->dev, "airo_attach()\n");
68
69
70 local = kzalloc(sizeof(*local), GFP_KERNEL);
71 if (!local)
72 return -ENOMEM;
73
74 p_dev->priv = local;
75
76 return airo_config(p_dev);
77}
78
79static void airo_detach(struct pcmcia_device *link)
80{
81 dev_dbg(&link->dev, "airo_detach\n");
82
83 airo_release(link);
84
85 if (((struct local_info *)link->priv)->eth_dev) {
86 stop_airo_card(((struct local_info *)link->priv)->eth_dev,
87 0);
88 }
89 ((struct local_info *)link->priv)->eth_dev = NULL;
90
91 kfree(link->priv);
92}
93
94static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
95{
96 if (p_dev->config_index == 0)
97 return -EINVAL;
98
99 return pcmcia_request_io(p_dev);
100}
101
102
103static int airo_config(struct pcmcia_device *link)
104{
105 int ret;
106
107 dev_dbg(&link->dev, "airo_config\n");
108
109 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
110 CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
111
112 ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
113 if (ret)
114 goto failed;
115
116 if (!link->irq)
117 goto failed;
118
119 ret = pcmcia_enable_device(link);
120 if (ret)
121 goto failed;
122 ((struct local_info *)link->priv)->eth_dev =
123 init_airo_card(link->irq,
124 link->resource[0]->start, 1, &link->dev);
125 if (!((struct local_info *)link->priv)->eth_dev)
126 goto failed;
127
128 return 0;
129
130 failed:
131 airo_release(link);
132 return -ENODEV;
133}
134
135static void airo_release(struct pcmcia_device *link)
136{
137 dev_dbg(&link->dev, "airo_release\n");
138 pcmcia_disable_device(link);
139}
140
141static int airo_suspend(struct pcmcia_device *link)
142{
143 struct local_info *local = link->priv;
144
145 netif_device_detach(local->eth_dev);
146
147 return 0;
148}
149
150static int airo_resume(struct pcmcia_device *link)
151{
152 struct local_info *local = link->priv;
153
154 if (link->open) {
155 reset_airo_card(local->eth_dev);
156 netif_device_attach(local->eth_dev);
157 }
158
159 return 0;
160}
161
162static const struct pcmcia_device_id airo_ids[] = {
163 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
164 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005),
165 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007),
166 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007),
167 PCMCIA_DEVICE_NULL,
168};
169MODULE_DEVICE_TABLE(pcmcia, airo_ids);
170
171static struct pcmcia_driver airo_driver = {
172 .owner = THIS_MODULE,
173 .name = "airo_cs",
174 .probe = airo_probe,
175 .remove = airo_detach,
176 .id_table = airo_ids,
177 .suspend = airo_suspend,
178 .resume = airo_resume,
179};
180module_pcmcia_driver(airo_driver);
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220