[PATCH] pcmcia: unify detach, REMOVAL_EVENT handlers into one remove callback
[linux-2.6/kvm.git] / drivers / net / pcmcia / ibmtr_cs.c
blob961294983354ffb988741d8df63bcd5d6d633ce7
1 /*======================================================================
3 A PCMCIA token-ring driver for IBM-based cards
5 This driver supports the IBM PCMCIA Token-Ring Card.
6 Written by Steve Kipisz, kipisz@vnet.ibm.com or
7 bungy@ibm.net
9 Written 1995,1996.
11 This code is based on pcnet_cs.c from David Hinds.
13 V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com
15 Linux V2.2.x presented significant changes to the underlying
16 ibmtr.c code. Mainly the code became a lot more organized and
17 modular.
19 This caused the old PCMCIA Token Ring driver to give up and go
20 home early. Instead of just patching the old code to make it
21 work, the PCMCIA code has been streamlined, updated and possibly
22 improved.
24 This code now only contains code required for the Card Services.
25 All we do here is set the card up enough so that the real ibmtr.c
26 driver can find it and work with it properly.
28 i.e. We set up the io port, irq, mmio memory and shared ram
29 memory. This enables ibmtr_probe in ibmtr.c to find the card and
30 configure it as though it was a normal ISA and/or PnP card.
32 CHANGES
34 v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com)
35 Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c
37 v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com)
38 Updated to version 2.2.7 to match the first version of the kernel
39 that the modification to ibmtr.c were incorporated into.
41 v2.2.17 July 2000 Burt Silverman (burts@us.ibm.com)
42 Address translation feature of PCMCIA controller is usable so
43 memory windows can be placed in High memory (meaning above
44 0xFFFFF.)
46 ======================================================================*/
48 #include <linux/kernel.h>
49 #include <linux/init.h>
50 #include <linux/ptrace.h>
51 #include <linux/slab.h>
52 #include <linux/string.h>
53 #include <linux/timer.h>
54 #include <linux/module.h>
55 #include <linux/ethtool.h>
56 #include <linux/netdevice.h>
57 #include <linux/trdevice.h>
58 #include <linux/ibmtr.h>
60 #include <pcmcia/cs_types.h>
61 #include <pcmcia/cs.h>
62 #include <pcmcia/cistpl.h>
63 #include <pcmcia/ds.h>
65 #include <asm/uaccess.h>
66 #include <asm/io.h>
67 #include <asm/system.h>
69 #define PCMCIA
70 #include "../tokenring/ibmtr.c"
72 #ifdef PCMCIA_DEBUG
73 static int pc_debug = PCMCIA_DEBUG;
74 module_param(pc_debug, int, 0);
75 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
76 static char *version =
77 "ibmtr_cs.c 1.10 1996/01/06 05:19:00 (Steve Kipisz)\n"
78 " 2.2.7 1999/05/03 12:00:00 (Mike Phillips)\n"
79 " 2.4.2 2001/30/28 Midnight (Burt Silverman)\n";
80 #else
81 #define DEBUG(n, args...)
82 #endif
84 /*====================================================================*/
86 /* Parameters that can be set with 'insmod' */
88 /* MMIO base address */
89 static u_long mmiobase = 0xce000;
91 /* SRAM base address */
92 static u_long srambase = 0xd0000;
94 /* SRAM size 8,16,32,64 */
95 static u_long sramsize = 64;
97 /* Ringspeed 4,16 */
98 static int ringspeed = 16;
100 module_param(mmiobase, ulong, 0);
101 module_param(srambase, ulong, 0);
102 module_param(sramsize, ulong, 0);
103 module_param(ringspeed, int, 0);
104 MODULE_LICENSE("GPL");
106 /*====================================================================*/
108 static void ibmtr_config(dev_link_t *link);
109 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
110 static void ibmtr_release(dev_link_t *link);
111 static int ibmtr_event(event_t event, int priority,
112 event_callback_args_t *args);
114 static dev_info_t dev_info = "ibmtr_cs";
116 static dev_link_t *ibmtr_attach(void);
117 static void ibmtr_detach(struct pcmcia_device *p_dev);
119 static dev_link_t *dev_list;
121 /*====================================================================*/
123 typedef struct ibmtr_dev_t {
124 dev_link_t link;
125 struct net_device *dev;
126 dev_node_t node;
127 window_handle_t sram_win_handle;
128 struct tok_info *ti;
129 } ibmtr_dev_t;
131 static void netdev_get_drvinfo(struct net_device *dev,
132 struct ethtool_drvinfo *info)
134 strcpy(info->driver, "ibmtr_cs");
137 static struct ethtool_ops netdev_ethtool_ops = {
138 .get_drvinfo = netdev_get_drvinfo,
141 /*======================================================================
143 ibmtr_attach() creates an "instance" of the driver, allocating
144 local data structures for one device. The device is registered
145 with Card Services.
147 ======================================================================*/
149 static dev_link_t *ibmtr_attach(void)
151 ibmtr_dev_t *info;
152 dev_link_t *link;
153 struct net_device *dev;
154 client_reg_t client_reg;
155 int ret;
157 DEBUG(0, "ibmtr_attach()\n");
159 /* Create new token-ring device */
160 info = kmalloc(sizeof(*info), GFP_KERNEL);
161 if (!info) return NULL;
162 memset(info,0,sizeof(*info));
163 dev = alloc_trdev(sizeof(struct tok_info));
164 if (!dev) {
165 kfree(info);
166 return NULL;
169 link = &info->link;
170 link->priv = info;
171 info->ti = netdev_priv(dev);
173 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
174 link->io.NumPorts1 = 4;
175 link->io.IOAddrLines = 16;
176 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
177 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
178 link->irq.Handler = &tok_interrupt;
179 link->conf.Attributes = CONF_ENABLE_IRQ;
180 link->conf.Vcc = 50;
181 link->conf.IntType = INT_MEMORY_AND_IO;
182 link->conf.Present = PRESENT_OPTION;
184 link->irq.Instance = info->dev = dev;
186 SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
188 /* Register with Card Services */
189 link->next = dev_list;
190 dev_list = link;
191 client_reg.dev_info = &dev_info;
192 client_reg.Version = 0x0210;
193 client_reg.event_callback_args.client_data = link;
194 ret = pcmcia_register_client(&link->handle, &client_reg);
195 if (ret != 0) {
196 cs_error(link->handle, RegisterClient, ret);
197 goto out_detach;
200 out:
201 return link;
203 out_detach:
204 ibmtr_detach(link->handle);
205 link = NULL;
206 goto out;
207 } /* ibmtr_attach */
209 /*======================================================================
211 This deletes a driver "instance". The device is de-registered
212 with Card Services. If it has been released, all local data
213 structures are freed. Otherwise, the structures will be freed
214 when the device is released.
216 ======================================================================*/
218 static void ibmtr_detach(struct pcmcia_device *p_dev)
220 dev_link_t *link = dev_to_instance(p_dev);
221 struct ibmtr_dev_t *info = link->priv;
222 dev_link_t **linkp;
223 struct net_device *dev;
225 DEBUG(0, "ibmtr_detach(0x%p)\n", link);
227 /* Locate device structure */
228 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
229 if (*linkp == link) break;
230 if (*linkp == NULL)
231 return;
233 dev = info->dev;
235 if (link->dev)
236 unregister_netdev(dev);
239 struct tok_info *ti = netdev_priv(dev);
240 del_timer_sync(&(ti->tr_timer));
242 if (link->state & DEV_CONFIG)
243 ibmtr_release(link);
245 /* Unlink device structure, free bits */
246 *linkp = link->next;
247 free_netdev(dev);
248 kfree(info);
249 } /* ibmtr_detach */
251 /*======================================================================
253 ibmtr_config() is scheduled to run after a CARD_INSERTION event
254 is received, to configure the PCMCIA socket, and to make the
255 token-ring device available to the system.
257 ======================================================================*/
259 #define CS_CHECK(fn, ret) \
260 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
262 static void ibmtr_config(dev_link_t *link)
264 client_handle_t handle = link->handle;
265 ibmtr_dev_t *info = link->priv;
266 struct net_device *dev = info->dev;
267 struct tok_info *ti = netdev_priv(dev);
268 tuple_t tuple;
269 cisparse_t parse;
270 win_req_t req;
271 memreq_t mem;
272 int i, last_ret, last_fn;
273 u_char buf[64];
275 DEBUG(0, "ibmtr_config(0x%p)\n", link);
277 tuple.Attributes = 0;
278 tuple.TupleData = buf;
279 tuple.TupleDataMax = 64;
280 tuple.TupleOffset = 0;
281 tuple.DesiredTuple = CISTPL_CONFIG;
282 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
283 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
284 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
285 link->conf.ConfigBase = parse.config.base;
287 /* Configure card */
288 link->state |= DEV_CONFIG;
290 link->conf.ConfigIndex = 0x61;
292 /* Determine if this is PRIMARY or ALTERNATE. */
294 /* Try PRIMARY card at 0xA20-0xA23 */
295 link->io.BasePort1 = 0xA20;
296 i = pcmcia_request_io(link->handle, &link->io);
297 if (i != CS_SUCCESS) {
298 /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */
299 link->io.BasePort1 = 0xA24;
300 CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
302 dev->base_addr = link->io.BasePort1;
304 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
305 dev->irq = link->irq.AssignedIRQ;
306 ti->irq = link->irq.AssignedIRQ;
307 ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
309 /* Allocate the MMIO memory window */
310 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
311 req.Attributes |= WIN_USE_WAIT;
312 req.Base = 0;
313 req.Size = 0x2000;
314 req.AccessSpeed = 250;
315 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
317 mem.CardOffset = mmiobase;
318 mem.Page = 0;
319 CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
320 ti->mmio = ioremap(req.Base, req.Size);
322 /* Allocate the SRAM memory window */
323 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
324 req.Attributes |= WIN_USE_WAIT;
325 req.Base = 0;
326 req.Size = sramsize * 1024;
327 req.AccessSpeed = 250;
328 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle));
330 mem.CardOffset = srambase;
331 mem.Page = 0;
332 CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem));
334 ti->sram_base = mem.CardOffset >> 12;
335 ti->sram_virt = ioremap(req.Base, req.Size);
336 ti->sram_phys = req.Base;
338 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
340 /* Set up the Token-Ring Controller Configuration Register and
341 turn on the card. Check the "Local Area Network Credit Card
342 Adapters Technical Reference" SC30-3585 for this info. */
343 ibmtr_hw_setup(dev, mmiobase);
345 link->dev = &info->node;
346 link->state &= ~DEV_CONFIG_PENDING;
347 SET_NETDEV_DEV(dev, &handle_to_dev(handle));
349 i = ibmtr_probe_card(dev);
350 if (i != 0) {
351 printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
352 link->dev = NULL;
353 goto failed;
356 strcpy(info->node.dev_name, dev->name);
358 printk(KERN_INFO "%s: port %#3lx, irq %d,",
359 dev->name, dev->base_addr, dev->irq);
360 printk (" mmio %#5lx,", (u_long)ti->mmio);
361 printk (" sram %#5lx,", (u_long)ti->sram_base << 12);
362 printk ("\n" KERN_INFO " hwaddr=");
363 for (i = 0; i < TR_ALEN; i++)
364 printk("%02X", dev->dev_addr[i]);
365 printk("\n");
366 return;
368 cs_failed:
369 cs_error(link->handle, last_fn, last_ret);
370 failed:
371 ibmtr_release(link);
372 } /* ibmtr_config */
374 /*======================================================================
376 After a card is removed, ibmtr_release() will unregister the net
377 device, and release the PCMCIA configuration. If the device is
378 still open, this will be postponed until it is closed.
380 ======================================================================*/
382 static void ibmtr_release(dev_link_t *link)
384 ibmtr_dev_t *info = link->priv;
385 struct net_device *dev = info->dev;
387 DEBUG(0, "ibmtr_release(0x%p)\n", link);
389 pcmcia_release_configuration(link->handle);
390 pcmcia_release_io(link->handle, &link->io);
391 pcmcia_release_irq(link->handle, &link->irq);
392 if (link->win) {
393 struct tok_info *ti = netdev_priv(dev);
394 iounmap(ti->mmio);
395 pcmcia_release_window(link->win);
396 pcmcia_release_window(info->sram_win_handle);
399 link->state &= ~DEV_CONFIG;
402 static int ibmtr_suspend(struct pcmcia_device *p_dev)
404 dev_link_t *link = dev_to_instance(p_dev);
405 ibmtr_dev_t *info = link->priv;
406 struct net_device *dev = info->dev;
408 link->state |= DEV_SUSPEND;
409 if (link->state & DEV_CONFIG) {
410 if (link->open)
411 netif_device_detach(dev);
412 pcmcia_release_configuration(link->handle);
415 return 0;
418 static int ibmtr_resume(struct pcmcia_device *p_dev)
420 dev_link_t *link = dev_to_instance(p_dev);
421 ibmtr_dev_t *info = link->priv;
422 struct net_device *dev = info->dev;
424 link->state &= ~DEV_SUSPEND;
425 if (link->state & DEV_CONFIG) {
426 pcmcia_request_configuration(link->handle, &link->conf);
427 if (link->open) {
428 ibmtr_probe(dev); /* really? */
429 netif_device_attach(dev);
433 return 0;
437 /*======================================================================
439 The card status event handler. Mostly, this schedules other
440 stuff to run after an event is received. A CARD_REMOVAL event
441 also sets some flags to discourage the net drivers from trying
442 to talk to the card any more.
444 ======================================================================*/
446 static int ibmtr_event(event_t event, int priority,
447 event_callback_args_t *args)
449 dev_link_t *link = args->client_data;
451 DEBUG(1, "ibmtr_event(0x%06x)\n", event);
453 switch (event) {
454 case CS_EVENT_CARD_INSERTION:
455 link->state |= DEV_PRESENT;
456 ibmtr_config(link);
457 break;
459 return 0;
460 } /* ibmtr_event */
462 /*====================================================================*/
464 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
466 int i;
468 /* Bizarre IBM behavior, there are 16 bits of information we
469 need to set, but the card only allows us to send 4 bits at a
470 time. For each byte sent to base_addr, bits 7-4 tell the
471 card which part of the 16 bits we are setting, bits 3-0 contain
472 the actual information */
474 /* First nibble provides 4 bits of mmio */
475 i = (mmiobase >> 16) & 0x0F;
476 outb(i, dev->base_addr);
478 /* Second nibble provides 3 bits of mmio */
479 i = 0x10 | ((mmiobase >> 12) & 0x0E);
480 outb(i, dev->base_addr);
482 /* Third nibble, hard-coded values */
483 i = 0x26;
484 outb(i, dev->base_addr);
486 /* Fourth nibble sets shared ram page size */
488 /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */
489 i = (sramsize >> 4) & 0x07;
490 i = ((i == 4) ? 3 : i) << 2;
491 i |= 0x30;
493 if (ringspeed == 16)
494 i |= 2;
495 if (dev->base_addr == 0xA24)
496 i |= 1;
497 outb(i, dev->base_addr);
499 /* 0x40 will release the card for use */
500 outb(0x40, dev->base_addr);
502 return;
505 static struct pcmcia_device_id ibmtr_ids[] = {
506 PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e),
507 PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47),
508 PCMCIA_DEVICE_NULL,
510 MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
512 static struct pcmcia_driver ibmtr_cs_driver = {
513 .owner = THIS_MODULE,
514 .drv = {
515 .name = "ibmtr_cs",
517 .attach = ibmtr_attach,
518 .event = ibmtr_event,
519 .remove = ibmtr_detach,
520 .id_table = ibmtr_ids,
521 .suspend = ibmtr_suspend,
522 .resume = ibmtr_resume,
525 static int __init init_ibmtr_cs(void)
527 return pcmcia_register_driver(&ibmtr_cs_driver);
530 static void __exit exit_ibmtr_cs(void)
532 pcmcia_unregister_driver(&ibmtr_cs_driver);
533 BUG_ON(dev_list != NULL);
536 module_init(init_ibmtr_cs);
537 module_exit(exit_ibmtr_cs);