OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [pcmcia/] [ibmtr_cs.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*======================================================================
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 = kzalloc(sizeof(*info), GFP_KERNEL);
150
    if (!info) return -ENOMEM;
151
    dev = alloc_trdev(sizeof(struct tok_info));
152
    if (!dev) {
153
        kfree(info);
154
        return -ENOMEM;
155
    }
156
 
157
    info->p_dev = link;
158
    link->priv = info;
159
    info->ti = netdev_priv(dev);
160
 
161
    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
162
    link->io.NumPorts1 = 4;
163
    link->io.IOAddrLines = 16;
164
    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
165
    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
166
    link->irq.Handler = &tok_interrupt;
167
    link->conf.Attributes = CONF_ENABLE_IRQ;
168
    link->conf.IntType = INT_MEMORY_AND_IO;
169
    link->conf.Present = PRESENT_OPTION;
170
 
171
    link->irq.Instance = info->dev = dev;
172
 
173
    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
174
 
175
    return ibmtr_config(link);
176
} /* ibmtr_attach */
177
 
178
/*======================================================================
179
 
180
    This deletes a driver "instance".  The device is de-registered
181
    with Card Services.  If it has been released, all local data
182
    structures are freed.  Otherwise, the structures will be freed
183
    when the device is released.
184
 
185
======================================================================*/
186
 
187
static void ibmtr_detach(struct pcmcia_device *link)
188
{
189
    struct ibmtr_dev_t *info = link->priv;
190
    struct net_device *dev = info->dev;
191
     struct tok_info *ti = netdev_priv(dev);
192
 
193
    DEBUG(0, "ibmtr_detach(0x%p)\n", link);
194
 
195
    /*
196
     * When the card removal interrupt hits tok_interrupt(),
197
     * bail out early, so we don't crash the machine
198
     */
199
    ti->sram_phys |= 1;
200
 
201
    if (link->dev_node)
202
        unregister_netdev(dev);
203
 
204
    del_timer_sync(&(ti->tr_timer));
205
 
206
    ibmtr_release(link);
207
 
208
    free_netdev(dev);
209
    kfree(info);
210
} /* ibmtr_detach */
211
 
212
/*======================================================================
213
 
214
    ibmtr_config() is scheduled to run after a CARD_INSERTION event
215
    is received, to configure the PCMCIA socket, and to make the
216
    token-ring device available to the system.
217
 
218
======================================================================*/
219
 
220
#define CS_CHECK(fn, ret) \
221
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
222
 
223
static int __devinit ibmtr_config(struct pcmcia_device *link)
224
{
225
    ibmtr_dev_t *info = link->priv;
226
    struct net_device *dev = info->dev;
227
    struct tok_info *ti = netdev_priv(dev);
228
    win_req_t req;
229
    memreq_t mem;
230
    int i, last_ret, last_fn;
231
 
232
    DEBUG(0, "ibmtr_config(0x%p)\n", link);
233
 
234
    link->conf.ConfigIndex = 0x61;
235
 
236
    /* Determine if this is PRIMARY or ALTERNATE. */
237
 
238
    /* Try PRIMARY card at 0xA20-0xA23 */
239
    link->io.BasePort1 = 0xA20;
240
    i = pcmcia_request_io(link, &link->io);
241
    if (i != CS_SUCCESS) {
242
        /* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
243
        link->io.BasePort1 = 0xA24;
244
        CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
245
    }
246
    dev->base_addr = link->io.BasePort1;
247
 
248
    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
249
    dev->irq = link->irq.AssignedIRQ;
250
    ti->irq = link->irq.AssignedIRQ;
251
    ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
252
 
253
    /* Allocate the MMIO memory window */
254
    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
255
    req.Attributes |= WIN_USE_WAIT;
256
    req.Base = 0;
257
    req.Size = 0x2000;
258
    req.AccessSpeed = 250;
259
    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
260
 
261
    mem.CardOffset = mmiobase;
262
    mem.Page = 0;
263
    CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
264
    ti->mmio = ioremap(req.Base, req.Size);
265
 
266
    /* Allocate the SRAM memory window */
267
    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
268
    req.Attributes |= WIN_USE_WAIT;
269
    req.Base = 0;
270
    req.Size = sramsize * 1024;
271
    req.AccessSpeed = 250;
272
    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle));
273
 
274
    mem.CardOffset = srambase;
275
    mem.Page = 0;
276
    CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem));
277
 
278
    ti->sram_base = mem.CardOffset >> 12;
279
    ti->sram_virt = ioremap(req.Base, req.Size);
280
    ti->sram_phys = req.Base;
281
 
282
    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
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 "%s: port %#3lx, irq %d,",
302
           dev->name, dev->base_addr, dev->irq);
303
    printk (" mmio %#5lx,", (u_long)ti->mmio);
304
    printk (" sram %#5lx,", (u_long)ti->sram_base << 12);
305
    printk ("\n" KERN_INFO "  hwaddr=");
306
    for (i = 0; i < TR_ALEN; i++)
307
        printk("%02X", dev->dev_addr[i]);
308
    printk("\n");
309
    return 0;
310
 
311
cs_failed:
312
    cs_error(link, last_fn, last_ret);
313
failed:
314
    ibmtr_release(link);
315
    return -ENODEV;
316
} /* ibmtr_config */
317
 
318
/*======================================================================
319
 
320
    After a card is removed, ibmtr_release() will unregister the net
321
    device, and release the PCMCIA configuration.  If the device is
322
    still open, this will be postponed until it is closed.
323
 
324
======================================================================*/
325
 
326
static void ibmtr_release(struct pcmcia_device *link)
327
{
328
        ibmtr_dev_t *info = link->priv;
329
        struct net_device *dev = info->dev;
330
 
331
        DEBUG(0, "ibmtr_release(0x%p)\n", link);
332
 
333
        if (link->win) {
334
                struct tok_info *ti = netdev_priv(dev);
335
                iounmap(ti->mmio);
336
                pcmcia_release_window(info->sram_win_handle);
337
        }
338
        pcmcia_disable_device(link);
339
}
340
 
341
static int ibmtr_suspend(struct pcmcia_device *link)
342
{
343
        ibmtr_dev_t *info = link->priv;
344
        struct net_device *dev = info->dev;
345
 
346
        if (link->open)
347
                netif_device_detach(dev);
348
 
349
        return 0;
350
}
351
 
352
static int ibmtr_resume(struct pcmcia_device *link)
353
{
354
        ibmtr_dev_t *info = link->priv;
355
        struct net_device *dev = info->dev;
356
 
357
        if (link->open) {
358
                ibmtr_probe(dev);       /* really? */
359
                netif_device_attach(dev);
360
        }
361
 
362
        return 0;
363
}
364
 
365
 
366
/*====================================================================*/
367
 
368
static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
369
{
370
    int i;
371
 
372
    /* Bizarre IBM behavior, there are 16 bits of information we
373
       need to set, but the card only allows us to send 4 bits at a
374
       time.  For each byte sent to base_addr, bits 7-4 tell the
375
       card which part of the 16 bits we are setting, bits 3-0 contain
376
       the actual information */
377
 
378
    /* First nibble provides 4 bits of mmio */
379
    i = (mmiobase >> 16) & 0x0F;
380
    outb(i, dev->base_addr);
381
 
382
    /* Second nibble provides 3 bits of mmio */
383
    i = 0x10 | ((mmiobase >> 12) & 0x0E);
384
    outb(i, dev->base_addr);
385
 
386
    /* Third nibble, hard-coded values */
387
    i = 0x26;
388
    outb(i, dev->base_addr);
389
 
390
    /* Fourth nibble sets shared ram page size */
391
 
392
    /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */
393
    i = (sramsize >> 4) & 0x07;
394
    i = ((i == 4) ? 3 : i) << 2;
395
    i |= 0x30;
396
 
397
    if (ringspeed == 16)
398
        i |= 2;
399
    if (dev->base_addr == 0xA24)
400
        i |= 1;
401
    outb(i, dev->base_addr);
402
 
403
    /* 0x40 will release the card for use */
404
    outb(0x40, dev->base_addr);
405
 
406
    return;
407
}
408
 
409
static struct pcmcia_device_id ibmtr_ids[] = {
410
        PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e),
411
        PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47),
412
        PCMCIA_DEVICE_NULL,
413
};
414
MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
415
 
416
static struct pcmcia_driver ibmtr_cs_driver = {
417
        .owner          = THIS_MODULE,
418
        .drv            = {
419
                .name   = "ibmtr_cs",
420
        },
421
        .probe          = ibmtr_attach,
422
        .remove         = ibmtr_detach,
423
        .id_table       = ibmtr_ids,
424
        .suspend        = ibmtr_suspend,
425
        .resume         = ibmtr_resume,
426
};
427
 
428
static int __init init_ibmtr_cs(void)
429
{
430
        return pcmcia_register_driver(&ibmtr_cs_driver);
431
}
432
 
433
static void __exit exit_ibmtr_cs(void)
434
{
435
        pcmcia_unregister_driver(&ibmtr_cs_driver);
436
}
437
 
438
module_init(init_ibmtr_cs);
439
module_exit(exit_ibmtr_cs);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.