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