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