[PATCH] pcmcia: embed dev_link_t into struct pcmcia_device
[deliverable/linux.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 com20020_dev_t *info;
144 struct net_device *dev;
1da177e4 145 struct arcnet_local *lp;
f8cfa618 146
1da177e4
LT
147 DEBUG(0, "com20020_attach()\n");
148
149 /* Create new network device */
1da177e4
LT
150 info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
151 if (!info)
152 goto fail_alloc_info;
153
154 dev = alloc_arcdev("");
155 if (!dev)
156 goto fail_alloc_dev;
157
158 memset(info, 0, sizeof(struct com20020_dev_t));
1da177e4
LT
159 lp = dev->priv;
160 lp->timeout = timeout;
161 lp->backplane = backplane;
162 lp->clockp = clockp;
163 lp->clockm = clockm & 3;
164 lp->hw.owner = THIS_MODULE;
165
166 /* fill in our module parameters as defaults */
167 dev->dev_addr[0] = node;
168
fd238232
DB
169 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
170 p_dev->io.NumPorts1 = 16;
171 p_dev->io.IOAddrLines = 16;
172 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
173 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
174 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
175 p_dev->conf.IntType = INT_MEMORY_AND_IO;
176 p_dev->conf.Present = PRESENT_OPTION;
1da177e4 177
fd238232
DB
178 p_dev->irq.Instance = info->dev = dev;
179 p_dev->priv = info;
1da177e4 180
fd238232
DB
181 p_dev->state |= DEV_PRESENT;
182 com20020_config(p_dev);
1da177e4 183
f8cfa618 184 return 0;
1da177e4
LT
185
186fail_alloc_dev:
187 kfree(info);
188fail_alloc_info:
f8cfa618 189 return -ENOMEM;
1da177e4
LT
190} /* com20020_attach */
191
192/*======================================================================
193
194 This deletes a driver "instance". The device is de-registered
195 with Card Services. If it has been released, all local data
196 structures are freed. Otherwise, the structures will be freed
197 when the device is released.
198
199======================================================================*/
200
cc3b4866 201static void com20020_detach(struct pcmcia_device *p_dev)
1da177e4 202{
cc3b4866 203 dev_link_t *link = dev_to_instance(p_dev);
1da177e4 204 struct com20020_dev_t *info = link->priv;
b4635811
DB
205 struct net_device *dev = info->dev;
206
1da177e4
LT
207 DEBUG(1,"detach...\n");
208
209 DEBUG(0, "com20020_detach(0x%p)\n", link);
210
fd238232 211 if (link->dev_node) {
1da177e4
LT
212 DEBUG(1,"unregister...\n");
213
214 unregister_netdev(dev);
b4635811 215
1da177e4
LT
216 /*
217 * this is necessary because we register our IRQ separately
218 * from card services.
219 */
220 if (dev->irq)
221 free_irq(dev->irq, dev);
222 }
223
224 if (link->state & DEV_CONFIG)
225 com20020_release(link);
226
1da177e4
LT
227 /* Unlink device structure, free bits */
228 DEBUG(1,"unlinking...\n");
1da177e4
LT
229 if (link->priv)
230 {
231 dev = info->dev;
232 if (dev)
233 {
234 DEBUG(1,"kfree...\n");
235 free_netdev(dev);
236 }
237 DEBUG(1,"kfree2...\n");
238 kfree(info);
239 }
1da177e4
LT
240
241} /* com20020_detach */
242
243/*======================================================================
244
245 com20020_config() is scheduled to run after a CARD_INSERTION event
246 is received, to configure the PCMCIA socket, and to make the
247 device available to the system.
248
249======================================================================*/
250
251#define CS_CHECK(fn, ret) \
252do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
253
254static void com20020_config(dev_link_t *link)
255{
256 struct arcnet_local *lp;
257 client_handle_t handle;
258 tuple_t tuple;
259 cisparse_t parse;
260 com20020_dev_t *info;
261 struct net_device *dev;
262 int i, last_ret, last_fn;
263 u_char buf[64];
264 int ioaddr;
265
266 handle = link->handle;
267 info = link->priv;
268 dev = info->dev;
269
270 DEBUG(1,"config...\n");
271
272 DEBUG(0, "com20020_config(0x%p)\n", link);
273
274 tuple.Attributes = 0;
275 tuple.TupleData = buf;
276 tuple.TupleDataMax = 64;
277 tuple.TupleOffset = 0;
278 tuple.DesiredTuple = CISTPL_CONFIG;
279 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
280 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
281 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
282 link->conf.ConfigBase = parse.config.base;
283
284 /* Configure card */
285 link->state |= DEV_CONFIG;
286
287 DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
288 i = !CS_SUCCESS;
289 if (!link->io.BasePort1)
290 {
291 for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
292 {
293 link->io.BasePort1 = ioaddr;
294 i = pcmcia_request_io(link->handle, &link->io);
295 if (i == CS_SUCCESS)
296 break;
297 }
298 }
299 else
300 i = pcmcia_request_io(link->handle, &link->io);
301
302 if (i != CS_SUCCESS)
303 {
304 DEBUG(1,"arcnet: requestIO failed totally!\n");
305 goto failed;
306 }
307
308 ioaddr = dev->base_addr = link->io.BasePort1;
309 DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);
310
311 DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
312 link->irq.AssignedIRQ,
313 link->irq.IRQInfo1, link->irq.IRQInfo2);
314 i = pcmcia_request_irq(link->handle, &link->irq);
315 if (i != CS_SUCCESS)
316 {
317 DEBUG(1,"arcnet: requestIRQ failed totally!\n");
318 goto failed;
319 }
320
321 dev->irq = link->irq.AssignedIRQ;
322
323 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
324
325 if (com20020_check(dev))
326 {
327 regdump(dev);
328 goto failed;
329 }
330
331 lp = dev->priv;
332 lp->card_name = "PCMCIA COM20020";
333 lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
334
fd238232 335 link->dev_node = &info->node;
1da177e4
LT
336 link->state &= ~DEV_CONFIG_PENDING;
337 SET_NETDEV_DEV(dev, &handle_to_dev(handle));
338
339 i = com20020_found(dev, 0); /* calls register_netdev */
340
341 if (i != 0) {
342 DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
fd238232 343 link->dev_node = NULL;
1da177e4
LT
344 goto failed;
345 }
346
347 strcpy(info->node.dev_name, dev->name);
348
349 DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
350 dev->name, dev->base_addr, dev->irq);
351 return;
352
353cs_failed:
354 cs_error(link->handle, last_fn, last_ret);
355failed:
356 DEBUG(1,"com20020_config failed...\n");
357 com20020_release(link);
358} /* com20020_config */
359
360/*======================================================================
361
362 After a card is removed, com20020_release() will unregister the net
363 device, and release the PCMCIA configuration. If the device is
364 still open, this will be postponed until it is closed.
365
366======================================================================*/
367
368static void com20020_release(dev_link_t *link)
369{
5f2a71fc
DB
370 DEBUG(0, "com20020_release(0x%p)\n", link);
371 pcmcia_disable_device(link->handle);
1da177e4
LT
372}
373
98e4c28b
DB
374static int com20020_suspend(struct pcmcia_device *p_dev)
375{
376 dev_link_t *link = dev_to_instance(p_dev);
377 com20020_dev_t *info = link->priv;
378 struct net_device *dev = info->dev;
379
8661bb5b
DB
380 if ((link->state & DEV_CONFIG) && (link->open))
381 netif_device_detach(dev);
98e4c28b
DB
382
383 return 0;
384}
385
386static int com20020_resume(struct pcmcia_device *p_dev)
387{
388 dev_link_t *link = dev_to_instance(p_dev);
389 com20020_dev_t *info = link->priv;
390 struct net_device *dev = info->dev;
391
8661bb5b
DB
392 if ((link->state & DEV_CONFIG) && (link->open)) {
393 int ioaddr = dev->base_addr;
394 struct arcnet_local *lp = dev->priv;
395 ARCRESET;
396 }
98e4c28b
DB
397
398 return 0;
399}
400
7fb22bb4
DB
401static struct pcmcia_device_id com20020_ids[] = {
402 PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
403 PCMCIA_DEVICE_NULL
404};
405MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
1da177e4
LT
406
407static struct pcmcia_driver com20020_cs_driver = {
408 .owner = THIS_MODULE,
409 .drv = {
410 .name = "com20020_cs",
411 },
f8cfa618 412 .probe = com20020_attach,
cc3b4866 413 .remove = com20020_detach,
7fb22bb4 414 .id_table = com20020_ids,
98e4c28b
DB
415 .suspend = com20020_suspend,
416 .resume = com20020_resume,
1da177e4
LT
417};
418
419static int __init init_com20020_cs(void)
420{
421 return pcmcia_register_driver(&com20020_cs_driver);
422}
423
424static void __exit exit_com20020_cs(void)
425{
426 pcmcia_unregister_driver(&com20020_cs_driver);
1da177e4
LT
427}
428
429module_init(init_com20020_cs);
430module_exit(exit_com20020_cs);
This page took 0.145791 seconds and 5 git commands to generate.