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/init.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/ptrace.h>
30#include <linux/slab.h>
31#include <linux/string.h>
32#include <linux/timer.h>
33#include <linux/netdevice.h>
34
35#include <pcmcia/cistpl.h>
36#include <pcmcia/cisreg.h>
37#include <pcmcia/ds.h>
38
39#include <linux/io.h>
40
41#include "airo.h"
42
43
44
45
46MODULE_AUTHOR("Benjamin Reed");
47MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet "
48 "cards. This is the module that links the PCMCIA card "
49 "with the airo module.");
50MODULE_LICENSE("Dual BSD/GPL");
51MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
52
53
54
55static int airo_config(struct pcmcia_device *link);
56static void airo_release(struct pcmcia_device *link);
57
58static void airo_detach(struct pcmcia_device *p_dev);
59
60typedef struct local_info_t {
61 struct net_device *eth_dev;
62} local_info_t;
63
64static int airo_probe(struct pcmcia_device *p_dev)
65{
66 local_info_t *local;
67
68 dev_dbg(&p_dev->dev, "airo_attach()\n");
69
70
71 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
72 if (!local)
73 return -ENOMEM;
74
75 p_dev->priv = local;
76
77 return airo_config(p_dev);
78}
79
80static void airo_detach(struct pcmcia_device *link)
81{
82 dev_dbg(&link->dev, "airo_detach\n");
83
84 airo_release(link);
85
86 if (((local_info_t *)link->priv)->eth_dev) {
87 stop_airo_card(((local_info_t *)link->priv)->eth_dev, 0);
88 }
89 ((local_info_t *)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 local_info_t *dev;
106 int ret;
107
108 dev = link->priv;
109
110 dev_dbg(&link->dev, "airo_config\n");
111
112 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
113 CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
114
115 ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
116 if (ret)
117 goto failed;
118
119 if (!link->irq)
120 goto failed;
121
122 ret = pcmcia_enable_device(link);
123 if (ret)
124 goto failed;
125 ((local_info_t *)link->priv)->eth_dev =
126 init_airo_card(link->irq,
127 link->resource[0]->start, 1, &link->dev);
128 if (!((local_info_t *)link->priv)->eth_dev)
129 goto failed;
130
131 return 0;
132
133 failed:
134 airo_release(link);
135 return -ENODEV;
136}
137
138static void airo_release(struct pcmcia_device *link)
139{
140 dev_dbg(&link->dev, "airo_release\n");
141 pcmcia_disable_device(link);
142}
143
144static int airo_suspend(struct pcmcia_device *link)
145{
146 local_info_t *local = link->priv;
147
148 netif_device_detach(local->eth_dev);
149
150 return 0;
151}
152
153static int airo_resume(struct pcmcia_device *link)
154{
155 local_info_t *local = link->priv;
156
157 if (link->open) {
158 reset_airo_card(local->eth_dev);
159 netif_device_attach(local->eth_dev);
160 }
161
162 return 0;
163}
164
165static const struct pcmcia_device_id airo_ids[] = {
166 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
167 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005),
168 PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007),
169 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007),
170 PCMCIA_DEVICE_NULL,
171};
172MODULE_DEVICE_TABLE(pcmcia, airo_ids);
173
174static struct pcmcia_driver airo_driver = {
175 .owner = THIS_MODULE,
176 .name = "airo_cs",
177 .probe = airo_probe,
178 .remove = airo_detach,
179 .id_table = airo_ids,
180 .suspend = airo_suspend,
181 .resume = airo_resume,
182};
183module_pcmcia_driver(airo_driver);
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
221
222
223