]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/net/pcmcia/ibmtr_cs.c
Fix hang on IBM Token Ring PCMCIA card ejection
[linux-2.6-omap-h63xx.git] / drivers / net / pcmcia / ibmtr_cs.c
1 /*======================================================================
2
3     A PCMCIA token-ring driver for IBM-based cards
4
5     This driver supports the IBM PCMCIA Token-Ring Card.
6     Written by Steve Kipisz, kipisz@vnet.ibm.com or
7                              bungy@ibm.net
8
9     Written 1995,1996.
10
11     This code is based on pcnet_cs.c from David Hinds.
12     
13     V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com
14
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.
18
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.
23
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.
27
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.
31
32     CHANGES
33
34     v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com)
35     Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c
36     
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.
40     
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.)
45
46 ======================================================================*/
47
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>
59
60 #include <pcmcia/cs_types.h>
61 #include <pcmcia/cs.h>
62 #include <pcmcia/cistpl.h>
63 #include <pcmcia/ds.h>
64
65 #include <asm/uaccess.h>
66 #include <asm/io.h>
67 #include <asm/system.h>
68
69 #define PCMCIA
70 #include "../tokenring/ibmtr.c"
71
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
83
84 /*====================================================================*/
85
86 /* Parameters that can be set with 'insmod' */
87
88 /* MMIO base address */
89 static u_long mmiobase = 0xce000;
90
91 /* SRAM base address */
92 static u_long srambase = 0xd0000;
93
94 /* SRAM size 8,16,32,64 */
95 static u_long sramsize = 64;
96
97 /* Ringspeed 4,16 */
98 static int ringspeed = 16;
99
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");
105
106 /*====================================================================*/
107
108 static int ibmtr_config(struct pcmcia_device *link);
109 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
110 static void ibmtr_release(struct pcmcia_device *link);
111 static void ibmtr_detach(struct pcmcia_device *p_dev);
112
113 /*====================================================================*/
114
115 typedef struct ibmtr_dev_t {
116         struct pcmcia_device    *p_dev;
117     struct net_device   *dev;
118     dev_node_t          node;
119     window_handle_t     sram_win_handle;
120     struct tok_info     *ti;
121 } ibmtr_dev_t;
122
123 static void netdev_get_drvinfo(struct net_device *dev,
124                                struct ethtool_drvinfo *info)
125 {
126         strcpy(info->driver, "ibmtr_cs");
127 }
128
129 static const struct ethtool_ops netdev_ethtool_ops = {
130         .get_drvinfo            = netdev_get_drvinfo,
131 };
132
133 /*======================================================================
134
135     ibmtr_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
141 static int __devinit ibmtr_attach(struct pcmcia_device *link)
142 {
143     ibmtr_dev_t *info;
144     struct net_device *dev;
145
146     DEBUG(0, "ibmtr_attach()\n");
147
148     /* Create new token-ring device */
149     info = kmalloc(sizeof(*info), GFP_KERNEL); 
150     if (!info) return -ENOMEM;
151     memset(info,0,sizeof(*info));
152     dev = alloc_trdev(sizeof(struct tok_info));
153     if (!dev) {
154         kfree(info);
155         return -ENOMEM;
156     }
157
158     info->p_dev = link;
159     link->priv = info;
160     info->ti = netdev_priv(dev);
161
162     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
163     link->io.NumPorts1 = 4;
164     link->io.IOAddrLines = 16;
165     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
166     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
167     link->irq.Handler = &tok_interrupt;
168     link->conf.Attributes = CONF_ENABLE_IRQ;
169     link->conf.IntType = INT_MEMORY_AND_IO;
170     link->conf.Present = PRESENT_OPTION;
171
172     link->irq.Instance = info->dev = dev;
173
174     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
175
176     return ibmtr_config(link);
177 } /* ibmtr_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
188 static void ibmtr_detach(struct pcmcia_device *link)
189 {
190     struct ibmtr_dev_t *info = link->priv;
191     struct net_device *dev = info->dev;
192      struct tok_info *ti = netdev_priv(dev);
193
194     DEBUG(0, "ibmtr_detach(0x%p)\n", link);
195     
196     /* 
197      * When the card removal interrupt hits tok_interrupt(), 
198      * bail out early, so we don't crash the machine 
199      */
200     ti->sram_phys |= 1;
201
202     if (link->dev_node)
203         unregister_netdev(dev);
204     
205     del_timer_sync(&(ti->tr_timer));
206
207     ibmtr_release(link);
208
209     free_netdev(dev);
210     kfree(info);
211 } /* ibmtr_detach */
212
213 /*======================================================================
214
215     ibmtr_config() is scheduled to run after a CARD_INSERTION event
216     is received, to configure the PCMCIA socket, and to make the
217     token-ring device available to the system.
218
219 ======================================================================*/
220
221 #define CS_CHECK(fn, ret) \
222 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
223
224 static int __devinit ibmtr_config(struct pcmcia_device *link)
225 {
226     ibmtr_dev_t *info = link->priv;
227     struct net_device *dev = info->dev;
228     struct tok_info *ti = netdev_priv(dev);
229     win_req_t req;
230     memreq_t mem;
231     int i, last_ret, last_fn;
232
233     DEBUG(0, "ibmtr_config(0x%p)\n", link);
234
235     link->conf.ConfigIndex = 0x61;
236
237     /* Determine if this is PRIMARY or ALTERNATE. */
238
239     /* Try PRIMARY card at 0xA20-0xA23 */
240     link->io.BasePort1 = 0xA20;
241     i = pcmcia_request_io(link, &link->io);
242     if (i != CS_SUCCESS) {
243         /* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
244         link->io.BasePort1 = 0xA24;
245         CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
246     }
247     dev->base_addr = link->io.BasePort1;
248
249     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
250     dev->irq = link->irq.AssignedIRQ;
251     ti->irq = link->irq.AssignedIRQ;
252     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
253
254     /* Allocate the MMIO memory window */
255     req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
256     req.Attributes |= WIN_USE_WAIT;
257     req.Base = 0; 
258     req.Size = 0x2000;
259     req.AccessSpeed = 250;
260     CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
261
262     mem.CardOffset = mmiobase;
263     mem.Page = 0;
264     CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
265     ti->mmio = ioremap(req.Base, req.Size);
266
267     /* Allocate the SRAM memory window */
268     req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
269     req.Attributes |= WIN_USE_WAIT;
270     req.Base = 0;
271     req.Size = sramsize * 1024;
272     req.AccessSpeed = 250;
273     CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle));
274
275     mem.CardOffset = srambase;
276     mem.Page = 0;
277     CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem));
278
279     ti->sram_base = mem.CardOffset >> 12;
280     ti->sram_virt = ioremap(req.Base, req.Size);
281     ti->sram_phys = req.Base;
282
283     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
284
285     /*  Set up the Token-Ring Controller Configuration Register and
286         turn on the card.  Check the "Local Area Network Credit Card
287         Adapters Technical Reference"  SC30-3585 for this info.  */
288     ibmtr_hw_setup(dev, mmiobase);
289
290     link->dev_node = &info->node;
291     SET_NETDEV_DEV(dev, &handle_to_dev(link));
292
293     i = ibmtr_probe_card(dev);
294     if (i != 0) {
295         printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
296         link->dev_node = NULL;
297         goto failed;
298     }
299
300     strcpy(info->node.dev_name, dev->name);
301
302     printk(KERN_INFO "%s: port %#3lx, irq %d,",
303            dev->name, dev->base_addr, dev->irq);
304     printk (" mmio %#5lx,", (u_long)ti->mmio);
305     printk (" sram %#5lx,", (u_long)ti->sram_base << 12);
306     printk ("\n" KERN_INFO "  hwaddr=");
307     for (i = 0; i < TR_ALEN; i++)
308         printk("%02X", dev->dev_addr[i]);
309     printk("\n");
310     return 0;
311
312 cs_failed:
313     cs_error(link, last_fn, last_ret);
314 failed:
315     ibmtr_release(link);
316     return -ENODEV;
317 } /* ibmtr_config */
318
319 /*======================================================================
320
321     After a card is removed, ibmtr_release() will unregister the net
322     device, and release the PCMCIA configuration.  If the device is
323     still open, this will be postponed until it is closed.
324
325 ======================================================================*/
326
327 static void ibmtr_release(struct pcmcia_device *link)
328 {
329         ibmtr_dev_t *info = link->priv;
330         struct net_device *dev = info->dev;
331
332         DEBUG(0, "ibmtr_release(0x%p)\n", link);
333
334         if (link->win) {
335                 struct tok_info *ti = netdev_priv(dev);
336                 iounmap(ti->mmio);
337                 pcmcia_release_window(info->sram_win_handle);
338         }
339         pcmcia_disable_device(link);
340 }
341
342 static int ibmtr_suspend(struct pcmcia_device *link)
343 {
344         ibmtr_dev_t *info = link->priv;
345         struct net_device *dev = info->dev;
346
347         if (link->open)
348                 netif_device_detach(dev);
349
350         return 0;
351 }
352
353 static int ibmtr_resume(struct pcmcia_device *link)
354 {
355         ibmtr_dev_t *info = link->priv;
356         struct net_device *dev = info->dev;
357
358         if (link->open) {
359                 ibmtr_probe(dev);       /* really? */
360                 netif_device_attach(dev);
361         }
362
363         return 0;
364 }
365
366
367 /*====================================================================*/
368
369 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
370 {
371     int i;
372
373     /* Bizarre IBM behavior, there are 16 bits of information we
374        need to set, but the card only allows us to send 4 bits at a 
375        time.  For each byte sent to base_addr, bits 7-4 tell the
376        card which part of the 16 bits we are setting, bits 3-0 contain 
377        the actual information */
378
379     /* First nibble provides 4 bits of mmio */
380     i = (mmiobase >> 16) & 0x0F;
381     outb(i, dev->base_addr);
382
383     /* Second nibble provides 3 bits of mmio */
384     i = 0x10 | ((mmiobase >> 12) & 0x0E);
385     outb(i, dev->base_addr);
386
387     /* Third nibble, hard-coded values */
388     i = 0x26;
389     outb(i, dev->base_addr);
390
391     /* Fourth nibble sets shared ram page size */
392
393     /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */          
394     i = (sramsize >> 4) & 0x07;
395     i = ((i == 4) ? 3 : i) << 2;
396     i |= 0x30;
397
398     if (ringspeed == 16)
399         i |= 2;
400     if (dev->base_addr == 0xA24)
401         i |= 1;
402     outb(i, dev->base_addr);
403
404     /* 0x40 will release the card for use */
405     outb(0x40, dev->base_addr);
406
407     return;
408 }
409
410 static struct pcmcia_device_id ibmtr_ids[] = {
411         PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e),
412         PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47),
413         PCMCIA_DEVICE_NULL,
414 };
415 MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
416
417 static struct pcmcia_driver ibmtr_cs_driver = {
418         .owner          = THIS_MODULE,
419         .drv            = {
420                 .name   = "ibmtr_cs",
421         },
422         .probe          = ibmtr_attach,
423         .remove         = ibmtr_detach,
424         .id_table       = ibmtr_ids,
425         .suspend        = ibmtr_suspend,
426         .resume         = ibmtr_resume,
427 };
428
429 static int __init init_ibmtr_cs(void)
430 {
431         return pcmcia_register_driver(&ibmtr_cs_driver);
432 }
433
434 static void __exit exit_ibmtr_cs(void)
435 {
436         pcmcia_unregister_driver(&ibmtr_cs_driver);
437 }
438
439 module_init(init_ibmtr_cs);
440 module_exit(exit_ibmtr_cs);