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