pcmcia: simplify IntType
[pandora-kernel.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/cs.h>
46 #include <pcmcia/cistpl.h>
47 #include <pcmcia/cisreg.h>
48 #include <pcmcia/ds.h>
49 #include <pcmcia/ciscode.h>
50
51 #include <asm/io.h>
52 #include <asm/system.h>
53 #include <linux/wireless.h>
54
55 #include "atmel.h"
56
57
58 /*====================================================================*/
59
60 MODULE_AUTHOR("Simon Kelley");
61 MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
62 MODULE_LICENSE("GPL");
63 MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
64
65 /*====================================================================*/
66
67 /*
68    The event() function is this driver's Card Services event handler.
69    It will be called by Card Services when an appropriate card status
70    event is received.  The config() and release() entry points are
71    used to configure or release a socket, in response to card
72    insertion and ejection events.  They are invoked from the atmel_cs
73    event handler.
74 */
75
76 static int atmel_config(struct pcmcia_device *link);
77 static void atmel_release(struct pcmcia_device *link);
78
79 /*
80    The attach() and detach() entry points are used to create and destroy
81    "instances" of the driver, where each instance represents everything
82    needed to manage one actual PCMCIA card.
83 */
84
85 static void atmel_detach(struct pcmcia_device *p_dev);
86
87 typedef struct local_info_t {
88         struct net_device *eth_dev;
89 } local_info_t;
90
91 /*======================================================================
92
93   atmel_attach() creates an "instance" of the driver, allocating
94   local data structures for one device.  The device is registered
95   with Card Services.
96
97   The dev_link structure is initialized, but we don't actually
98   configure the card at this point -- we wait until we receive a
99   card insertion event.
100
101   ======================================================================*/
102
103 static int atmel_probe(struct pcmcia_device *p_dev)
104 {
105         local_info_t *local;
106
107         dev_dbg(&p_dev->dev, "atmel_attach()\n");
108
109         /*
110           General socket configuration defaults can go here.  In this
111           client, we assume very little, and rely on the CIS for almost
112           everything.  In most clients, many details (i.e., number, sizes,
113           and attributes of IO windows) are fixed by the nature of the
114           device, and can be hard-wired here.
115         */
116         p_dev->conf.Attributes = 0;
117
118         /* Allocate space for private device-specific data */
119         local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
120         if (!local) {
121                 printk(KERN_ERR "atmel_cs: no memory for new device\n");
122                 return -ENOMEM;
123         }
124         p_dev->priv = local;
125
126         return atmel_config(p_dev);
127 } /* atmel_attach */
128
129 /*======================================================================
130
131   This deletes a driver "instance".  The device is de-registered
132   with Card Services.  If it has been released, all local data
133   structures are freed.  Otherwise, the structures will be freed
134   when the device is released.
135
136   ======================================================================*/
137
138 static void atmel_detach(struct pcmcia_device *link)
139 {
140         dev_dbg(&link->dev, "atmel_detach\n");
141
142         atmel_release(link);
143
144         kfree(link->priv);
145 }
146
147 /*======================================================================
148
149   atmel_config() is scheduled to run after a CARD_INSERTION event
150   is received, to configure the PCMCIA socket, and to make the
151   device available to the system.
152
153   ======================================================================*/
154
155 /* Call-back function to interrogate PCMCIA-specific information
156    about the current existance of the card */
157 static int card_present(void *arg)
158 {
159         struct pcmcia_device *link = (struct pcmcia_device *)arg;
160
161         if (pcmcia_dev_present(link))
162                 return 1;
163
164         return 0;
165 }
166
167 static int atmel_config_check(struct pcmcia_device *p_dev,
168                               cistpl_cftable_entry_t *cfg,
169                               cistpl_cftable_entry_t *dflt,
170                               unsigned int vcc,
171                               void *priv_data)
172 {
173         if (cfg->index == 0)
174                 return -ENODEV;
175
176         /* Does this card need audio output? */
177         if (cfg->flags & CISTPL_CFTABLE_AUDIO)
178                 p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
179
180         /* Use power settings for Vcc and Vpp if present */
181         /*  Note that the CIS values need to be rescaled */
182         if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
183                 p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
184         else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
185                 p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
186
187         p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
188
189         /* IO window settings */
190         p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
191         if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
192                 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
193                 p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
194                 p_dev->resource[0]->flags |=
195                                         pcmcia_io_cfg_data_width(io->flags);
196                 p_dev->resource[0]->start = io->win[0].base;
197                 p_dev->resource[0]->end = io->win[0].len;
198                 if (io->nwin > 1) {
199                         p_dev->resource[1]->flags = p_dev->resource[0]->flags;
200                         p_dev->resource[1]->start = io->win[1].base;
201                         p_dev->resource[1]->end = io->win[1].len;
202                 }
203         }
204
205         /* This reserves IO space but doesn't actually enable it */
206         return pcmcia_request_io(p_dev);
207 }
208
209 static int atmel_config(struct pcmcia_device *link)
210 {
211         local_info_t *dev;
212         int ret;
213         struct pcmcia_device_id *did;
214
215         dev = link->priv;
216         did = dev_get_drvdata(&link->dev);
217
218         dev_dbg(&link->dev, "atmel_config\n");
219
220         /*
221           In this loop, we scan the CIS for configuration table entries,
222           each of which describes a valid card configuration, including
223           voltage, IO window, memory window, and interrupt settings.
224
225           We make no assumptions about the card to be configured: we use
226           just the information available in the CIS.  In an ideal world,
227           this would work for any PCMCIA card, but it requires a complete
228           and accurate CIS.  In practice, a driver usually "knows" most of
229           these things without consulting the CIS, and most client drivers
230           will only use the CIS to fill in implementation-defined details.
231         */
232         if (pcmcia_loop_config(link, atmel_config_check, NULL))
233                 goto failed;
234
235         if (!link->irq) {
236                 dev_err(&link->dev, "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
237                 goto failed;
238         }
239
240         /*
241           This actually configures the PCMCIA socket -- setting up
242           the I/O windows and the interrupt mapping, and putting the
243           card and host interface into "Memory and IO" mode.
244         */
245         ret = pcmcia_request_configuration(link, &link->conf);
246         if (ret)
247                 goto failed;
248
249         ((local_info_t*)link->priv)->eth_dev =
250                 init_atmel_card(link->irq,
251                                 link->resource[0]->start,
252                                 did ? did->driver_info : ATMEL_FW_TYPE_NONE,
253                                 &link->dev,
254                                 card_present,
255                                 link);
256         if (!((local_info_t*)link->priv)->eth_dev)
257                         goto failed;
258
259
260         return 0;
261
262  failed:
263         atmel_release(link);
264         return -ENODEV;
265 }
266
267 /*======================================================================
268
269   After a card is removed, atmel_release() will unregister the
270   device, and release the PCMCIA configuration.  If the device is
271   still open, this will be postponed until it is closed.
272
273   ======================================================================*/
274
275 static void atmel_release(struct pcmcia_device *link)
276 {
277         struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
278
279         dev_dbg(&link->dev, "atmel_release\n");
280
281         if (dev)
282                 stop_atmel_card(dev);
283         ((local_info_t*)link->priv)->eth_dev = NULL;
284
285         pcmcia_disable_device(link);
286 }
287
288 static int atmel_suspend(struct pcmcia_device *link)
289 {
290         local_info_t *local = link->priv;
291
292         netif_device_detach(local->eth_dev);
293
294         return 0;
295 }
296
297 static int atmel_resume(struct pcmcia_device *link)
298 {
299         local_info_t *local = link->priv;
300
301         atmel_open(local->eth_dev);
302         netif_device_attach(local->eth_dev);
303
304         return 0;
305 }
306
307 /*====================================================================*/
308 /* We use the driver_info field to store the correct firmware type for a card. */
309
310 #define PCMCIA_DEVICE_MANF_CARD_INFO(manf, card, info) { \
311         .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \
312                         PCMCIA_DEV_ID_MATCH_CARD_ID, \
313         .manf_id = (manf), \
314         .card_id = (card), \
315         .driver_info = (kernel_ulong_t)(info), }
316
317 #define PCMCIA_DEVICE_PROD_ID12_INFO(v1, v2, vh1, vh2, info) { \
318         .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \
319                         PCMCIA_DEV_ID_MATCH_PROD_ID2, \
320         .prod_id = { (v1), (v2), NULL, NULL }, \
321         .prod_id_hash = { (vh1), (vh2), 0, 0 }, \
322         .driver_info = (kernel_ulong_t)(info), }
323
324 static struct pcmcia_device_id atmel_ids[] = {
325         PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0620, ATMEL_FW_TYPE_502_3COM),
326         PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0696, ATMEL_FW_TYPE_502_3COM),
327         PCMCIA_DEVICE_MANF_CARD_INFO(0x01bf, 0x3302, ATMEL_FW_TYPE_502E),
328         PCMCIA_DEVICE_MANF_CARD_INFO(0xd601, 0x0007, ATMEL_FW_TYPE_502),
329         PCMCIA_DEVICE_PROD_ID12_INFO("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9, ATMEL_FW_TYPE_502E),
330         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f, ATMEL_FW_TYPE_502),
331         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_D", 0xabda4164, 0x3675d704, ATMEL_FW_TYPE_502D),
332         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_E", 0xabda4164, 0x4172e792, ATMEL_FW_TYPE_502E),
333         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504_R", 0xabda4164, 0x917f3d72, ATMEL_FW_TYPE_504_2958),
334         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504", 0xabda4164, 0x5040670a, ATMEL_FW_TYPE_504),
335         PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f, ATMEL_FW_TYPE_504A_2958),
336         PCMCIA_DEVICE_PROD_ID12_INFO("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5, ATMEL_FW_TYPE_502),
337         PCMCIA_DEVICE_PROD_ID12_INFO("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b, ATMEL_FW_TYPE_502E),
338         PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6, ATMEL_FW_TYPE_502),
339         PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN Card S", 0x5b878724, 0x5fba533a, ATMEL_FW_TYPE_504_2958),
340         PCMCIA_DEVICE_PROD_ID12_INFO("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68, ATMEL_FW_TYPE_502),
341         PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W", 0xc4f8b18b, 0x30f38774, ATMEL_FW_TYPE_502D),
342         PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377, ATMEL_FW_TYPE_502),
343         PCMCIA_DEVICE_PROD_ID12_INFO("Wireless", "PC_CARD", 0xa407ecdd, 0x119f6314, ATMEL_FW_TYPE_502D),
344         PCMCIA_DEVICE_PROD_ID12_INFO("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4, ATMEL_FW_TYPE_502D),
345         PCMCIA_DEVICE_PROD_ID12_INFO("LG", "LW2100N", 0xb474d43a, 0x6b1fec94, ATMEL_FW_TYPE_502E),
346         PCMCIA_DEVICE_NULL
347 };
348
349 MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
350
351 static struct pcmcia_driver atmel_driver = {
352         .owner          = THIS_MODULE,
353         .drv            = {
354                 .name   = "atmel_cs",
355         },
356         .probe          = atmel_probe,
357         .remove         = atmel_detach,
358         .id_table       = atmel_ids,
359         .suspend        = atmel_suspend,
360         .resume         = atmel_resume,
361 };
362
363 static int atmel_cs_init(void)
364 {
365         return pcmcia_register_driver(&atmel_driver);
366 }
367
368 static void atmel_cs_cleanup(void)
369 {
370         pcmcia_unregister_driver(&atmel_driver);
371 }
372
373 /*
374     This program is free software; you can redistribute it and/or
375     modify it under the terms of the GNU General Public License
376     as published by the Free Software Foundation; either version 2
377     of the License, or (at your option) any later version.
378
379     This program is distributed in the hope that it will be useful,
380     but WITHOUT ANY WARRANTY; without even the implied warranty of
381     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
382     GNU General Public License for more details.
383
384     In addition:
385
386     Redistribution and use in source and binary forms, with or without
387     modification, are permitted provided that the following conditions
388     are met:
389
390     1. Redistributions of source code must retain the above copyright
391        notice, this list of conditions and the following disclaimer.
392     2. Redistributions in binary form must reproduce the above copyright
393        notice, this list of conditions and the following disclaimer in the
394        documentation and/or other materials provided with the distribution.
395     3. The name of the author may not be used to endorse or promote
396        products derived from this software without specific prior written
397        permission.
398
399     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
400     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
401     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
402     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
403     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
404     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
405     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
406     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
407     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
408     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
409     POSSIBILITY OF SUCH DAMAGE.
410 */
411
412 module_init(atmel_cs_init);
413 module_exit(atmel_cs_cleanup);