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