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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* e2100.c: A Cabletron E2100 series ethernet driver for linux. */
2
/*
3
        Written 1993-1994 by Donald Becker.
4
 
5
        Copyright 1994 by Donald Becker.
6
        Copyright 1993 United States Government as represented by the
7
        Director, National Security Agency.  This software may be used and
8
        distributed according to the terms of the GNU General Public License,
9
        incorporated herein by reference.
10
 
11
        This is a driver for the Cabletron E2100 series ethercards.
12
 
13
        The Author may be reached as becker@scyld.com, or C/O
14
        Scyld Computing Corporation
15
        410 Severn Ave., Suite 210
16
        Annapolis MD 21403
17
 
18
        The E2100 series ethercard is a fairly generic shared memory 8390
19
        implementation.  The only unusual aspect is the way the shared memory
20
        registers are set: first you do an inb() in what is normally the
21
        station address region, and the low three bits of next outb() *address*
22
        is used as the write value for that register.  Either someone wasn't
23
        too used to dem bit en bites, or they were trying to obfuscate the
24
        programming interface.
25
 
26
        There is an additional complication when setting the window on the packet
27
        buffer.  You must first do a read into the packet buffer region with the
28
        low 8 address bits the address setting the page for the start of the packet
29
        buffer window, and then do the above operation.  See mem_on() for details.
30
 
31
        One bug on the chip is that even a hard reset won't disable the memory
32
        window, usually resulting in a hung machine if mem_off() isn't called.
33
        If this happens, you must power down the machine for about 30 seconds.
34
*/
35
 
36
static const char version[] =
37
        "e2100.c:v1.01 7/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
38
 
39
#include <linux/module.h>
40
#include <linux/kernel.h>
41
#include <linux/errno.h>
42
#include <linux/string.h>
43
#include <linux/ioport.h>
44
#include <linux/netdevice.h>
45
#include <linux/etherdevice.h>
46
#include <linux/init.h>
47
#include <linux/delay.h>
48
 
49
#include <asm/io.h>
50
#include <asm/system.h>
51
 
52
#include "8390.h"
53
 
54
#define DRV_NAME "e2100"
55
 
56
static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
57
 
58
/* Offsets from the base_addr.
59
   Read from the ASIC register, and the low three bits of the next outb()
60
   address is used to set the corresponding register. */
61
#define E21_NIC_OFFSET  0               /* Offset to the 8390 NIC. */
62
#define E21_ASIC                0x10
63
#define E21_MEM_ENABLE  0x10
64
#define  E21_MEM_ON             0x05    /* Enable memory in 16 bit mode. */
65
#define  E21_MEM_ON_8   0x07    /* Enable memory in  8 bit mode. */
66
#define E21_MEM_BASE    0x11
67
#define E21_IRQ_LOW             0x12    /* The low three bits of the IRQ number. */
68
#define E21_IRQ_HIGH    0x14    /* The high IRQ bit and media select ...  */
69
#define E21_MEDIA               0x14    /* (alias). */
70
#define  E21_ALT_IFPORT 0x02    /* Set to use the other (BNC,AUI) port. */
71
#define  E21_BIG_MEM    0x04    /* Use a bigger (64K) buffer (we don't) */
72
#define E21_SAPROM              0x10    /* Offset to station address data. */
73
#define E21_IO_EXTENT    0x20
74
 
75
static inline void mem_on(short port, volatile char __iomem *mem_base,
76
                                                  unsigned char start_page )
77
{
78
        /* This is a little weird: set the shared memory window by doing a
79
           read.  The low address bits specify the starting page. */
80
        readb(mem_base+start_page);
81
        inb(port + E21_MEM_ENABLE);
82
        outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
83
}
84
 
85
static inline void mem_off(short port)
86
{
87
        inb(port + E21_MEM_ENABLE);
88
        outb(0x00, port + E21_MEM_ENABLE);
89
}
90
 
91
/* In other drivers I put the TX pages first, but the E2100 window circuitry
92
   is designed to have a 4K Tx region last. The windowing circuitry wraps the
93
   window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring
94
   appear contiguously in the window. */
95
#define E21_RX_START_PG         0x00    /* First page of RX buffer */
96
#define E21_RX_STOP_PG          0x30    /* Last page +1 of RX ring */
97
#define E21_BIG_RX_STOP_PG      0xF0    /* Last page +1 of RX ring */
98
#define E21_TX_START_PG         E21_RX_STOP_PG  /* First page of TX buffer */
99
 
100
static int e21_probe1(struct net_device *dev, int ioaddr);
101
 
102
static int e21_open(struct net_device *dev);
103
static void e21_reset_8390(struct net_device *dev);
104
static void e21_block_input(struct net_device *dev, int count,
105
                                                   struct sk_buff *skb, int ring_offset);
106
static void e21_block_output(struct net_device *dev, int count,
107
                                                         const unsigned char *buf, int start_page);
108
static void e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
109
                                                        int ring_page);
110
 
111
static int e21_close(struct net_device *dev);
112
 
113
 
114
/*  Probe for the E2100 series ethercards.  These cards have an 8390 at the
115
        base address and the station address at both offset 0x10 and 0x18.  I read
116
        the station address from offset 0x18 to avoid the dataport of NE2000
117
        ethercards, and look for Ctron's unique ID (first three octets of the
118
        station address).
119
 */
120
 
121
static int  __init do_e2100_probe(struct net_device *dev)
122
{
123
        int *port;
124
        int base_addr = dev->base_addr;
125
        int irq = dev->irq;
126
 
127
        if (base_addr > 0x1ff)          /* Check a single specified location. */
128
                return e21_probe1(dev, base_addr);
129
        else if (base_addr != 0) /* Don't probe at all. */
130
                return -ENXIO;
131
 
132
        for (port = e21_probe_list; *port; port++) {
133
                dev->irq = irq;
134
                if (e21_probe1(dev, *port) == 0)
135
                        return 0;
136
        }
137
 
138
        return -ENODEV;
139
}
140
 
141
#ifndef MODULE
142
struct net_device * __init e2100_probe(int unit)
143
{
144
        struct net_device *dev = alloc_ei_netdev();
145
        int err;
146
 
147
        if (!dev)
148
                return ERR_PTR(-ENOMEM);
149
 
150
        sprintf(dev->name, "eth%d", unit);
151
        netdev_boot_setup_check(dev);
152
 
153
        err = do_e2100_probe(dev);
154
        if (err)
155
                goto out;
156
        return dev;
157
out:
158
        free_netdev(dev);
159
        return ERR_PTR(err);
160
}
161
#endif
162
 
163
static int __init e21_probe1(struct net_device *dev, int ioaddr)
164
{
165
        int i, status, retval;
166
        unsigned char *station_addr = dev->dev_addr;
167
        static unsigned version_printed;
168
 
169
        if (!request_region(ioaddr, E21_IO_EXTENT, DRV_NAME))
170
                return -EBUSY;
171
 
172
        /* First check the station address for the Ctron prefix. */
173
        if (inb(ioaddr + E21_SAPROM + 0) != 0x00
174
                || inb(ioaddr + E21_SAPROM + 1) != 0x00
175
                || inb(ioaddr + E21_SAPROM + 2) != 0x1d) {
176
                retval = -ENODEV;
177
                goto out;
178
        }
179
 
180
        /* Verify by making certain that there is a 8390 at there. */
181
        outb(E8390_NODMA + E8390_STOP, ioaddr);
182
        udelay(1);      /* we want to delay one I/O cycle - which is 2MHz */
183
        status = inb(ioaddr);
184
        if (status != 0x21 && status != 0x23) {
185
                retval = -ENODEV;
186
                goto out;
187
        }
188
 
189
        /* Read the station address PROM.  */
190
        for (i = 0; i < 6; i++)
191
                station_addr[i] = inb(ioaddr + E21_SAPROM + i);
192
 
193
        inb(ioaddr + E21_MEDIA);                /* Point to media selection. */
194
        outb(0, ioaddr + E21_ASIC);      /* and disable the secondary interface. */
195
 
196
        if (ei_debug  &&  version_printed++ == 0)
197
                printk(version);
198
 
199
        for (i = 0; i < 6; i++)
200
                printk(" %02X", station_addr[i]);
201
 
202
        if (dev->irq < 2) {
203
                int irqlist[] = {15,11,10,12,5,9,3,4}, i;
204
                for (i = 0; i < 8; i++)
205
                        if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
206
                                dev->irq = irqlist[i];
207
                                break;
208
                        }
209
                if (i >= 8) {
210
                        printk(" unable to get IRQ %d.\n", dev->irq);
211
                        retval = -EAGAIN;
212
                        goto out;
213
                }
214
        } else if (dev->irq == 2)       /* Fixup luser bogosity: IRQ2 is really IRQ9 */
215
                dev->irq = 9;
216
 
217
        /* The 8390 is at the base address. */
218
        dev->base_addr = ioaddr;
219
 
220
        ei_status.name = "E2100";
221
        ei_status.word16 = 1;
222
        ei_status.tx_start_page = E21_TX_START_PG;
223
        ei_status.rx_start_page = E21_RX_START_PG;
224
        ei_status.stop_page = E21_RX_STOP_PG;
225
        ei_status.saved_irq = dev->irq;
226
 
227
        /* Check the media port used.  The port can be passed in on the
228
           low mem_end bits. */
229
        if (dev->mem_end & 15)
230
                dev->if_port = dev->mem_end & 7;
231
        else {
232
                dev->if_port = 0;
233
                inb(ioaddr + E21_MEDIA);        /* Turn automatic media detection on. */
234
                for(i = 0; i < 6; i++)
235
                        if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) {
236
                                dev->if_port = 1;
237
                                break;
238
                        }
239
        }
240
 
241
        /* Never map in the E21 shared memory unless you are actively using it.
242
           Also, the shared memory has effective only one setting -- spread all
243
           over the 128K region! */
244
        if (dev->mem_start == 0)
245
                dev->mem_start = 0xd0000;
246
 
247
        ei_status.mem = ioremap(dev->mem_start, 2*1024);
248
        if (!ei_status.mem) {
249
                printk("unable to remap memory\n");
250
                retval = -EAGAIN;
251
                goto out;
252
        }
253
 
254
#ifdef notdef
255
        /* These values are unused.  The E2100 has a 2K window into the packet
256
           buffer.  The window can be set to start on any page boundary. */
257
        ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
258
        dev->mem_end = ei_status.rmem_end = dev->mem_start + 2*1024;
259
#endif
260
 
261
        printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
262
                   dev->if_port ? "secondary" : "primary", dev->mem_start);
263
 
264
        ei_status.reset_8390 = &e21_reset_8390;
265
        ei_status.block_input = &e21_block_input;
266
        ei_status.block_output = &e21_block_output;
267
        ei_status.get_8390_hdr = &e21_get_8390_hdr;
268
        dev->open = &e21_open;
269
        dev->stop = &e21_close;
270
#ifdef CONFIG_NET_POLL_CONTROLLER
271
        dev->poll_controller = ei_poll;
272
#endif
273
        NS8390_init(dev, 0);
274
 
275
        retval = register_netdev(dev);
276
        if (retval)
277
                goto out;
278
        return 0;
279
out:
280
        release_region(ioaddr, E21_IO_EXTENT);
281
        return retval;
282
}
283
 
284
static int
285
e21_open(struct net_device *dev)
286
{
287
        short ioaddr = dev->base_addr;
288
        int retval;
289
 
290
        if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
291
                return retval;
292
 
293
        /* Set the interrupt line and memory base on the hardware. */
294
        inb(ioaddr + E21_IRQ_LOW);
295
        outb(0, ioaddr + E21_ASIC + (dev->irq & 7));
296
        inb(ioaddr + E21_IRQ_HIGH);                     /* High IRQ bit, and if_port. */
297
        outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
298
                   + (dev->if_port ? E21_ALT_IFPORT : 0));
299
        inb(ioaddr + E21_MEM_BASE);
300
        outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
301
 
302
        ei_open(dev);
303
        return 0;
304
}
305
 
306
static void
307
e21_reset_8390(struct net_device *dev)
308
{
309
        short ioaddr = dev->base_addr;
310
 
311
        outb(0x01, ioaddr);
312
        if (ei_debug > 1) printk("resetting the E2180x3 t=%ld...", jiffies);
313
        ei_status.txing = 0;
314
 
315
        /* Set up the ASIC registers, just in case something changed them. */
316
 
317
        if (ei_debug > 1) printk("reset done\n");
318
        return;
319
}
320
 
321
/* Grab the 8390 specific header. We put the 2k window so the header page
322
   appears at the start of the shared memory. */
323
 
324
static void
325
e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
326
{
327
 
328
        short ioaddr = dev->base_addr;
329
        char __iomem *shared_mem = ei_status.mem;
330
 
331
        mem_on(ioaddr, shared_mem, ring_page);
332
 
333
#ifdef notdef
334
        /* Officially this is what we are doing, but the readl() is faster */
335
        memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr));
336
#else
337
        ((unsigned int*)hdr)[0] = readl(shared_mem);
338
#endif
339
 
340
        /* Turn off memory access: we would need to reprogram the window anyway. */
341
        mem_off(ioaddr);
342
 
343
}
344
 
345
/*  Block input and output are easy on shared memory ethercards.
346
        The E21xx makes block_input() especially easy by wrapping the top
347
        ring buffer to the bottom automatically. */
348
static void
349
e21_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
350
{
351
        short ioaddr = dev->base_addr;
352
        char __iomem *shared_mem = ei_status.mem;
353
 
354
        mem_on(ioaddr, shared_mem, (ring_offset>>8));
355
 
356
        memcpy_fromio(skb->data, ei_status.mem + (ring_offset & 0xff), count);
357
 
358
        mem_off(ioaddr);
359
}
360
 
361
static void
362
e21_block_output(struct net_device *dev, int count, const unsigned char *buf,
363
                                 int start_page)
364
{
365
        short ioaddr = dev->base_addr;
366
        volatile char __iomem *shared_mem = ei_status.mem;
367
 
368
        /* Set the shared memory window start by doing a read, with the low address
369
           bits specifying the starting page. */
370
        readb(shared_mem + start_page);
371
        mem_on(ioaddr, shared_mem, start_page);
372
 
373
        memcpy_toio(shared_mem, buf, count);
374
        mem_off(ioaddr);
375
}
376
 
377
static int
378
e21_close(struct net_device *dev)
379
{
380
        short ioaddr = dev->base_addr;
381
 
382
        if (ei_debug > 1)
383
                printk("%s: Shutting down ethercard.\n", dev->name);
384
 
385
        free_irq(dev->irq, dev);
386
        dev->irq = ei_status.saved_irq;
387
 
388
        /* Shut off the interrupt line and secondary interface. */
389
        inb(ioaddr + E21_IRQ_LOW);
390
        outb(0, ioaddr + E21_ASIC);
391
        inb(ioaddr + E21_IRQ_HIGH);                     /* High IRQ bit, and if_port. */
392
        outb(0, ioaddr + E21_ASIC);
393
 
394
        ei_close(dev);
395
 
396
        /* Double-check that the memory has been turned off, because really
397
           really bad things happen if it isn't. */
398
        mem_off(ioaddr);
399
 
400
        return 0;
401
}
402
 
403
 
404
#ifdef MODULE
405
#define MAX_E21_CARDS   4       /* Max number of E21 cards per module */
406
static struct net_device *dev_e21[MAX_E21_CARDS];
407
static int io[MAX_E21_CARDS];
408
static int irq[MAX_E21_CARDS];
409
static int mem[MAX_E21_CARDS];
410
static int xcvr[MAX_E21_CARDS];         /* choose int. or ext. xcvr */
411
 
412
module_param_array(io, int, NULL, 0);
413
module_param_array(irq, int, NULL, 0);
414
module_param_array(mem, int, NULL, 0);
415
module_param_array(xcvr, int, NULL, 0);
416
MODULE_PARM_DESC(io, "I/O base address(es)");
417
MODULE_PARM_DESC(irq, "IRQ number(s)");
418
MODULE_PARM_DESC(mem, " memory base address(es)");
419
MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
420
MODULE_DESCRIPTION("Cabletron E2100 ISA ethernet driver");
421
MODULE_LICENSE("GPL");
422
 
423
/* This is set up so that only a single autoprobe takes place per call.
424
ISA device autoprobes on a running machine are not recommended. */
425
 
426
int __init init_module(void)
427
{
428
        struct net_device *dev;
429
        int this_dev, found = 0;
430
 
431
        for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
432
                if (io[this_dev] == 0)  {
433
                        if (this_dev != 0) break; /* only autoprobe 1st one */
434
                        printk(KERN_NOTICE "e2100.c: Presently autoprobing (not recommended) for a single card.\n");
435
                }
436
                dev = alloc_ei_netdev();
437
                if (!dev)
438
                        break;
439
                dev->irq = irq[this_dev];
440
                dev->base_addr = io[this_dev];
441
                dev->mem_start = mem[this_dev];
442
                dev->mem_end = xcvr[this_dev];  /* low 4bits = xcvr sel. */
443
                if (do_e2100_probe(dev) == 0) {
444
                        dev_e21[found++] = dev;
445
                        continue;
446
                }
447
                free_netdev(dev);
448
                printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]);
449
                break;
450
        }
451
        if (found)
452
                return 0;
453
        return -ENXIO;
454
}
455
 
456
static void cleanup_card(struct net_device *dev)
457
{
458
        /* NB: e21_close() handles free_irq */
459
        iounmap(ei_status.mem);
460
        release_region(dev->base_addr, E21_IO_EXTENT);
461
}
462
 
463
void __exit
464
cleanup_module(void)
465
{
466
        int this_dev;
467
 
468
        for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
469
                struct net_device *dev = dev_e21[this_dev];
470
                if (dev) {
471
                        unregister_netdev(dev);
472
                        cleanup_card(dev);
473
                        free_netdev(dev);
474
                }
475
        }
476
}
477
#endif /* MODULE */

powered by: WebSVN 2.1.0

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