VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[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->dev) {
266         DEBUG(1,"unregister...\n");
267
268         unregister_netdev(dev);
269             
270         /*
271          * this is necessary because we register our IRQ separately
272          * from card services.
273          */
274         if (dev->irq)
275             free_irq(dev->irq, dev);
276     }
277
278     if (link->state & DEV_CONFIG)
279         com20020_release(link);
280
281     if (link->handle)
282         pcmcia_deregister_client(link->handle);
283
284     /* Unlink device structure, free bits */
285     DEBUG(1,"unlinking...\n");
286     *linkp = link->next;
287     if (link->priv)
288     {
289         dev = info->dev;
290         if (dev)
291         {
292             DEBUG(1,"kfree...\n");
293             free_netdev(dev);
294         }
295         DEBUG(1,"kfree2...\n");
296         kfree(info);
297     }
298     DEBUG(1,"kfree3...\n");
299     kfree(link);
300
301 } /* com20020_detach */
302
303 /*======================================================================
304
305     com20020_config() is scheduled to run after a CARD_INSERTION event
306     is received, to configure the PCMCIA socket, and to make the
307     device available to the system.
308
309 ======================================================================*/
310
311 #define CS_CHECK(fn, ret) \
312 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
313
314 static void com20020_config(dev_link_t *link)
315 {
316     struct arcnet_local *lp;
317     client_handle_t handle;
318     tuple_t tuple;
319     cisparse_t parse;
320     com20020_dev_t *info;
321     struct net_device *dev;
322     int i, last_ret, last_fn;
323     u_char buf[64];
324     int ioaddr;
325
326     handle = link->handle;
327     info = link->priv;
328     dev = info->dev;
329
330     DEBUG(1,"config...\n");
331
332     DEBUG(0, "com20020_config(0x%p)\n", link);
333
334     tuple.Attributes = 0;
335     tuple.TupleData = buf;
336     tuple.TupleDataMax = 64;
337     tuple.TupleOffset = 0;
338     tuple.DesiredTuple = CISTPL_CONFIG;
339     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
340     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
341     CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
342     link->conf.ConfigBase = parse.config.base;
343
344     /* Configure card */
345     link->state |= DEV_CONFIG;
346
347     DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
348     i = !CS_SUCCESS;
349     if (!link->io.BasePort1)
350     {
351         for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
352         {
353             link->io.BasePort1 = ioaddr;
354             i = pcmcia_request_io(link->handle, &link->io);
355             if (i == CS_SUCCESS)
356                 break;
357         }
358     }
359     else
360         i = pcmcia_request_io(link->handle, &link->io);
361     
362     if (i != CS_SUCCESS)
363     {
364         DEBUG(1,"arcnet: requestIO failed totally!\n");
365         goto failed;
366     }
367         
368     ioaddr = dev->base_addr = link->io.BasePort1;
369     DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);
370
371     DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
372            link->irq.AssignedIRQ,
373            link->irq.IRQInfo1, link->irq.IRQInfo2);
374     i = pcmcia_request_irq(link->handle, &link->irq);
375     if (i != CS_SUCCESS)
376     {
377         DEBUG(1,"arcnet: requestIRQ failed totally!\n");
378         goto failed;
379     }
380
381     dev->irq = link->irq.AssignedIRQ;
382
383     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
384
385     if (com20020_check(dev))
386     {
387         regdump(dev);
388         goto failed;
389     }
390     
391     lp = dev->priv;
392     lp->card_name = "PCMCIA COM20020";
393     lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
394
395     link->dev = &info->node;
396     link->state &= ~DEV_CONFIG_PENDING;
397
398     i = com20020_found(dev, 0); /* calls register_netdev */
399     
400     if (i != 0) {
401         DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
402         link->dev = NULL;
403         goto failed;
404     }
405
406     strcpy(info->node.dev_name, dev->name);
407
408     DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
409            dev->name, dev->base_addr, dev->irq);
410     return;
411
412 cs_failed:
413     cs_error(link->handle, last_fn, last_ret);
414 failed:
415     DEBUG(1,"com20020_config failed...\n");
416     com20020_release(link);
417 } /* com20020_config */
418
419 /*======================================================================
420
421     After a card is removed, com20020_release() will unregister the net
422     device, and release the PCMCIA configuration.  If the device is
423     still open, this will be postponed until it is closed.
424
425 ======================================================================*/
426
427 static void com20020_release(dev_link_t *link)
428 {
429
430     DEBUG(1,"release...\n");
431
432     DEBUG(0, "com20020_release(0x%p)\n", link);
433
434     pcmcia_release_configuration(link->handle);
435     pcmcia_release_io(link->handle, &link->io);
436     pcmcia_release_irq(link->handle, &link->irq);
437
438     link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
439 }
440
441 /*======================================================================
442
443     The card status event handler.  Mostly, this schedules other
444     stuff to run after an event is received.  A CARD_REMOVAL event
445     also sets some flags to discourage the net drivers from trying
446     to talk to the card any more.
447
448 ======================================================================*/
449
450 static int com20020_event(event_t event, int priority,
451                           event_callback_args_t *args)
452 {
453     dev_link_t *link = args->client_data;
454     com20020_dev_t *info = link->priv;
455     struct net_device *dev = info->dev;
456
457     DEBUG(1, "com20020_event(0x%06x)\n", event);
458     
459     switch (event) {
460     case CS_EVENT_CARD_REMOVAL:
461         link->state &= ~DEV_PRESENT;
462         if (link->state & DEV_CONFIG)
463             netif_device_detach(dev);
464         break;
465     case CS_EVENT_CARD_INSERTION:
466         link->state |= DEV_PRESENT;
467         com20020_config(link); 
468         break;
469     case CS_EVENT_PM_SUSPEND:
470         link->state |= DEV_SUSPEND;
471         /* Fall through... */
472     case CS_EVENT_RESET_PHYSICAL:
473         if (link->state & DEV_CONFIG) {
474             if (link->open) {
475                 netif_device_detach(dev);
476             }
477             pcmcia_release_configuration(link->handle);
478         }
479         break;
480     case CS_EVENT_PM_RESUME:
481         link->state &= ~DEV_SUSPEND;
482         /* Fall through... */
483     case CS_EVENT_CARD_RESET:
484         if (link->state & DEV_CONFIG) {
485             pcmcia_request_configuration(link->handle, &link->conf);
486             if (link->open) {
487                 int ioaddr = dev->base_addr;
488                 struct arcnet_local *lp = dev->priv;
489                 ARCRESET;
490             }
491         }
492         break;
493     }
494     return 0;
495 } /* com20020_event */
496
497
498
499 static struct pcmcia_driver com20020_cs_driver = {
500         .owner          = THIS_MODULE,
501         .drv            = {
502                 .name   = "com20020_cs",
503         },
504         .attach         = com20020_attach,
505         .detach         = com20020_detach,
506 };
507
508 static int __init init_com20020_cs(void)
509 {
510         return pcmcia_register_driver(&com20020_cs_driver);
511 }
512
513 static void __exit exit_com20020_cs(void)
514 {
515         pcmcia_unregister_driver(&com20020_cs_driver);
516         while (dev_list != NULL)
517                 com20020_detach(dev_list);
518 }
519
520 module_init(init_com20020_cs);
521 module_exit(exit_com20020_cs);