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