]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/pcmcia/com20020_cs.c
pcmcia: dev_node removal (drivers with unregister_netdev check)
[mirror_ubuntu-artful-kernel.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
dd0fab5b 56#ifdef DEBUG
1da177e4
LT
57
58static 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
1da177e4
LT
91static inline void regdump(struct net_device *dev) { }
92
93#endif
94
95
96/*====================================================================*/
97
98/* Parameters that can be set with 'insmod' */
99
100static int node;
101static int timeout = 3;
102static int backplane;
103static int clockp;
104static int clockm;
105
106module_param(node, int, 0);
107module_param(timeout, int, 0);
108module_param(backplane, int, 0);
109module_param(clockp, int, 0);
110module_param(clockm, int, 0);
111
112MODULE_LICENSE("GPL");
113
114/*====================================================================*/
115
15b99ac1 116static int com20020_config(struct pcmcia_device *link);
fba395ee 117static void com20020_release(struct pcmcia_device *link);
1da177e4 118
cc3b4866 119static void com20020_detach(struct pcmcia_device *p_dev);
1da177e4 120
1da177e4
LT
121/*====================================================================*/
122
123typedef struct com20020_dev_t {
124 struct net_device *dev;
1da177e4
LT
125} com20020_dev_t;
126
127/*======================================================================
128
129 com20020_attach() creates an "instance" of the driver, allocating
130 local data structures for one device. The device is registered
131 with Card Services.
132
133======================================================================*/
134
15b99ac1 135static int com20020_probe(struct pcmcia_device *p_dev)
1da177e4 136{
1da177e4
LT
137 com20020_dev_t *info;
138 struct net_device *dev;
1da177e4 139 struct arcnet_local *lp;
f8cfa618 140
dd0fab5b 141 dev_dbg(&p_dev->dev, "com20020_attach()\n");
1da177e4
LT
142
143 /* Create new network device */
dd00cc48 144 info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
1da177e4
LT
145 if (!info)
146 goto fail_alloc_info;
147
148 dev = alloc_arcdev("");
149 if (!dev)
150 goto fail_alloc_dev;
151
4cf1653a 152 lp = netdev_priv(dev);
1da177e4
LT
153 lp->timeout = timeout;
154 lp->backplane = backplane;
155 lp->clockp = clockp;
156 lp->clockm = clockm & 3;
157 lp->hw.owner = THIS_MODULE;
158
159 /* fill in our module parameters as defaults */
160 dev->dev_addr[0] = node;
161
fd238232
DB
162 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
163 p_dev->io.NumPorts1 = 16;
164 p_dev->io.IOAddrLines = 16;
fd238232
DB
165 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
166 p_dev->conf.IntType = INT_MEMORY_AND_IO;
1da177e4 167
5fa9167a 168 info->dev = dev;
fd238232 169 p_dev->priv = info;
1da177e4 170
15b99ac1 171 return com20020_config(p_dev);
1da177e4
LT
172
173fail_alloc_dev:
174 kfree(info);
175fail_alloc_info:
f8cfa618 176 return -ENOMEM;
1da177e4
LT
177} /* com20020_attach */
178
179/*======================================================================
180
181 This deletes a driver "instance". The device is de-registered
182 with Card Services. If it has been released, all local data
183 structures are freed. Otherwise, the structures will be freed
184 when the device is released.
185
186======================================================================*/
187
fba395ee 188static void com20020_detach(struct pcmcia_device *link)
1da177e4
LT
189{
190 struct com20020_dev_t *info = link->priv;
b4635811
DB
191 struct net_device *dev = info->dev;
192
dd0fab5b 193 dev_dbg(&link->dev, "detach...\n");
1da177e4 194
dd0fab5b 195 dev_dbg(&link->dev, "com20020_detach\n");
1da177e4 196
c7c2fa07 197 dev_dbg(&link->dev, "unregister...\n");
1da177e4 198
c7c2fa07 199 unregister_netdev(dev);
b4635811 200
c7c2fa07
DB
201 /*
202 * this is necessary because we register our IRQ separately
203 * from card services.
204 */
205 if (dev->irq)
1da177e4 206 free_irq(dev->irq, dev);
1da177e4 207
e2d40963 208 com20020_release(link);
1da177e4 209
1da177e4 210 /* Unlink device structure, free bits */
dd0fab5b 211 dev_dbg(&link->dev, "unlinking...\n");
1da177e4
LT
212 if (link->priv)
213 {
214 dev = info->dev;
215 if (dev)
216 {
dd0fab5b 217 dev_dbg(&link->dev, "kfree...\n");
1da177e4
LT
218 free_netdev(dev);
219 }
dd0fab5b 220 dev_dbg(&link->dev, "kfree2...\n");
1da177e4
LT
221 kfree(info);
222 }
1da177e4
LT
223
224} /* com20020_detach */
225
226/*======================================================================
227
228 com20020_config() is scheduled to run after a CARD_INSERTION event
229 is received, to configure the PCMCIA socket, and to make the
230 device available to the system.
231
232======================================================================*/
233
15b99ac1 234static int com20020_config(struct pcmcia_device *link)
1da177e4
LT
235{
236 struct arcnet_local *lp;
1da177e4
LT
237 com20020_dev_t *info;
238 struct net_device *dev;
dd0fab5b 239 int i, ret;
1da177e4
LT
240 int ioaddr;
241
1da177e4
LT
242 info = link->priv;
243 dev = info->dev;
244
dd0fab5b 245 dev_dbg(&link->dev, "config...\n");
1da177e4 246
dd0fab5b 247 dev_dbg(&link->dev, "com20020_config\n");
1da177e4 248
dd0fab5b 249 dev_dbg(&link->dev, "baseport1 is %Xh\n", link->io.BasePort1);
4c89e88b 250 i = -ENODEV;
1da177e4
LT
251 if (!link->io.BasePort1)
252 {
253 for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
254 {
255 link->io.BasePort1 = ioaddr;
fba395ee 256 i = pcmcia_request_io(link, &link->io);
4c89e88b 257 if (i == 0)
1da177e4
LT
258 break;
259 }
260 }
261 else
fba395ee 262 i = pcmcia_request_io(link, &link->io);
1da177e4 263
4c89e88b 264 if (i != 0)
1da177e4 265 {
dd0fab5b 266 dev_dbg(&link->dev, "requestIO failed totally!\n");
1da177e4
LT
267 goto failed;
268 }
269
270 ioaddr = dev->base_addr = link->io.BasePort1;
dd0fab5b 271 dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
1da177e4 272
5fa9167a 273 dev_dbg(&link->dev, "request IRQ %d\n",
eb14120f
DB
274 link->irq);
275 if (!link->irq)
1da177e4 276 {
dd0fab5b 277 dev_dbg(&link->dev, "requestIRQ failed totally!\n");
1da177e4
LT
278 goto failed;
279 }
280
eb14120f 281 dev->irq = link->irq;
1da177e4 282
dd0fab5b
DB
283 ret = pcmcia_request_configuration(link, &link->conf);
284 if (ret)
285 goto failed;
1da177e4
LT
286
287 if (com20020_check(dev))
288 {
289 regdump(dev);
290 goto failed;
291 }
292
4cf1653a 293 lp = netdev_priv(dev);
1da177e4
LT
294 lp->card_name = "PCMCIA COM20020";
295 lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
296
dd2e5a15 297 SET_NETDEV_DEV(dev, &link->dev);
1da177e4
LT
298
299 i = com20020_found(dev, 0); /* calls register_netdev */
300
301 if (i != 0) {
dd0fab5b
DB
302 dev_printk(KERN_NOTICE, &link->dev,
303 "com20020_cs: com20020_found() failed\n");
1da177e4
LT
304 goto failed;
305 }
306
dd0fab5b 307 dev_dbg(&link->dev,KERN_INFO "%s: port %#3lx, irq %d\n",
1da177e4 308 dev->name, dev->base_addr, dev->irq);
15b99ac1 309 return 0;
1da177e4 310
1da177e4 311failed:
dd0fab5b 312 dev_dbg(&link->dev, "com20020_config failed...\n");
1da177e4 313 com20020_release(link);
15b99ac1 314 return -ENODEV;
1da177e4
LT
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
fba395ee 325static void com20020_release(struct pcmcia_device *link)
1da177e4 326{
dd0fab5b 327 dev_dbg(&link->dev, "com20020_release\n");
fba395ee 328 pcmcia_disable_device(link);
1da177e4
LT
329}
330
fba395ee 331static int com20020_suspend(struct pcmcia_device *link)
98e4c28b 332{
98e4c28b
DB
333 com20020_dev_t *info = link->priv;
334 struct net_device *dev = info->dev;
335
e2d40963 336 if (link->open)
8661bb5b 337 netif_device_detach(dev);
98e4c28b
DB
338
339 return 0;
340}
341
fba395ee 342static int com20020_resume(struct pcmcia_device *link)
98e4c28b 343{
98e4c28b
DB
344 com20020_dev_t *info = link->priv;
345 struct net_device *dev = info->dev;
346
e2d40963 347 if (link->open) {
8661bb5b 348 int ioaddr = dev->base_addr;
4cf1653a 349 struct arcnet_local *lp = netdev_priv(dev);
8661bb5b
DB
350 ARCRESET;
351 }
98e4c28b
DB
352
353 return 0;
354}
355
7fb22bb4 356static struct pcmcia_device_id com20020_ids[] = {
6bb1c39a
MS
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),
7fb22bb4
DB
361 PCMCIA_DEVICE_NULL
362};
363MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
1da177e4
LT
364
365static struct pcmcia_driver com20020_cs_driver = {
366 .owner = THIS_MODULE,
367 .drv = {
368 .name = "com20020_cs",
369 },
15b99ac1 370 .probe = com20020_probe,
cc3b4866 371 .remove = com20020_detach,
7fb22bb4 372 .id_table = com20020_ids,
98e4c28b
DB
373 .suspend = com20020_suspend,
374 .resume = com20020_resume,
1da177e4
LT
375};
376
377static int __init init_com20020_cs(void)
378{
379 return pcmcia_register_driver(&com20020_cs_driver);
380}
381
382static void __exit exit_com20020_cs(void)
383{
384 pcmcia_unregister_driver(&com20020_cs_driver);
1da177e4
LT
385}
386
387module_init(init_com20020_cs);
388module_exit(exit_com20020_cs);