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