[PATCH] pcmcia: unify detach, REMOVAL_EVENT handlers into one remove callback
[powerpc.git] / drivers / net / pcmcia / com20020_cs.c
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
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
58 static int pc_debug = PCMCIA_DEBUG;
59 module_param(pc_debug, int, 0);
60 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
61
62 static 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)
96 static inline void regdump(struct net_device *dev) { }
97
98 #endif
99
100
101 /*====================================================================*/
102
103 /* Parameters that can be set with 'insmod' */
104
105 static int node;
106 static int timeout = 3;
107 static int backplane;
108 static int clockp;
109 static int clockm;
110
111 module_param(node, int, 0);
112 module_param(timeout, int, 0);
113 module_param(backplane, int, 0);
114 module_param(clockp, int, 0);
115 module_param(clockm, int, 0);
116
117 MODULE_LICENSE("GPL");
118
119 /*====================================================================*/
120
121 static void com20020_config(dev_link_t *link);
122 static void com20020_release(dev_link_t *link);
123 static int com20020_event(event_t event, int priority,
124                        event_callback_args_t *args);
125
126 static dev_info_t dev_info = "com20020_cs";
127
128 static dev_link_t *com20020_attach(void);
129 static void com20020_detach(struct pcmcia_device *p_dev);
130
131 static dev_link_t *dev_list;
132
133 /*====================================================================*/
134
135 typedef struct com20020_dev_t {
136     struct net_device       *dev;
137     dev_node_t          node;
138 } com20020_dev_t;
139
140 /*======================================================================
141
142     com20020_attach() creates an "instance" of the driver, allocating
143     local data structures for one device.  The device is registered
144     with Card Services.
145
146 ======================================================================*/
147
148 static dev_link_t *com20020_attach(void)
149 {
150     client_reg_t client_reg;
151     dev_link_t *link;
152     com20020_dev_t *info;
153     struct net_device *dev;
154     int ret;
155     struct arcnet_local *lp;
156     
157     DEBUG(0, "com20020_attach()\n");
158
159     /* Create new network device */
160     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
161     if (!link)
162         return NULL;
163
164     info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
165     if (!info)
166         goto fail_alloc_info;
167
168     dev = alloc_arcdev("");
169     if (!dev)
170         goto fail_alloc_dev;
171
172     memset(info, 0, sizeof(struct com20020_dev_t));
173     memset(link, 0, sizeof(struct dev_link_t));
174     lp = dev->priv;
175     lp->timeout = timeout;
176     lp->backplane = backplane;
177     lp->clockp = clockp;
178     lp->clockm = clockm & 3;
179     lp->hw.owner = THIS_MODULE;
180
181     /* fill in our module parameters as defaults */
182     dev->dev_addr[0] = node;
183
184     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
185     link->io.NumPorts1 = 16;
186     link->io.IOAddrLines = 16;
187     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
188     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
189     link->conf.Attributes = CONF_ENABLE_IRQ;
190     link->conf.Vcc = 50;
191     link->conf.IntType = INT_MEMORY_AND_IO;
192     link->conf.Present = PRESENT_OPTION;
193
194
195     link->irq.Instance = info->dev = dev;
196     link->priv = info;
197
198     /* Register with Card Services */
199     link->next = dev_list;
200     dev_list = link;
201     client_reg.dev_info = &dev_info;
202     client_reg.Version = 0x0210;
203     client_reg.event_callback_args.client_data = link;
204     ret = pcmcia_register_client(&link->handle, &client_reg);
205     if (ret != 0) {
206         cs_error(link->handle, RegisterClient, ret);
207         com20020_detach(link->handle);
208         return NULL;
209     }
210
211     return link;
212
213 fail_alloc_dev:
214     kfree(info);
215 fail_alloc_info:
216     kfree(link);
217     return NULL;
218 } /* com20020_attach */
219
220 /*======================================================================
221
222     This deletes a driver "instance".  The device is de-registered
223     with Card Services.  If it has been released, all local data
224     structures are freed.  Otherwise, the structures will be freed
225     when the device is released.
226
227 ======================================================================*/
228
229 static void com20020_detach(struct pcmcia_device *p_dev)
230 {
231     dev_link_t *link = dev_to_instance(p_dev);
232     struct com20020_dev_t *info = link->priv;
233     dev_link_t **linkp;
234     struct net_device *dev; 
235     
236     DEBUG(1,"detach...\n");
237
238     DEBUG(0, "com20020_detach(0x%p)\n", link);
239
240     /* Locate device structure */
241     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
242         if (*linkp == link) break;
243     if (*linkp == NULL)
244         return;
245
246     dev = info->dev;
247
248     if (link->dev) {
249         DEBUG(1,"unregister...\n");
250
251         unregister_netdev(dev);
252             
253         /*
254          * this is necessary because we register our IRQ separately
255          * from card services.
256          */
257         if (dev->irq)
258             free_irq(dev->irq, dev);
259     }
260
261     if (link->state & DEV_CONFIG)
262         com20020_release(link);
263
264     /* Unlink device structure, free bits */
265     DEBUG(1,"unlinking...\n");
266     *linkp = link->next;
267     if (link->priv)
268     {
269         dev = info->dev;
270         if (dev)
271         {
272             DEBUG(1,"kfree...\n");
273             free_netdev(dev);
274         }
275         DEBUG(1,"kfree2...\n");
276         kfree(info);
277     }
278     DEBUG(1,"kfree3...\n");
279     kfree(link);
280
281 } /* com20020_detach */
282
283 /*======================================================================
284
285     com20020_config() is scheduled to run after a CARD_INSERTION event
286     is received, to configure the PCMCIA socket, and to make the
287     device available to the system.
288
289 ======================================================================*/
290
291 #define CS_CHECK(fn, ret) \
292 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
293
294 static void com20020_config(dev_link_t *link)
295 {
296     struct arcnet_local *lp;
297     client_handle_t handle;
298     tuple_t tuple;
299     cisparse_t parse;
300     com20020_dev_t *info;
301     struct net_device *dev;
302     int i, last_ret, last_fn;
303     u_char buf[64];
304     int ioaddr;
305
306     handle = link->handle;
307     info = link->priv;
308     dev = info->dev;
309
310     DEBUG(1,"config...\n");
311
312     DEBUG(0, "com20020_config(0x%p)\n", link);
313
314     tuple.Attributes = 0;
315     tuple.TupleData = buf;
316     tuple.TupleDataMax = 64;
317     tuple.TupleOffset = 0;
318     tuple.DesiredTuple = CISTPL_CONFIG;
319     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
320     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
321     CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
322     link->conf.ConfigBase = parse.config.base;
323
324     /* Configure card */
325     link->state |= DEV_CONFIG;
326
327     DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
328     i = !CS_SUCCESS;
329     if (!link->io.BasePort1)
330     {
331         for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
332         {
333             link->io.BasePort1 = ioaddr;
334             i = pcmcia_request_io(link->handle, &link->io);
335             if (i == CS_SUCCESS)
336                 break;
337         }
338     }
339     else
340         i = pcmcia_request_io(link->handle, &link->io);
341     
342     if (i != CS_SUCCESS)
343     {
344         DEBUG(1,"arcnet: requestIO failed totally!\n");
345         goto failed;
346     }
347         
348     ioaddr = dev->base_addr = link->io.BasePort1;
349     DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);
350
351     DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
352            link->irq.AssignedIRQ,
353            link->irq.IRQInfo1, link->irq.IRQInfo2);
354     i = pcmcia_request_irq(link->handle, &link->irq);
355     if (i != CS_SUCCESS)
356     {
357         DEBUG(1,"arcnet: requestIRQ failed totally!\n");
358         goto failed;
359     }
360
361     dev->irq = link->irq.AssignedIRQ;
362
363     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
364
365     if (com20020_check(dev))
366     {
367         regdump(dev);
368         goto failed;
369     }
370     
371     lp = dev->priv;
372     lp->card_name = "PCMCIA COM20020";
373     lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
374
375     link->dev = &info->node;
376     link->state &= ~DEV_CONFIG_PENDING;
377     SET_NETDEV_DEV(dev, &handle_to_dev(handle));
378
379     i = com20020_found(dev, 0); /* calls register_netdev */
380     
381     if (i != 0) {
382         DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
383         link->dev = NULL;
384         goto failed;
385     }
386
387     strcpy(info->node.dev_name, dev->name);
388
389     DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
390            dev->name, dev->base_addr, dev->irq);
391     return;
392
393 cs_failed:
394     cs_error(link->handle, last_fn, last_ret);
395 failed:
396     DEBUG(1,"com20020_config failed...\n");
397     com20020_release(link);
398 } /* com20020_config */
399
400 /*======================================================================
401
402     After a card is removed, com20020_release() will unregister the net
403     device, and release the PCMCIA configuration.  If the device is
404     still open, this will be postponed until it is closed.
405
406 ======================================================================*/
407
408 static void com20020_release(dev_link_t *link)
409 {
410
411     DEBUG(1,"release...\n");
412
413     DEBUG(0, "com20020_release(0x%p)\n", link);
414
415     pcmcia_release_configuration(link->handle);
416     pcmcia_release_io(link->handle, &link->io);
417     pcmcia_release_irq(link->handle, &link->irq);
418
419     link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
420 }
421
422 static int com20020_suspend(struct pcmcia_device *p_dev)
423 {
424         dev_link_t *link = dev_to_instance(p_dev);
425         com20020_dev_t *info = link->priv;
426         struct net_device *dev = info->dev;
427
428         link->state |= DEV_SUSPEND;
429         if (link->state & DEV_CONFIG) {
430                 if (link->open) {
431                         netif_device_detach(dev);
432                 }
433                 pcmcia_release_configuration(link->handle);
434         }
435
436         return 0;
437 }
438
439 static int com20020_resume(struct pcmcia_device *p_dev)
440 {
441         dev_link_t *link = dev_to_instance(p_dev);
442         com20020_dev_t *info = link->priv;
443         struct net_device *dev = info->dev;
444
445         link->state &= ~DEV_SUSPEND;
446         if (link->state & DEV_CONFIG) {
447                 pcmcia_request_configuration(link->handle, &link->conf);
448                 if (link->open) {
449                         int ioaddr = dev->base_addr;
450                         struct arcnet_local *lp = dev->priv;
451                         ARCRESET;
452                 }
453         }
454
455         return 0;
456 }
457
458 /*======================================================================
459
460     The card status event handler.  Mostly, this schedules other
461     stuff to run after an event is received.  A CARD_REMOVAL event
462     also sets some flags to discourage the net drivers from trying
463     to talk to the card any more.
464
465 ======================================================================*/
466
467 static int com20020_event(event_t event, int priority,
468                           event_callback_args_t *args)
469 {
470     dev_link_t *link = args->client_data;
471
472     DEBUG(1, "com20020_event(0x%06x)\n", event);
473     
474     switch (event) {
475     case CS_EVENT_CARD_INSERTION:
476         link->state |= DEV_PRESENT;
477         com20020_config(link); 
478         break;
479     }
480     return 0;
481 } /* com20020_event */
482
483 static struct pcmcia_device_id com20020_ids[] = {
484         PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
485         PCMCIA_DEVICE_NULL
486 };
487 MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
488
489 static struct pcmcia_driver com20020_cs_driver = {
490         .owner          = THIS_MODULE,
491         .drv            = {
492                 .name   = "com20020_cs",
493         },
494         .attach         = com20020_attach,
495         .event          = com20020_event,
496         .remove         = com20020_detach,
497         .id_table       = com20020_ids,
498         .suspend        = com20020_suspend,
499         .resume         = com20020_resume,
500 };
501
502 static int __init init_com20020_cs(void)
503 {
504         return pcmcia_register_driver(&com20020_cs_driver);
505 }
506
507 static void __exit exit_com20020_cs(void)
508 {
509         pcmcia_unregister_driver(&com20020_cs_driver);
510         BUG_ON(dev_list != NULL);
511 }
512
513 module_init(init_com20020_cs);
514 module_exit(exit_com20020_cs);