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