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