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