[PATCH] au1xxx: pcmcia: fix __init called from non-init
[deliverable/linux.git] / drivers / net / pcmcia / com20020_cs.c
CommitLineData
1da177e4
LT
1/*
2 * Linux ARCnet driver - COM20020 PCMCIA support
3 *
4 * Written 1994-1999 by Avery Pennarun,
5 * based on an ISA version by David Woodhouse.
6 * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4)
7 * which was derived from pcnet_cs.c by David Hinds.
8 * Some additional portions derived from skeleton.c by Donald Becker.
9 *
10 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
11 * for sponsoring the further development of this driver.
12 *
13 * **********************
14 *
15 * The original copyright of skeleton.c was as follows:
16 *
17 * skeleton.c Written 1993 by Donald Becker.
18 * Copyright 1993 United States Government as represented by the
19 * Director, National Security Agency. This software may only be used
20 * and distributed according to the terms of the GNU General Public License as
21 * modified by SRC, incorporated herein by reference.
22 *
23 * **********************
24 * Changes:
25 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
26 * - reorganize kmallocs in com20020_attach, checking all for failure
27 * and releasing the previous allocations if one fails
28 * **********************
29 *
30 * For more details, see drivers/net/arcnet.c
31 *
32 * **********************
33 */
34#include <linux/kernel.h>
35#include <linux/init.h>
36#include <linux/ptrace.h>
37#include <linux/slab.h>
38#include <linux/string.h>
39#include <linux/timer.h>
40#include <linux/delay.h>
41#include <linux/module.h>
42#include <linux/netdevice.h>
43#include <linux/arcdevice.h>
44#include <linux/com20020.h>
45
1da177e4
LT
46#include <pcmcia/cs_types.h>
47#include <pcmcia/cs.h>
48#include <pcmcia/cistpl.h>
49#include <pcmcia/ds.h>
50
51#include <asm/io.h>
52#include <asm/system.h>
53
54#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
55
56#ifdef PCMCIA_DEBUG
57
58static int pc_debug = PCMCIA_DEBUG;
59module_param(pc_debug, int, 0);
60#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
61
62static void regdump(struct net_device *dev)
63{
64 int ioaddr = dev->base_addr;
65 int count;
66
67 printk("com20020 register dump:\n");
68 for (count = ioaddr; count < ioaddr + 16; count++)
69 {
70 if (!(count % 16))
71 printk("\n%04X: ", count);
72 printk("%02X ", inb(count));
73 }
74 printk("\n");
75
76 printk("buffer0 dump:\n");
77 /* set up the address register */
78 count = 0;
79 outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
80 outb(count & 0xff, _ADDR_LO);
81
82 for (count = 0; count < 256+32; count++)
83 {
84 if (!(count % 16))
85 printk("\n%04X: ", count);
86
87 /* copy the data */
88 printk("%02X ", inb(_MEMDATA));
89 }
90 printk("\n");
91}
92
93#else
94
95#define DEBUG(n, args...) do { } while (0)
96static inline void regdump(struct net_device *dev) { }
97
98#endif
99
100
101/*====================================================================*/
102
103/* Parameters that can be set with 'insmod' */
104
105static int node;
106static int timeout = 3;
107static int backplane;
108static int clockp;
109static int clockm;
110
111module_param(node, int, 0);
112module_param(timeout, int, 0);
113module_param(backplane, int, 0);
114module_param(clockp, int, 0);
115module_param(clockm, int, 0);
116
117MODULE_LICENSE("GPL");
118
119/*====================================================================*/
120
15b99ac1 121static int com20020_config(struct pcmcia_device *link);
fba395ee 122static void com20020_release(struct pcmcia_device *link);
1da177e4 123
cc3b4866 124static void com20020_detach(struct pcmcia_device *p_dev);
1da177e4 125
1da177e4
LT
126/*====================================================================*/
127
128typedef struct com20020_dev_t {
129 struct net_device *dev;
130 dev_node_t node;
131} com20020_dev_t;
132
133/*======================================================================
134
135 com20020_attach() creates an "instance" of the driver, allocating
136 local data structures for one device. The device is registered
137 with Card Services.
138
139======================================================================*/
140
15b99ac1 141static int com20020_probe(struct pcmcia_device *p_dev)
1da177e4 142{
1da177e4
LT
143 com20020_dev_t *info;
144 struct net_device *dev;
1da177e4 145 struct arcnet_local *lp;
f8cfa618 146
1da177e4
LT
147 DEBUG(0, "com20020_attach()\n");
148
149 /* Create new network device */
1da177e4
LT
150 info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
151 if (!info)
152 goto fail_alloc_info;
153
154 dev = alloc_arcdev("");
155 if (!dev)
156 goto fail_alloc_dev;
157
158 memset(info, 0, sizeof(struct com20020_dev_t));
1da177e4
LT
159 lp = dev->priv;
160 lp->timeout = timeout;
161 lp->backplane = backplane;
162 lp->clockp = clockp;
163 lp->clockm = clockm & 3;
164 lp->hw.owner = THIS_MODULE;
165
166 /* fill in our module parameters as defaults */
167 dev->dev_addr[0] = node;
168
fd238232
DB
169 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
170 p_dev->io.NumPorts1 = 16;
171 p_dev->io.IOAddrLines = 16;
172 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
173 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
174 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
175 p_dev->conf.IntType = INT_MEMORY_AND_IO;
176 p_dev->conf.Present = PRESENT_OPTION;
1da177e4 177
fd238232
DB
178 p_dev->irq.Instance = info->dev = dev;
179 p_dev->priv = info;
1da177e4 180
15b99ac1 181 return com20020_config(p_dev);
1da177e4
LT
182
183fail_alloc_dev:
184 kfree(info);
185fail_alloc_info:
f8cfa618 186 return -ENOMEM;
1da177e4
LT
187} /* com20020_attach */
188
189/*======================================================================
190
191 This deletes a driver "instance". The device is de-registered
192 with Card Services. If it has been released, all local data
193 structures are freed. Otherwise, the structures will be freed
194 when the device is released.
195
196======================================================================*/
197
fba395ee 198static void com20020_detach(struct pcmcia_device *link)
1da177e4
LT
199{
200 struct com20020_dev_t *info = link->priv;
b4635811
DB
201 struct net_device *dev = info->dev;
202
1da177e4
LT
203 DEBUG(1,"detach...\n");
204
205 DEBUG(0, "com20020_detach(0x%p)\n", link);
206
fd238232 207 if (link->dev_node) {
1da177e4
LT
208 DEBUG(1,"unregister...\n");
209
210 unregister_netdev(dev);
b4635811 211
1da177e4
LT
212 /*
213 * this is necessary because we register our IRQ separately
214 * from card services.
215 */
216 if (dev->irq)
217 free_irq(dev->irq, dev);
218 }
219
e2d40963 220 com20020_release(link);
1da177e4 221
1da177e4
LT
222 /* Unlink device structure, free bits */
223 DEBUG(1,"unlinking...\n");
1da177e4
LT
224 if (link->priv)
225 {
226 dev = info->dev;
227 if (dev)
228 {
229 DEBUG(1,"kfree...\n");
230 free_netdev(dev);
231 }
232 DEBUG(1,"kfree2...\n");
233 kfree(info);
234 }
1da177e4
LT
235
236} /* com20020_detach */
237
238/*======================================================================
239
240 com20020_config() is scheduled to run after a CARD_INSERTION event
241 is received, to configure the PCMCIA socket, and to make the
242 device available to the system.
243
244======================================================================*/
245
246#define CS_CHECK(fn, ret) \
247do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
248
15b99ac1 249static int com20020_config(struct pcmcia_device *link)
1da177e4
LT
250{
251 struct arcnet_local *lp;
1da177e4
LT
252 tuple_t tuple;
253 cisparse_t parse;
254 com20020_dev_t *info;
255 struct net_device *dev;
256 int i, last_ret, last_fn;
257 u_char buf[64];
258 int ioaddr;
259
1da177e4
LT
260 info = link->priv;
261 dev = info->dev;
262
263 DEBUG(1,"config...\n");
264
265 DEBUG(0, "com20020_config(0x%p)\n", link);
266
267 tuple.Attributes = 0;
268 tuple.TupleData = buf;
269 tuple.TupleDataMax = 64;
270 tuple.TupleOffset = 0;
271 tuple.DesiredTuple = CISTPL_CONFIG;
fba395ee
DB
272 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
273 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
274 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
1da177e4
LT
275 link->conf.ConfigBase = parse.config.base;
276
1da177e4
LT
277 DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
278 i = !CS_SUCCESS;
279 if (!link->io.BasePort1)
280 {
281 for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
282 {
283 link->io.BasePort1 = ioaddr;
fba395ee 284 i = pcmcia_request_io(link, &link->io);
1da177e4
LT
285 if (i == CS_SUCCESS)
286 break;
287 }
288 }
289 else
fba395ee 290 i = pcmcia_request_io(link, &link->io);
1da177e4
LT
291
292 if (i != CS_SUCCESS)
293 {
294 DEBUG(1,"arcnet: requestIO failed totally!\n");
295 goto failed;
296 }
297
298 ioaddr = dev->base_addr = link->io.BasePort1;
299 DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);
300
301 DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
302 link->irq.AssignedIRQ,
303 link->irq.IRQInfo1, link->irq.IRQInfo2);
fba395ee 304 i = pcmcia_request_irq(link, &link->irq);
1da177e4
LT
305 if (i != CS_SUCCESS)
306 {
307 DEBUG(1,"arcnet: requestIRQ failed totally!\n");
308 goto failed;
309 }
310
311 dev->irq = link->irq.AssignedIRQ;
312
fba395ee 313 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
1da177e4
LT
314
315 if (com20020_check(dev))
316 {
317 regdump(dev);
318 goto failed;
319 }
320
321 lp = dev->priv;
322 lp->card_name = "PCMCIA COM20020";
323 lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
324
fd238232 325 link->dev_node = &info->node;
fba395ee 326 SET_NETDEV_DEV(dev, &handle_to_dev(link));
1da177e4
LT
327
328 i = com20020_found(dev, 0); /* calls register_netdev */
329
330 if (i != 0) {
331 DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
fd238232 332 link->dev_node = NULL;
1da177e4
LT
333 goto failed;
334 }
335
336 strcpy(info->node.dev_name, dev->name);
337
338 DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
339 dev->name, dev->base_addr, dev->irq);
15b99ac1 340 return 0;
1da177e4
LT
341
342cs_failed:
fba395ee 343 cs_error(link, last_fn, last_ret);
1da177e4
LT
344failed:
345 DEBUG(1,"com20020_config failed...\n");
346 com20020_release(link);
15b99ac1 347 return -ENODEV;
1da177e4
LT
348} /* com20020_config */
349
350/*======================================================================
351
352 After a card is removed, com20020_release() will unregister the net
353 device, and release the PCMCIA configuration. If the device is
354 still open, this will be postponed until it is closed.
355
356======================================================================*/
357
fba395ee 358static void com20020_release(struct pcmcia_device *link)
1da177e4 359{
5f2a71fc 360 DEBUG(0, "com20020_release(0x%p)\n", link);
fba395ee 361 pcmcia_disable_device(link);
1da177e4
LT
362}
363
fba395ee 364static int com20020_suspend(struct pcmcia_device *link)
98e4c28b 365{
98e4c28b
DB
366 com20020_dev_t *info = link->priv;
367 struct net_device *dev = info->dev;
368
e2d40963 369 if (link->open)
8661bb5b 370 netif_device_detach(dev);
98e4c28b
DB
371
372 return 0;
373}
374
fba395ee 375static int com20020_resume(struct pcmcia_device *link)
98e4c28b 376{
98e4c28b
DB
377 com20020_dev_t *info = link->priv;
378 struct net_device *dev = info->dev;
379
e2d40963 380 if (link->open) {
8661bb5b
DB
381 int ioaddr = dev->base_addr;
382 struct arcnet_local *lp = dev->priv;
383 ARCRESET;
384 }
98e4c28b
DB
385
386 return 0;
387}
388
7fb22bb4
DB
389static struct pcmcia_device_id com20020_ids[] = {
390 PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
391 PCMCIA_DEVICE_NULL
392};
393MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
1da177e4
LT
394
395static struct pcmcia_driver com20020_cs_driver = {
396 .owner = THIS_MODULE,
397 .drv = {
398 .name = "com20020_cs",
399 },
15b99ac1 400 .probe = com20020_probe,
cc3b4866 401 .remove = com20020_detach,
7fb22bb4 402 .id_table = com20020_ids,
98e4c28b
DB
403 .suspend = com20020_suspend,
404 .resume = com20020_resume,
1da177e4
LT
405};
406
407static int __init init_com20020_cs(void)
408{
409 return pcmcia_register_driver(&com20020_cs_driver);
410}
411
412static void __exit exit_com20020_cs(void)
413{
414 pcmcia_unregister_driver(&com20020_cs_driver);
1da177e4
LT
415}
416
417module_init(init_com20020_cs);
418module_exit(exit_com20020_cs);
This page took 0.169543 seconds and 5 git commands to generate.