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