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