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");
50
51
52
53static int airo_config(struct pcmcia_device *link);
54static void airo_release(struct pcmcia_device *link);
55
56static void airo_detach(struct pcmcia_device *p_dev);
57
58struct local_info {
59 struct net_device *eth_dev;
60};
61
62static int airo_probe(struct pcmcia_device *p_dev)
63{
64 struct local_info *local;
65
66 dev_dbg(&p_dev->dev, "airo_attach()\n");
67
68
69 local = kzalloc(sizeof(*local), GFP_KERNEL);
70 if (!local)
71 return -ENOMEM;
72
73 p_dev->priv = local;
74
75 return airo_config(p_dev);
76}
77
78static void airo_detach(struct pcmcia_device *link)
79{
80 dev_dbg(&link->dev, "airo_detach\n");
81
82 airo_release(link);
83
84 if (((struct local_info *)link->priv)->eth_dev) {
85 stop_airo_card(((struct local_info *)link->priv)->eth_dev,
86 0);
87 }
88 ((struct local_info *)link->priv)->eth_dev = NULL;
89
90 kfree(link->priv);
91}
92
93static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
94{
95 if (p_dev->config_index == 0)
96 return -EINVAL;
97
98 return pcmcia_request_io(p_dev);
99}
100
101
102static int airo_config(struct pcmcia_device *link)
103{
104 int ret;
105
106 dev_dbg(&link->dev, "airo_config\n");
107
108 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
109 CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
110
111 ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
112 if (ret)
113 goto failed;
114
115 if (!link->irq)
116 goto failed;
117
118 ret = pcmcia_enable_device(link);
119 if (ret)
120 goto failed;
121 ((struct local_info *)link->priv)->eth_dev =
122 init_airo_card(link->irq,
123 link->resource[0]->start, 1, &link->dev);
124 if (!((struct local_info *)link->priv)->eth_dev)
125 goto failed;
126
127 return 0;
128
129 failed:
130 airo_release(link);
131 return -ENODEV;
132}
133
134static void airo_release(struct pcmcia_device *link)
135{
136 dev_dbg(&link->dev, "airo_release\n");
137 pcmcia_disable_device(link);
138}
139
140static int airo_suspend(struct pcmcia_device *link)
141{
142 struct local_info *local = link->priv;
143
144 netif_device_detach(local->eth_dev);
145
146 return 0;
147}
148
149static int airo_resume(struct pcmcia_device *link)
150{
151 struct local_info *local = link->priv;
152
153 if (link->open) {
154 reset_airo_card(local->eth_dev);
155 netif_device_attach(local->eth_dev);
156 }
157
158 return 0;
159}
160
161static const struct pcmcia_device_id airo_ids[] = {
162 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
163 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005),
164 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007),
165 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007),
166 PCMCIA_DEVICE_NULL,
167};
168MODULE_DEVICE_TABLE(pcmcia, airo_ids);
169
170static struct pcmcia_driver airo_driver = {
171 .owner = THIS_MODULE,
172 .name = "airo_cs",
173 .probe = airo_probe,
174 .remove = airo_detach,
175 .id_table = airo_ids,
176 .suspend = airo_suspend,
177 .resume = airo_resume,
178};
179module_pcmcia_driver(airo_driver);
180
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