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