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