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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
49 
50 #include <linux/kernel.h>
51 #include <linux/init.h>
52 #include <linux/ptrace.h>
53 #include <linux/slab.h>
54 #include <linux/string.h>
55 #include <linux/timer.h>
56 #include <linux/module.h>
57 #include <linux/netdevice.h>
58 #include <linux/trdevice.h>
59 #include <linux/ibmtr.h>
60 
61 #include <pcmcia/cistpl.h>
62 #include <pcmcia/ds.h>
63 
64 #include <asm/uaccess.h>
65 #include <asm/io.h>
66 #include <asm/system.h>
67 
68 #define PCMCIA
69 #include "../tokenring/ibmtr.c"
70 
71 
72 /*====================================================================*/
73 
74 /* Parameters that can be set with 'insmod' */
75 
76 /* MMIO base address */
77 static u_long mmiobase = 0xce000;
78 
79 /* SRAM base address */
80 static u_long srambase = 0xd0000;
81 
82 /* SRAM size 8,16,32,64 */
83 static u_long sramsize = 64;
84 
85 /* Ringspeed 4,16 */
86 static int ringspeed = 16;
87 
88 module_param(mmiobase, ulong, 0);
89 module_param(srambase, ulong, 0);
90 module_param(sramsize, ulong, 0);
91 module_param(ringspeed, int, 0);
92 MODULE_LICENSE("GPL");
93 
94 /*====================================================================*/
95 
96 static int ibmtr_config(struct pcmcia_device *link);
97 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
98 static void ibmtr_release(struct pcmcia_device *link);
99 static void ibmtr_detach(struct pcmcia_device *p_dev);
100 
101 /*====================================================================*/
102 
103 typedef struct ibmtr_dev_t {
104 	struct pcmcia_device	*p_dev;
105 	struct net_device	*dev;
106 	struct tok_info		*ti;
107 } ibmtr_dev_t;
108 
ibmtr_interrupt(int irq,void * dev_id)109 static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) {
110 	ibmtr_dev_t *info = dev_id;
111 	struct net_device *dev = info->dev;
112 	return tok_interrupt(irq, dev);
113 };
114 
ibmtr_attach(struct pcmcia_device * link)115 static int __devinit ibmtr_attach(struct pcmcia_device *link)
116 {
117     ibmtr_dev_t *info;
118     struct net_device *dev;
119 
120     dev_dbg(&link->dev, "ibmtr_attach()\n");
121 
122     /* Create new token-ring device */
123     info = kzalloc(sizeof(*info), GFP_KERNEL);
124     if (!info) return -ENOMEM;
125     dev = alloc_trdev(sizeof(struct tok_info));
126     if (!dev) {
127 	kfree(info);
128 	return -ENOMEM;
129     }
130 
131     info->p_dev = link;
132     link->priv = info;
133     info->ti = netdev_priv(dev);
134 
135     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
136     link->resource[0]->end = 4;
137     link->config_flags |= CONF_ENABLE_IRQ;
138     link->config_regs = PRESENT_OPTION;
139 
140     info->dev = dev;
141 
142     return ibmtr_config(link);
143 } /* ibmtr_attach */
144 
ibmtr_detach(struct pcmcia_device * link)145 static void ibmtr_detach(struct pcmcia_device *link)
146 {
147     struct ibmtr_dev_t *info = link->priv;
148     struct net_device *dev = info->dev;
149      struct tok_info *ti = netdev_priv(dev);
150 
151     dev_dbg(&link->dev, "ibmtr_detach\n");
152 
153     /*
154      * When the card removal interrupt hits tok_interrupt(),
155      * bail out early, so we don't crash the machine
156      */
157     ti->sram_phys |= 1;
158 
159     unregister_netdev(dev);
160 
161     del_timer_sync(&(ti->tr_timer));
162 
163     ibmtr_release(link);
164 
165     free_netdev(dev);
166     kfree(info);
167 } /* ibmtr_detach */
168 
ibmtr_config(struct pcmcia_device * link)169 static int __devinit ibmtr_config(struct pcmcia_device *link)
170 {
171     ibmtr_dev_t *info = link->priv;
172     struct net_device *dev = info->dev;
173     struct tok_info *ti = netdev_priv(dev);
174     int i, ret;
175 
176     dev_dbg(&link->dev, "ibmtr_config\n");
177 
178     link->io_lines = 16;
179     link->config_index = 0x61;
180 
181     /* Determine if this is PRIMARY or ALTERNATE. */
182 
183     /* Try PRIMARY card at 0xA20-0xA23 */
184     link->resource[0]->start = 0xA20;
185     i = pcmcia_request_io(link);
186     if (i != 0) {
187 	/* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
188 	link->resource[0]->start = 0xA24;
189 	ret = pcmcia_request_io(link);
190 	if (ret)
191 		goto failed;
192     }
193     dev->base_addr = link->resource[0]->start;
194 
195     ret = pcmcia_request_exclusive_irq(link, ibmtr_interrupt);
196     if (ret)
197 	    goto failed;
198     dev->irq = link->irq;
199     ti->irq = link->irq;
200     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
201 
202     /* Allocate the MMIO memory window */
203     link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
204     link->resource[2]->flags |= WIN_USE_WAIT;
205     link->resource[2]->start = 0;
206     link->resource[2]->end = 0x2000;
207     ret = pcmcia_request_window(link, link->resource[2], 250);
208     if (ret)
209 	    goto failed;
210 
211     ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase);
212     if (ret)
213 	    goto failed;
214     ti->mmio = ioremap(link->resource[2]->start,
215 		    resource_size(link->resource[2]));
216 
217     /* Allocate the SRAM memory window */
218     link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
219     link->resource[3]->flags |= WIN_USE_WAIT;
220     link->resource[3]->start = 0;
221     link->resource[3]->end = sramsize * 1024;
222     ret = pcmcia_request_window(link, link->resource[3], 250);
223     if (ret)
224 	    goto failed;
225 
226     ret = pcmcia_map_mem_page(link, link->resource[3], srambase);
227     if (ret)
228 	    goto failed;
229 
230     ti->sram_base = srambase >> 12;
231     ti->sram_virt = ioremap(link->resource[3]->start,
232 		    resource_size(link->resource[3]));
233     ti->sram_phys = link->resource[3]->start;
234 
235     ret = pcmcia_enable_device(link);
236     if (ret)
237 	    goto failed;
238 
239     /*  Set up the Token-Ring Controller Configuration Register and
240         turn on the card.  Check the "Local Area Network Credit Card
241         Adapters Technical Reference"  SC30-3585 for this info.  */
242     ibmtr_hw_setup(dev, mmiobase);
243 
244     SET_NETDEV_DEV(dev, &link->dev);
245 
246     i = ibmtr_probe_card(dev);
247     if (i != 0) {
248 	pr_notice("register_netdev() failed\n");
249 	goto failed;
250     }
251 
252     netdev_info(dev, "port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
253 		dev->base_addr, dev->irq,
254 		(u_long)ti->mmio, (u_long)(ti->sram_base << 12),
255 		dev->dev_addr);
256     return 0;
257 
258 failed:
259     ibmtr_release(link);
260     return -ENODEV;
261 } /* ibmtr_config */
262 
ibmtr_release(struct pcmcia_device * link)263 static void ibmtr_release(struct pcmcia_device *link)
264 {
265 	ibmtr_dev_t *info = link->priv;
266 	struct net_device *dev = info->dev;
267 
268 	dev_dbg(&link->dev, "ibmtr_release\n");
269 
270 	if (link->resource[2]->end) {
271 		struct tok_info *ti = netdev_priv(dev);
272 		iounmap(ti->mmio);
273 	}
274 	pcmcia_disable_device(link);
275 }
276 
ibmtr_suspend(struct pcmcia_device * link)277 static int ibmtr_suspend(struct pcmcia_device *link)
278 {
279 	ibmtr_dev_t *info = link->priv;
280 	struct net_device *dev = info->dev;
281 
282 	if (link->open)
283 		netif_device_detach(dev);
284 
285 	return 0;
286 }
287 
ibmtr_resume(struct pcmcia_device * link)288 static int __devinit ibmtr_resume(struct pcmcia_device *link)
289 {
290 	ibmtr_dev_t *info = link->priv;
291 	struct net_device *dev = info->dev;
292 
293 	if (link->open) {
294 		ibmtr_probe(dev);	/* really? */
295 		netif_device_attach(dev);
296 	}
297 
298 	return 0;
299 }
300 
301 
302 /*====================================================================*/
303 
ibmtr_hw_setup(struct net_device * dev,u_int mmiobase)304 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
305 {
306     int i;
307 
308     /* Bizarre IBM behavior, there are 16 bits of information we
309        need to set, but the card only allows us to send 4 bits at a
310        time.  For each byte sent to base_addr, bits 7-4 tell the
311        card which part of the 16 bits we are setting, bits 3-0 contain
312        the actual information */
313 
314     /* First nibble provides 4 bits of mmio */
315     i = (mmiobase >> 16) & 0x0F;
316     outb(i, dev->base_addr);
317 
318     /* Second nibble provides 3 bits of mmio */
319     i = 0x10 | ((mmiobase >> 12) & 0x0E);
320     outb(i, dev->base_addr);
321 
322     /* Third nibble, hard-coded values */
323     i = 0x26;
324     outb(i, dev->base_addr);
325 
326     /* Fourth nibble sets shared ram page size */
327 
328     /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */
329     i = (sramsize >> 4) & 0x07;
330     i = ((i == 4) ? 3 : i) << 2;
331     i |= 0x30;
332 
333     if (ringspeed == 16)
334 	i |= 2;
335     if (dev->base_addr == 0xA24)
336 	i |= 1;
337     outb(i, dev->base_addr);
338 
339     /* 0x40 will release the card for use */
340     outb(0x40, dev->base_addr);
341 }
342 
343 static struct pcmcia_device_id ibmtr_ids[] = {
344 	PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e),
345 	PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47),
346 	PCMCIA_DEVICE_NULL,
347 };
348 MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
349 
350 static struct pcmcia_driver ibmtr_cs_driver = {
351 	.owner		= THIS_MODULE,
352 	.name		= "ibmtr_cs",
353 	.probe		= ibmtr_attach,
354 	.remove		= ibmtr_detach,
355 	.id_table       = ibmtr_ids,
356 	.suspend	= ibmtr_suspend,
357 	.resume		= ibmtr_resume,
358 };
359 
init_ibmtr_cs(void)360 static int __init init_ibmtr_cs(void)
361 {
362 	return pcmcia_register_driver(&ibmtr_cs_driver);
363 }
364 
exit_ibmtr_cs(void)365 static void __exit exit_ibmtr_cs(void)
366 {
367 	pcmcia_unregister_driver(&ibmtr_cs_driver);
368 }
369 
370 module_init(init_ibmtr_cs);
371 module_exit(exit_ibmtr_cs);
372