pcmcia: avoid messages on module (un)loading
[linux-2.6.git] / drivers / net / wireless / atmel_cs.c
1 /*** -*- linux-c -*- **********************************************************
2
3      Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
4
5         Copyright 2000-2001 ATMEL Corporation.
6         Copyright 2003 Simon Kelley.
7
8     This code was developed from version 2.1.1 of the Atmel drivers,
9     released by Atmel corp. under the GPL in December 2002. It also
10     includes code from the Linux aironet drivers (C) Benjamin Reed,
11     and the Linux PCMCIA package, (C) David Hinds.
12
13     For all queries about this code, please contact the current author,
14     Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
15
16     This program is free software; you can redistribute it and/or modify
17     it under the terms of the GNU General Public License as published by
18     the Free Software Foundation; either version 2 of the License, or
19     (at your option) any later version.
20
21     This software is distributed in the hope that it will be useful,
22     but WITHOUT ANY WARRANTY; without even the implied warranty of
23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24     GNU General Public License for more details.
25
26     You should have received a copy of the GNU General Public License
27     along with Atmel wireless lan drivers; if not, write to the Free Software
28     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
30 ******************************************************************************/
31
32 #ifdef __IN_PCMCIA_PACKAGE__
33 #include <pcmcia/k_compat.h>
34 #endif
35 #include <linux/init.h>
36 #include <linux/kernel.h>
37 #include <linux/module.h>
38 #include <linux/ptrace.h>
39 #include <linux/slab.h>
40 #include <linux/string.h>
41 #include <linux/netdevice.h>
42 #include <linux/moduleparam.h>
43 #include <linux/device.h>
44
45 #include <pcmcia/cistpl.h>
46 #include <pcmcia/cisreg.h>
47 #include <pcmcia/ds.h>
48 #include <pcmcia/ciscode.h>
49
50 #include <asm/io.h>
51 #include <asm/system.h>
52 #include <linux/wireless.h>
53
54 #include "atmel.h"
55
56
57 /*====================================================================*/
58
59 MODULE_AUTHOR("Simon Kelley");
60 MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
61 MODULE_LICENSE("GPL");
62 MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
63
64 /*====================================================================*/
65
66 /*
67    The event() function is this driver's Card Services event handler.
68    It will be called by Card Services when an appropriate card status
69    event is received.  The config() and release() entry points are
70    used to configure or release a socket, in response to card
71    insertion and ejection events.  They are invoked from the atmel_cs
72    event handler.
73 */
74
75 static int atmel_config(struct pcmcia_device *link);
76 static void atmel_release(struct pcmcia_device *link);
77
78 /*
79    The attach() and detach() entry points are used to create and destroy
80    "instances" of the driver, where each instance represents everything
81    needed to manage one actual PCMCIA card.
82 */
83
84 static void atmel_detach(struct pcmcia_device *p_dev);
85
86 typedef struct local_info_t {
87         struct net_device *eth_dev;
88 } local_info_t;
89
90 /*======================================================================
91
92   atmel_attach() creates an "instance" of the driver, allocating
93   local data structures for one device.  The device is registered
94   with Card Services.
95
96   The dev_link structure is initialized, but we don't actually
97   configure the card at this point -- we wait until we receive a
98   card insertion event.
99
100   ======================================================================*/
101
102 static int atmel_probe(struct pcmcia_device *p_dev)
103 {
104         local_info_t *local;
105
106         dev_dbg(&p_dev->dev, "atmel_attach()\n");
107
108         /* Allocate space for private device-specific data */
109         local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
110         if (!local) {
111                 printk(KERN_ERR "atmel_cs: no memory for new device\n");
112                 return -ENOMEM;
113         }
114         p_dev->priv = local;
115
116         return atmel_config(p_dev);
117 } /* atmel_attach */
118
119 /*======================================================================
120
121   This deletes a driver "instance".  The device is de-registered
122   with Card Services.  If it has been released, all local data
123   structures are freed.  Otherwise, the structures will be freed
124   when the device is released.
125
126   ======================================================================*/
127
128 static void atmel_detach(struct pcmcia_device *link)
129 {
130         dev_dbg(&link->dev, "atmel_detach\n");
131
132         atmel_release(link);
133
134         kfree(link->priv);
135 }
136
137 /*======================================================================
138
139   atmel_config() is scheduled to run after a CARD_INSERTION event
140   is received, to configure the PCMCIA socket, and to make the
141   device available to the system.
142
143   ======================================================================*/
144
145 /* Call-back function to interrogate PCMCIA-specific information
146    about the current existance of the card */
147 static int card_present(void *arg)
148 {
149         struct pcmcia_device *link = (struct pcmcia_device *)arg;
150
151         if (pcmcia_dev_present(link))
152                 return 1;
153
154         return 0;
155 }
156
157 static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
158 {
159         if (p_dev->config_index == 0)
160                 return -EINVAL;
161
162         return pcmcia_request_io(p_dev);
163 }
164
165 static int atmel_config(struct pcmcia_device *link)
166 {
167         local_info_t *dev;
168         int ret;
169         struct pcmcia_device_id *did;
170
171         dev = link->priv;
172         did = dev_get_drvdata(&link->dev);
173
174         dev_dbg(&link->dev, "atmel_config\n");
175
176         link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
177                 CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
178
179         /*
180           In this loop, we scan the CIS for configuration table entries,
181           each of which describes a valid card configuration, including
182           voltage, IO window, memory window, and interrupt settings.
183
184           We make no assumptions about the card to be configured: we use
185           just the information available in the CIS.  In an ideal world,
186           this would work for any PCMCIA card, but it requires a complete
187           and accurate CIS.  In practice, a driver usually "knows" most of
188           these things without consulting the CIS, and most client drivers
189           will only use the CIS to fill in implementation-defined details.
190         */
191         if (pcmcia_loop_config(link, atmel_config_check, NULL))
192                 goto failed;
193
194         if (!link->irq) {
195                 dev_err(&link->dev, "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
196                 goto failed;
197         }
198
199         /*
200           This actually configures the PCMCIA socket -- setting up
201           the I/O windows and the interrupt mapping, and putting the
202           card and host interface into "Memory and IO" mode.
203         */
204         ret = pcmcia_enable_device(link);
205         if (ret)
206                 goto failed;
207
208         ((local_info_t*)link->priv)->eth_dev =
209                 init_atmel_card(link->irq,
210                                 link->resource[0]->start,
211                                 did ? did->driver_info : ATMEL_FW_TYPE_NONE,
212                                 &link->dev,
213                                 card_present,
214                                 link);
215         if (!((local_info_t*)link->priv)->eth_dev)
216                         goto failed;
217
218
219         return 0;
220
221  failed:
222         atmel_release(link);
223         return -ENODEV;
224 }
225
226 /*======================================================================
227
228   After a card is removed, atmel_release() will unregister the
229   device, and release the PCMCIA configuration.  If the device is
230   still open, this will be postponed until it is closed.
231
232   ======================================================================*/
233
234 static void atmel_release(struct pcmcia_device *link)
235 {
236         struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
237
238         dev_dbg(&link->dev, "atmel_release\n");
239
240         if (dev)
241                 stop_atmel_card(dev);
242         ((local_info_t*)link->priv)->eth_dev = NULL;
243
244         pcmcia_disable_device(link);
245 }
246
247 static int atmel_suspend(struct pcmcia_device *link)
248 {
249         local_info_t *local = link->priv;
250
251         netif_device_detach(local->eth_dev);
252
253         return 0;
254 }
255
256 static int atmel_resume(struct pcmcia_device *link)
257 {
258         local_info_t *local = link->priv;
259
260         atmel_open(local->eth_dev);
261         netif_device_attach(local->eth_dev);
262
263         return 0;
264 }
265
266 /*====================================================================*/
267 /* We use the driver_info field to store the correct firmware type for a card. */
268
269 #define PCMCIA_DEVICE_MANF_CARD_INFO(manf, card, info) { \
270         .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \
271                         PCMCIA_DEV_ID_MATCH_CARD_ID, \
272         .manf_id = (manf), \
273         .card_id = (card), \
274         .driver_info = (kernel_ulong_t)(info), }
275
276 #define PCMCIA_DEVICE_PROD_ID12_INFO(v1, v2, vh1, vh2, info) { \
277         .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \
278                         PCMCIA_DEV_ID_MATCH_PROD_ID2, \
279         .prod_id = { (v1), (v2), NULL, NULL }, \
280         .prod_id_hash = { (vh1), (vh2), 0, 0 }, \
281         .driver_info = (kernel_ulong_t)(info), }
282
283 static struct pcmcia_device_id atmel_ids[] = {
284         PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0620, ATMEL_FW_TYPE_502_3COM),
285         PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0696, ATMEL_FW_TYPE_502_3COM),
286         PCMCIA_DEVICE_MANF_CARD_INFO(0x01bf, 0x3302, ATMEL_FW_TYPE_502E),
287         PCMCIA_DEVICE_MANF_CARD_INFO(0xd601, 0x0007, ATMEL_FW_TYPE_502),
288         PCMCIA_DEVICE_PROD_ID12_INFO("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9, ATMEL_FW_TYPE_502E),
289         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f, ATMEL_FW_TYPE_502),
290         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_D", 0xabda4164, 0x3675d704, ATMEL_FW_TYPE_502D),
291         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_E", 0xabda4164, 0x4172e792, ATMEL_FW_TYPE_502E),
292         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504_R", 0xabda4164, 0x917f3d72, ATMEL_FW_TYPE_504_2958),
293         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504", 0xabda4164, 0x5040670a, ATMEL_FW_TYPE_504),
294         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f, ATMEL_FW_TYPE_504A_2958),
295         PCMCIA_DEVICE_PROD_ID12_INFO("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5, ATMEL_FW_TYPE_502),
296         PCMCIA_DEVICE_PROD_ID12_INFO("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b, ATMEL_FW_TYPE_502E),
297         PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6, ATMEL_FW_TYPE_502),
298         PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN Card S", 0x5b878724, 0x5fba533a, ATMEL_FW_TYPE_504_2958),
299         PCMCIA_DEVICE_PROD_ID12_INFO("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68, ATMEL_FW_TYPE_502),
300         PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W", 0xc4f8b18b, 0x30f38774, ATMEL_FW_TYPE_502D),
301         PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377, ATMEL_FW_TYPE_502),
302         PCMCIA_DEVICE_PROD_ID12_INFO("Wireless", "PC_CARD", 0xa407ecdd, 0x119f6314, ATMEL_FW_TYPE_502D),
303         PCMCIA_DEVICE_PROD_ID12_INFO("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4, ATMEL_FW_TYPE_502D),
304         PCMCIA_DEVICE_PROD_ID12_INFO("LG", "LW2100N", 0xb474d43a, 0x6b1fec94, ATMEL_FW_TYPE_502E),
305         PCMCIA_DEVICE_NULL
306 };
307
308 MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
309
310 static struct pcmcia_driver atmel_driver = {
311         .owner          = THIS_MODULE,
312         .name           = "atmel_cs",
313         .probe          = atmel_probe,
314         .remove         = atmel_detach,
315         .id_table       = atmel_ids,
316         .suspend        = atmel_suspend,
317         .resume         = atmel_resume,
318 };
319
320 static int __init atmel_cs_init(void)
321 {
322         return pcmcia_register_driver(&atmel_driver);
323 }
324
325 static void __exit atmel_cs_cleanup(void)
326 {
327         pcmcia_unregister_driver(&atmel_driver);
328 }
329
330 /*
331     This program is free software; you can redistribute it and/or
332     modify it under the terms of the GNU General Public License
333     as published by the Free Software Foundation; either version 2
334     of the License, or (at your option) any later version.
335
336     This program is distributed in the hope that it will be useful,
337     but WITHOUT ANY WARRANTY; without even the implied warranty of
338     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
339     GNU General Public License for more details.
340
341     In addition:
342
343     Redistribution and use in source and binary forms, with or without
344     modification, are permitted provided that the following conditions
345     are met:
346
347     1. Redistributions of source code must retain the above copyright
348        notice, this list of conditions and the following disclaimer.
349     2. Redistributions in binary form must reproduce the above copyright
350        notice, this list of conditions and the following disclaimer in the
351        documentation and/or other materials provided with the distribution.
352     3. The name of the author may not be used to endorse or promote
353        products derived from this software without specific prior written
354        permission.
355
356     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
357     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
358     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
359     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
360     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
361     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
362     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
363     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
364     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
365     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
366     POSSIBILITY OF SUCH DAMAGE.
367 */
368
369 module_init(atmel_cs_init);
370 module_exit(atmel_cs_cleanup);