pcmcia: Pass struct pcmcia_device to pcmcia_release_window()
[linux-2.6.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
73 /*====================================================================*/
74
75 /* Parameters that can be set with 'insmod' */
76
77 /* MMIO base address */
78 static u_long mmiobase = 0xce000;
79
80 /* SRAM base address */
81 static u_long srambase = 0xd0000;
82
83 /* SRAM size 8,16,32,64 */
84 static u_long sramsize = 64;
85
86 /* Ringspeed 4,16 */
87 static int ringspeed = 16;
88
89 module_param(mmiobase, ulong, 0);
90 module_param(srambase, ulong, 0);
91 module_param(sramsize, ulong, 0);
92 module_param(ringspeed, int, 0);
93 MODULE_LICENSE("GPL");
94
95 /*====================================================================*/
96
97 static int ibmtr_config(struct pcmcia_device *link);
98 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
99 static void ibmtr_release(struct pcmcia_device *link);
100 static void ibmtr_detach(struct pcmcia_device *p_dev);
101
102 /*====================================================================*/
103
104 typedef struct ibmtr_dev_t {
105         struct pcmcia_device    *p_dev;
106     struct net_device   *dev;
107     dev_node_t          node;
108     window_handle_t     sram_win_handle;
109     struct tok_info     *ti;
110 } ibmtr_dev_t;
111
112 static void netdev_get_drvinfo(struct net_device *dev,
113                                struct ethtool_drvinfo *info)
114 {
115         strcpy(info->driver, "ibmtr_cs");
116 }
117
118 static const struct ethtool_ops netdev_ethtool_ops = {
119         .get_drvinfo            = netdev_get_drvinfo,
120 };
121
122 /*======================================================================
123
124     ibmtr_attach() creates an "instance" of the driver, allocating
125     local data structures for one device.  The device is registered
126     with Card Services.
127
128 ======================================================================*/
129
130 static int __devinit ibmtr_attach(struct pcmcia_device *link)
131 {
132     ibmtr_dev_t *info;
133     struct net_device *dev;
134
135     dev_dbg(&link->dev, "ibmtr_attach()\n");
136
137     /* Create new token-ring device */
138     info = kzalloc(sizeof(*info), GFP_KERNEL);
139     if (!info) return -ENOMEM;
140     dev = alloc_trdev(sizeof(struct tok_info));
141     if (!dev) {
142         kfree(info);
143         return -ENOMEM;
144     }
145
146     info->p_dev = link;
147     link->priv = info;
148     info->ti = netdev_priv(dev);
149
150     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
151     link->io.NumPorts1 = 4;
152     link->io.IOAddrLines = 16;
153     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
154     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
155     link->irq.Handler = &tok_interrupt;
156     link->conf.Attributes = CONF_ENABLE_IRQ;
157     link->conf.IntType = INT_MEMORY_AND_IO;
158     link->conf.Present = PRESENT_OPTION;
159
160     link->irq.Instance = info->dev = dev;
161
162     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
163
164     return ibmtr_config(link);
165 } /* ibmtr_attach */
166
167 /*======================================================================
168
169     This deletes a driver "instance".  The device is de-registered
170     with Card Services.  If it has been released, all local data
171     structures are freed.  Otherwise, the structures will be freed
172     when the device is released.
173
174 ======================================================================*/
175
176 static void ibmtr_detach(struct pcmcia_device *link)
177 {
178     struct ibmtr_dev_t *info = link->priv;
179     struct net_device *dev = info->dev;
180      struct tok_info *ti = netdev_priv(dev);
181
182     dev_dbg(&link->dev, "ibmtr_detach\n");
183     
184     /* 
185      * When the card removal interrupt hits tok_interrupt(), 
186      * bail out early, so we don't crash the machine 
187      */
188     ti->sram_phys |= 1;
189
190     if (link->dev_node)
191         unregister_netdev(dev);
192     
193     del_timer_sync(&(ti->tr_timer));
194
195     ibmtr_release(link);
196
197     free_netdev(dev);
198     kfree(info);
199 } /* ibmtr_detach */
200
201 /*======================================================================
202
203     ibmtr_config() is scheduled to run after a CARD_INSERTION event
204     is received, to configure the PCMCIA socket, and to make the
205     token-ring device available to the system.
206
207 ======================================================================*/
208
209 static int __devinit ibmtr_config(struct pcmcia_device *link)
210 {
211     ibmtr_dev_t *info = link->priv;
212     struct net_device *dev = info->dev;
213     struct tok_info *ti = netdev_priv(dev);
214     win_req_t req;
215     memreq_t mem;
216     int i, ret;
217
218     dev_dbg(&link->dev, "ibmtr_config\n");
219
220     link->conf.ConfigIndex = 0x61;
221
222     /* Determine if this is PRIMARY or ALTERNATE. */
223
224     /* Try PRIMARY card at 0xA20-0xA23 */
225     link->io.BasePort1 = 0xA20;
226     i = pcmcia_request_io(link, &link->io);
227     if (i != 0) {
228         /* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
229         link->io.BasePort1 = 0xA24;
230         ret = pcmcia_request_io(link, &link->io);
231         if (ret)
232                 goto failed;
233     }
234     dev->base_addr = link->io.BasePort1;
235
236     ret = pcmcia_request_irq(link, &link->irq);
237     if (ret)
238             goto failed;
239     dev->irq = link->irq.AssignedIRQ;
240     ti->irq = link->irq.AssignedIRQ;
241     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
242
243     /* Allocate the MMIO memory window */
244     req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
245     req.Attributes |= WIN_USE_WAIT;
246     req.Base = 0; 
247     req.Size = 0x2000;
248     req.AccessSpeed = 250;
249     ret = pcmcia_request_window(&link, &req, &link->win);
250     if (ret)
251             goto failed;
252
253     mem.CardOffset = mmiobase;
254     mem.Page = 0;
255     ret = pcmcia_map_mem_page(link->win, &mem);
256     if (ret)
257             goto failed;
258     ti->mmio = ioremap(req.Base, req.Size);
259
260     /* Allocate the SRAM memory window */
261     req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
262     req.Attributes |= WIN_USE_WAIT;
263     req.Base = 0;
264     req.Size = sramsize * 1024;
265     req.AccessSpeed = 250;
266     ret = pcmcia_request_window(&link, &req, &info->sram_win_handle);
267     if (ret)
268             goto failed;
269
270     mem.CardOffset = srambase;
271     mem.Page = 0;
272     ret = pcmcia_map_mem_page(info->sram_win_handle, &mem);
273     if (ret)
274             goto failed;
275
276     ti->sram_base = mem.CardOffset >> 12;
277     ti->sram_virt = ioremap(req.Base, req.Size);
278     ti->sram_phys = req.Base;
279
280     ret = pcmcia_request_configuration(link, &link->conf);
281     if (ret)
282             goto failed;
283
284     /*  Set up the Token-Ring Controller Configuration Register and
285         turn on the card.  Check the "Local Area Network Credit Card
286         Adapters Technical Reference"  SC30-3585 for this info.  */
287     ibmtr_hw_setup(dev, mmiobase);
288
289     link->dev_node = &info->node;
290     SET_NETDEV_DEV(dev, &handle_to_dev(link));
291
292     i = ibmtr_probe_card(dev);
293     if (i != 0) {
294         printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
295         link->dev_node = NULL;
296         goto failed;
297     }
298
299     strcpy(info->node.dev_name, dev->name);
300
301     printk(KERN_INFO
302            "%s: port %#3lx, irq %d,  mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
303            dev->name, dev->base_addr, dev->irq,
304            (u_long)ti->mmio, (u_long)(ti->sram_base << 12),
305            dev->dev_addr);
306     return 0;
307
308 failed:
309     ibmtr_release(link);
310     return -ENODEV;
311 } /* ibmtr_config */
312
313 /*======================================================================
314
315     After a card is removed, ibmtr_release() will unregister the net
316     device, and release the PCMCIA configuration.  If the device is
317     still open, this will be postponed until it is closed.
318
319 ======================================================================*/
320
321 static void ibmtr_release(struct pcmcia_device *link)
322 {
323         ibmtr_dev_t *info = link->priv;
324         struct net_device *dev = info->dev;
325
326         dev_dbg(&link->dev, "ibmtr_release\n");
327
328         if (link->win) {
329                 struct tok_info *ti = netdev_priv(dev);
330                 iounmap(ti->mmio);
331                 pcmcia_release_window(link, info->sram_win_handle);
332         }
333         pcmcia_disable_device(link);
334 }
335
336 static int ibmtr_suspend(struct pcmcia_device *link)
337 {
338         ibmtr_dev_t *info = link->priv;
339         struct net_device *dev = info->dev;
340
341         if (link->open)
342                 netif_device_detach(dev);
343
344         return 0;
345 }
346
347 static int __devinit ibmtr_resume(struct pcmcia_device *link)
348 {
349         ibmtr_dev_t *info = link->priv;
350         struct net_device *dev = info->dev;
351
352         if (link->open) {
353                 ibmtr_probe(dev);       /* really? */
354                 netif_device_attach(dev);
355         }
356
357         return 0;
358 }
359
360
361 /*====================================================================*/
362
363 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
364 {
365     int i;
366
367     /* Bizarre IBM behavior, there are 16 bits of information we
368        need to set, but the card only allows us to send 4 bits at a 
369        time.  For each byte sent to base_addr, bits 7-4 tell the
370        card which part of the 16 bits we are setting, bits 3-0 contain 
371        the actual information */
372
373     /* First nibble provides 4 bits of mmio */
374     i = (mmiobase >> 16) & 0x0F;
375     outb(i, dev->base_addr);
376
377     /* Second nibble provides 3 bits of mmio */
378     i = 0x10 | ((mmiobase >> 12) & 0x0E);
379     outb(i, dev->base_addr);
380
381     /* Third nibble, hard-coded values */
382     i = 0x26;
383     outb(i, dev->base_addr);
384
385     /* Fourth nibble sets shared ram page size */
386
387     /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */          
388     i = (sramsize >> 4) & 0x07;
389     i = ((i == 4) ? 3 : i) << 2;
390     i |= 0x30;
391
392     if (ringspeed == 16)
393         i |= 2;
394     if (dev->base_addr == 0xA24)
395         i |= 1;
396     outb(i, dev->base_addr);
397
398     /* 0x40 will release the card for use */
399     outb(0x40, dev->base_addr);
400
401     return;
402 }
403
404 static struct pcmcia_device_id ibmtr_ids[] = {
405         PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e),
406         PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47),
407         PCMCIA_DEVICE_NULL,
408 };
409 MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
410
411 static struct pcmcia_driver ibmtr_cs_driver = {
412         .owner          = THIS_MODULE,
413         .drv            = {
414                 .name   = "ibmtr_cs",
415         },
416         .probe          = ibmtr_attach,
417         .remove         = ibmtr_detach,
418         .id_table       = ibmtr_ids,
419         .suspend        = ibmtr_suspend,
420         .resume         = ibmtr_resume,
421 };
422
423 static int __init init_ibmtr_cs(void)
424 {
425         return pcmcia_register_driver(&ibmtr_cs_driver);
426 }
427
428 static void __exit exit_ibmtr_cs(void)
429 {
430         pcmcia_unregister_driver(&ibmtr_cs_driver);
431 }
432
433 module_init(init_ibmtr_cs);
434 module_exit(exit_ibmtr_cs);