[PATCH] pcmcia: convert remaining users of pcmcia_release_io and _irq
[linux-2.6-block.git] / drivers / net / pcmcia / com20020_cs.c
CommitLineData
1da177e4
LT
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
1da177e4
LT
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
58static int pc_debug = PCMCIA_DEBUG;
59module_param(pc_debug, int, 0);
60#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
61
62static 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)
96static inline void regdump(struct net_device *dev) { }
97
98#endif
99
100
101/*====================================================================*/
102
103/* Parameters that can be set with 'insmod' */
104
105static int node;
106static int timeout = 3;
107static int backplane;
108static int clockp;
109static int clockm;
110
111module_param(node, int, 0);
112module_param(timeout, int, 0);
113module_param(backplane, int, 0);
114module_param(clockp, int, 0);
115module_param(clockm, int, 0);
116
117MODULE_LICENSE("GPL");
118
119/*====================================================================*/
120
121static void com20020_config(dev_link_t *link);
122static void com20020_release(dev_link_t *link);
1da177e4 123
cc3b4866 124static void com20020_detach(struct pcmcia_device *p_dev);
1da177e4 125
1da177e4
LT
126/*====================================================================*/
127
128typedef 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
f8cfa618 141static int com20020_attach(struct pcmcia_device *p_dev)
1da177e4 142{
1da177e4
LT
143 dev_link_t *link;
144 com20020_dev_t *info;
145 struct net_device *dev;
1da177e4 146 struct arcnet_local *lp;
f8cfa618 147
1da177e4
LT
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)
f8cfa618 153 return -ENOMEM;
1da177e4
LT
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.Vcc = 50;
182 link->conf.IntType = INT_MEMORY_AND_IO;
183 link->conf.Present = PRESENT_OPTION;
184
1da177e4
LT
185 link->irq.Instance = info->dev = dev;
186 link->priv = info;
187
f8cfa618
DB
188 link->state |= DEV_PRESENT;
189 com20020_config(link);
1da177e4 190
f8cfa618 191 return 0;
1da177e4
LT
192
193fail_alloc_dev:
194 kfree(info);
195fail_alloc_info:
196 kfree(link);
f8cfa618 197 return -ENOMEM;
1da177e4
LT
198} /* com20020_attach */
199
200/*======================================================================
201
202 This deletes a driver "instance". The device is de-registered
203 with Card Services. If it has been released, all local data
204 structures are freed. Otherwise, the structures will be freed
205 when the device is released.
206
207======================================================================*/
208
cc3b4866 209static void com20020_detach(struct pcmcia_device *p_dev)
1da177e4 210{
cc3b4866 211 dev_link_t *link = dev_to_instance(p_dev);
1da177e4 212 struct com20020_dev_t *info = link->priv;
b4635811
DB
213 struct net_device *dev = info->dev;
214
1da177e4
LT
215 DEBUG(1,"detach...\n");
216
217 DEBUG(0, "com20020_detach(0x%p)\n", link);
218
1da177e4
LT
219 if (link->dev) {
220 DEBUG(1,"unregister...\n");
221
222 unregister_netdev(dev);
b4635811 223
1da177e4
LT
224 /*
225 * this is necessary because we register our IRQ separately
226 * from card services.
227 */
228 if (dev->irq)
229 free_irq(dev->irq, dev);
230 }
231
232 if (link->state & DEV_CONFIG)
233 com20020_release(link);
234
1da177e4
LT
235 /* Unlink device structure, free bits */
236 DEBUG(1,"unlinking...\n");
1da177e4
LT
237 if (link->priv)
238 {
239 dev = info->dev;
240 if (dev)
241 {
242 DEBUG(1,"kfree...\n");
243 free_netdev(dev);
244 }
245 DEBUG(1,"kfree2...\n");
246 kfree(info);
247 }
248 DEBUG(1,"kfree3...\n");
249 kfree(link);
250
251} /* com20020_detach */
252
253/*======================================================================
254
255 com20020_config() is scheduled to run after a CARD_INSERTION event
256 is received, to configure the PCMCIA socket, and to make the
257 device available to the system.
258
259======================================================================*/
260
261#define CS_CHECK(fn, ret) \
262do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
263
264static void com20020_config(dev_link_t *link)
265{
266 struct arcnet_local *lp;
267 client_handle_t handle;
268 tuple_t tuple;
269 cisparse_t parse;
270 com20020_dev_t *info;
271 struct net_device *dev;
272 int i, last_ret, last_fn;
273 u_char buf[64];
274 int ioaddr;
275
276 handle = link->handle;
277 info = link->priv;
278 dev = info->dev;
279
280 DEBUG(1,"config...\n");
281
282 DEBUG(0, "com20020_config(0x%p)\n", link);
283
284 tuple.Attributes = 0;
285 tuple.TupleData = buf;
286 tuple.TupleDataMax = 64;
287 tuple.TupleOffset = 0;
288 tuple.DesiredTuple = CISTPL_CONFIG;
289 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
290 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
291 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
292 link->conf.ConfigBase = parse.config.base;
293
294 /* Configure card */
295 link->state |= DEV_CONFIG;
296
297 DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
298 i = !CS_SUCCESS;
299 if (!link->io.BasePort1)
300 {
301 for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
302 {
303 link->io.BasePort1 = ioaddr;
304 i = pcmcia_request_io(link->handle, &link->io);
305 if (i == CS_SUCCESS)
306 break;
307 }
308 }
309 else
310 i = pcmcia_request_io(link->handle, &link->io);
311
312 if (i != CS_SUCCESS)
313 {
314 DEBUG(1,"arcnet: requestIO failed totally!\n");
315 goto failed;
316 }
317
318 ioaddr = dev->base_addr = link->io.BasePort1;
319 DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);
320
321 DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
322 link->irq.AssignedIRQ,
323 link->irq.IRQInfo1, link->irq.IRQInfo2);
324 i = pcmcia_request_irq(link->handle, &link->irq);
325 if (i != CS_SUCCESS)
326 {
327 DEBUG(1,"arcnet: requestIRQ failed totally!\n");
328 goto failed;
329 }
330
331 dev->irq = link->irq.AssignedIRQ;
332
333 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
334
335 if (com20020_check(dev))
336 {
337 regdump(dev);
338 goto failed;
339 }
340
341 lp = dev->priv;
342 lp->card_name = "PCMCIA COM20020";
343 lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
344
345 link->dev = &info->node;
346 link->state &= ~DEV_CONFIG_PENDING;
347 SET_NETDEV_DEV(dev, &handle_to_dev(handle));
348
349 i = com20020_found(dev, 0); /* calls register_netdev */
350
351 if (i != 0) {
352 DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
353 link->dev = NULL;
354 goto failed;
355 }
356
357 strcpy(info->node.dev_name, dev->name);
358
359 DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
360 dev->name, dev->base_addr, dev->irq);
361 return;
362
363cs_failed:
364 cs_error(link->handle, last_fn, last_ret);
365failed:
366 DEBUG(1,"com20020_config failed...\n");
367 com20020_release(link);
368} /* com20020_config */
369
370/*======================================================================
371
372 After a card is removed, com20020_release() will unregister the net
373 device, and release the PCMCIA configuration. If the device is
374 still open, this will be postponed until it is closed.
375
376======================================================================*/
377
378static void com20020_release(dev_link_t *link)
379{
5f2a71fc
DB
380 DEBUG(0, "com20020_release(0x%p)\n", link);
381 pcmcia_disable_device(link->handle);
1da177e4
LT
382}
383
98e4c28b
DB
384static int com20020_suspend(struct pcmcia_device *p_dev)
385{
386 dev_link_t *link = dev_to_instance(p_dev);
387 com20020_dev_t *info = link->priv;
388 struct net_device *dev = info->dev;
389
390 link->state |= DEV_SUSPEND;
391 if (link->state & DEV_CONFIG) {
392 if (link->open) {
393 netif_device_detach(dev);
394 }
395 pcmcia_release_configuration(link->handle);
396 }
397
398 return 0;
399}
400
401static int com20020_resume(struct pcmcia_device *p_dev)
402{
403 dev_link_t *link = dev_to_instance(p_dev);
404 com20020_dev_t *info = link->priv;
405 struct net_device *dev = info->dev;
406
407 link->state &= ~DEV_SUSPEND;
408 if (link->state & DEV_CONFIG) {
409 pcmcia_request_configuration(link->handle, &link->conf);
410 if (link->open) {
411 int ioaddr = dev->base_addr;
412 struct arcnet_local *lp = dev->priv;
413 ARCRESET;
414 }
415 }
416
417 return 0;
418}
419
7fb22bb4
DB
420static struct pcmcia_device_id com20020_ids[] = {
421 PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
422 PCMCIA_DEVICE_NULL
423};
424MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
1da177e4
LT
425
426static struct pcmcia_driver com20020_cs_driver = {
427 .owner = THIS_MODULE,
428 .drv = {
429 .name = "com20020_cs",
430 },
f8cfa618 431 .probe = com20020_attach,
cc3b4866 432 .remove = com20020_detach,
7fb22bb4 433 .id_table = com20020_ids,
98e4c28b
DB
434 .suspend = com20020_suspend,
435 .resume = com20020_resume,
1da177e4
LT
436};
437
438static int __init init_com20020_cs(void)
439{
440 return pcmcia_register_driver(&com20020_cs_driver);
441}
442
443static void __exit exit_com20020_cs(void)
444{
445 pcmcia_unregister_driver(&com20020_cs_driver);
1da177e4
LT
446}
447
448module_init(init_com20020_cs);
449module_exit(exit_com20020_cs);