8f9f75f56c78d701a7df2c7c0e4075150354005b
[linux-flexiantxendom0-3.2.10.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(u_long arg);
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     int dev_configured;
145     dev_node_t          node;
146 } com20020_dev_t;
147
148 /*======================================================================
149
150     This bit of code is used to avoid unregistering network devices
151     at inappropriate times.  2.2 and later kernels are fairly picky
152     about when this can happen.
153     
154 ======================================================================*/
155
156 static void flush_stale_links(void)
157 {
158     dev_link_t *link, *next;
159     for (link = dev_list; link; link = next) {
160         next = link->next;
161         if (link->state & DEV_STALE_LINK)
162             com20020_detach(link);
163     }
164 }
165
166 /*======================================================================
167
168     com20020_attach() creates an "instance" of the driver, allocating
169     local data structures for one device.  The device is registered
170     with Card Services.
171
172 ======================================================================*/
173
174 static void com20020cs_open_close(struct net_device *dev, bool open)
175 {
176     if (open)
177         MOD_INC_USE_COUNT;
178     else
179         MOD_DEC_USE_COUNT;
180 }
181
182 static dev_link_t *com20020_attach(void)
183 {
184     client_reg_t client_reg;
185     dev_link_t *link;
186     com20020_dev_t *info;
187     struct net_device *dev;
188     int i, ret;
189     struct arcnet_local *lp;
190     
191     DEBUG(0, "com20020_attach()\n");
192     flush_stale_links();
193
194     /* Create new network device */
195     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
196     if (!link)
197         return NULL;
198
199     info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
200     if (!info)
201         goto fail_alloc_info;
202
203     lp =  kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
204     if (!lp)
205         goto fail_alloc_lp;
206
207     dev = dev_alloc("arc%d", &ret);
208     if (!dev)
209         goto fail_alloc_dev;
210
211     memset(info, 0, sizeof(struct com20020_dev_t));
212     memset(lp, 0, sizeof(struct arcnet_local));
213     memset(link, 0, sizeof(struct dev_link_t));
214     dev->priv = lp;
215
216     init_timer(&link->release);
217     link->release.function = &com20020_release;
218     link->release.data = (u_long)link;
219     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
220     link->io.NumPorts1 = 16;
221     link->io.IOAddrLines = 16;
222     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
223     link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
224     if (irq_list[0] == -1)
225         link->irq.IRQInfo2 = irq_mask;
226     else
227         for (i = 0; i < 4; i++)
228             link->irq.IRQInfo2 |= 1 << irq_list[i];
229     link->conf.Attributes = CONF_ENABLE_IRQ;
230     link->conf.Vcc = 50;
231     link->conf.IntType = INT_MEMORY_AND_IO;
232     link->conf.Present = PRESENT_OPTION;
233
234     /* fill in our module parameters as defaults */
235     dev->dev_addr[0] = node;
236     lp->timeout = timeout;
237     lp->backplane = backplane;
238     lp->clockp = clockp;
239     lp->clockm = clockm & 3;
240     lp->hw.open_close_ll = com20020cs_open_close;
241
242     link->irq.Instance = info->dev = dev;
243     link->priv = info;
244
245     /* Register with Card Services */
246     link->next = dev_list;
247     dev_list = link;
248     client_reg.dev_info = &dev_info;
249     client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
250     client_reg.EventMask =
251         CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
252         CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
253         CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
254     client_reg.event_handler = &com20020_event;
255     client_reg.Version = 0x0210;
256     client_reg.event_callback_args.client_data = link;
257     ret = CardServices(RegisterClient, &link->handle, &client_reg);
258     if (ret != 0) {
259         cs_error(link->handle, RegisterClient, ret);
260         com20020_detach(link);
261         return NULL;
262     }
263
264     return link;
265
266 fail_alloc_dev:
267     kfree(lp);
268 fail_alloc_lp:
269     kfree(info);
270 fail_alloc_info:
271     kfree(link);
272     return NULL;
273 } /* com20020_attach */
274
275 /*======================================================================
276
277     This deletes a driver "instance".  The device is de-registered
278     with Card Services.  If it has been released, all local data
279     structures are freed.  Otherwise, the structures will be freed
280     when the device is released.
281
282 ======================================================================*/
283
284 static void com20020_detach(dev_link_t *link)
285 {
286     struct com20020_dev_t *info = link->priv;
287     dev_link_t **linkp;
288     struct net_device *dev; 
289     
290     DEBUG(1,"detach...\n");
291
292     DEBUG(0, "com20020_detach(0x%p)\n", link);
293
294     /* Locate device structure */
295     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
296         if (*linkp == link) break;
297     if (*linkp == NULL)
298         return;
299
300     dev = info->dev;
301
302     if (link->state & DEV_CONFIG) {
303         com20020_release((u_long)link);
304         if (link->state & DEV_STALE_CONFIG) {
305             link->state |= DEV_STALE_LINK;
306             return;
307         }
308     }
309
310     if (link->handle)
311         CardServices(DeregisterClient, link->handle);
312
313     /* Unlink device structure, free bits */
314     DEBUG(1,"unlinking...\n");
315     *linkp = link->next;
316     if (link->priv)
317     {
318         dev = info->dev;
319         if (dev)
320         {
321             if (info->dev_configured)
322             {
323                 DEBUG(1,"unregister...\n");
324
325                 if (netif_running(dev))
326                     dev->stop(dev);
327             
328                 /*
329                  * this is necessary because we register our IRQ separately
330                  * from card services.
331                  */
332                 if (dev->irq)
333                     free_irq(dev->irq, dev);
334                 
335                 /* ...but I/O ports are done automatically by card services */
336                 
337                 unregister_netdev(dev);
338                 MOD_DEC_USE_COUNT;
339             }
340             
341             DEBUG(1,"kfree...\n");
342             kfree(dev->priv);
343             kfree(dev);
344         }
345         DEBUG(1,"kfree2...\n");
346         kfree(info);
347     }
348     DEBUG(1,"kfree3...\n");
349     kfree(link);
350
351 } /* com20020_detach */
352
353 /*======================================================================
354
355     com20020_config() is scheduled to run after a CARD_INSERTION event
356     is received, to configure the PCMCIA socket, and to make the
357     device available to the system.
358
359 ======================================================================*/
360
361 #define CS_CHECK(fn, args...) \
362 while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
363
364 static void com20020_config(dev_link_t *link)
365 {
366     struct arcnet_local *lp;
367     client_handle_t handle;
368     tuple_t tuple;
369     cisparse_t parse;
370     com20020_dev_t *info;
371     struct net_device *dev;
372     int i, last_ret, last_fn;
373     u_char buf[64];
374     int ioaddr;
375
376     handle = link->handle;
377     info = link->priv;
378     dev = info->dev;
379
380     DEBUG(1,"config...\n");
381
382     DEBUG(0, "com20020_config(0x%p)\n", link);
383
384     tuple.Attributes = 0;
385     tuple.TupleData = buf;
386     tuple.TupleDataMax = 64;
387     tuple.TupleOffset = 0;
388     tuple.DesiredTuple = CISTPL_CONFIG;
389     CS_CHECK(GetFirstTuple, handle, &tuple);
390     CS_CHECK(GetTupleData, handle, &tuple);
391     CS_CHECK(ParseTuple, handle, &tuple, &parse);
392     link->conf.ConfigBase = parse.config.base;
393
394     /* Configure card */
395     link->state |= DEV_CONFIG;
396     strcpy(info->node.dev_name, dev->name);
397
398     DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
399     i = !CS_SUCCESS;
400     if (!link->io.BasePort1)
401     {
402         for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
403         {
404             link->io.BasePort1 = ioaddr;
405             i = CardServices(RequestIO, link->handle, &link->io);
406             if (i == CS_SUCCESS)
407                 break;
408         }
409     }
410     else
411         i = CardServices(RequestIO, link->handle, &link->io);
412     
413     if (i != CS_SUCCESS)
414     {
415         DEBUG(1,"arcnet: requestIO failed totally!\n");
416         goto failed;
417     }
418         
419     ioaddr = dev->base_addr = link->io.BasePort1;
420     DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);
421
422     DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
423            link->irq.AssignedIRQ,
424            link->irq.IRQInfo1, link->irq.IRQInfo2);
425     i = CardServices(RequestIRQ, link->handle, &link->irq);
426     if (i != CS_SUCCESS)
427     {
428         DEBUG(1,"arcnet: requestIRQ failed totally!\n");
429         goto failed;
430     }
431
432     dev->irq = link->irq.AssignedIRQ;
433
434     CS_CHECK(RequestConfiguration, link->handle, &link->conf);
435
436     if (com20020_check(dev))
437     {
438         regdump(dev);
439         goto failed;
440     }
441     
442     MOD_INC_USE_COUNT;
443
444     lp = dev->priv;
445     lp->card_name = "PCMCIA COM20020";
446     lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
447
448     i = com20020_found(dev, 0);
449     
450     if (i != 0) {
451         DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
452         goto failed;
453     }
454
455     info->dev_configured = 1;
456     link->dev = &info->node;
457     link->state &= ~DEV_CONFIG_PENDING;
458
459     DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
460            dev->name, dev->base_addr, dev->irq);
461     return;
462
463 cs_failed:
464     cs_error(link->handle, last_fn, last_ret);
465 failed:
466     DEBUG(1,"com20020_config failed...\n");
467     com20020_release((u_long)link);
468 } /* com20020_config */
469
470 /*======================================================================
471
472     After a card is removed, com20020_release() will unregister the net
473     device, and release the PCMCIA configuration.  If the device is
474     still open, this will be postponed until it is closed.
475
476 ======================================================================*/
477
478 static void com20020_release(u_long arg)
479 {
480     dev_link_t *link = (dev_link_t *)arg;
481
482     DEBUG(1,"release...\n");
483
484     DEBUG(0, "com20020_release(0x%p)\n", link);
485
486     if (link->open) {
487         DEBUG(1,"postpone...\n");
488         DEBUG(1, "com20020_cs: release postponed, device stll open\n");
489         link->state |= DEV_STALE_CONFIG;
490         return;
491     }
492
493     CardServices(ReleaseConfiguration, link->handle);
494     CardServices(ReleaseIO, link->handle, &link->io);
495     CardServices(ReleaseIRQ, link->handle, &link->irq);
496
497     link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
498
499 } /* com20020_release */
500
501 /*======================================================================
502
503     The card status event handler.  Mostly, this schedules other
504     stuff to run after an event is received.  A CARD_REMOVAL event
505     also sets some flags to discourage the net drivers from trying
506     to talk to the card any more.
507
508 ======================================================================*/
509
510 static int com20020_event(event_t event, int priority,
511                           event_callback_args_t *args)
512 {
513     dev_link_t *link = args->client_data;
514     com20020_dev_t *info = link->priv;
515     struct net_device *dev = info->dev;
516
517     DEBUG(1, "com20020_event(0x%06x)\n", event);
518     
519     switch (event) {
520     case CS_EVENT_CARD_REMOVAL:
521         link->state &= ~DEV_PRESENT;
522         if (link->state & DEV_CONFIG) {
523             netif_device_detach(dev);
524             link->release.expires = jiffies + HZ/20;
525             link->state |= DEV_RELEASE_PENDING;
526             add_timer(&link->release);
527         }
528         break;
529     case CS_EVENT_CARD_INSERTION:
530         link->state |= DEV_PRESENT;
531         com20020_config(link); 
532         break;
533     case CS_EVENT_PM_SUSPEND:
534         link->state |= DEV_SUSPEND;
535         /* Fall through... */
536     case CS_EVENT_RESET_PHYSICAL:
537         if (link->state & DEV_CONFIG) {
538             if (link->open) {
539                 netif_device_detach(dev);
540             }
541             CardServices(ReleaseConfiguration, link->handle);
542         }
543         break;
544     case CS_EVENT_PM_RESUME:
545         link->state &= ~DEV_SUSPEND;
546         /* Fall through... */
547     case CS_EVENT_CARD_RESET:
548         if (link->state & DEV_CONFIG) {
549             CardServices(RequestConfiguration, link->handle, &link->conf);
550             if (link->open) {
551                 int ioaddr = dev->base_addr;
552                 struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
553                 ARCRESET;
554             }
555         }
556         break;
557     }
558     return 0;
559 } /* com20020_event */
560
561
562
563 static struct pcmcia_driver com20020_cs_driver = {
564         .owner          = THIS_MODULE,
565         .drv            = {
566                 .name   = "com20020_cs",
567         },
568         .attach         = com20020_attach,
569         .detach         = com20020_detach,
570 };
571
572 static int __init init_com20020_cs(void)
573 {
574         return pcmcia_register_driver(&com20020_cs_driver);
575 }
576
577 static void __exit exit_com20020_cs(void)
578 {
579         pcmcia_unregister_driver(&com20020_cs_driver);
580         while (dev_list != NULL)
581                 com20020_detach(dev_list);
582 }
583
584 module_init(init_com20020_cs);
585 module_exit(exit_com20020_cs);