pcmcia: convert pcmcia_request_configuration to pcmcia_enable_device
[deliverable/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 .drv = {
368 .name = "com20020_cs",
369 },
370 .probe = com20020_probe,
371 .remove = com20020_detach,
372 .id_table = com20020_ids,
373 .suspend = com20020_suspend,
374 .resume = com20020_resume,
375 };
376
377 static int __init init_com20020_cs(void)
378 {
379 return pcmcia_register_driver(&com20020_cs_driver);
380 }
381
382 static void __exit exit_com20020_cs(void)
383 {
384 pcmcia_unregister_driver(&com20020_cs_driver);
385 }
386
387 module_init(init_com20020_cs);
388 module_exit(exit_com20020_cs);
This page took 0.492772 seconds and 5 git commands to generate.