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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
2
/*
3
        Written 1993, 1994 by Donald Becker.
4
        Copyright 1993 United States Government as represented by the Director,
5
        National Security Agency.  This software may only be used and distributed
6
        according to the terms of the GNU General Public License as modified by SRC,
7
        incorporated herein by reference.
8
 
9
        The author may be reached as becker@scyld.com, or C/O
10
        Scyld Computing Corporation
11
        410 Severn Ave., Suite 210
12
        Annapolis MD 21403
13
 
14
        This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
15
        Adapter.  The programming information is from the users manual, as related
16
        by glee@ardnassak.math.clemson.edu.
17
 
18
        Changelog:
19
 
20
        Paul Gortmaker 05/98    : add support for shared mem above 1MB.
21
 
22
  */
23
 
24
static const char version[] =
25
        "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
26
 
27
#include <linux/module.h>
28
#include <linux/eisa.h>
29
#include <linux/kernel.h>
30
#include <linux/errno.h>
31
#include <linux/string.h>
32
#include <linux/netdevice.h>
33
#include <linux/etherdevice.h>
34
#include <linux/init.h>
35
 
36
#include <asm/system.h>
37
#include <asm/io.h>
38
#include <asm/irq.h>
39
 
40
#include "8390.h"
41
 
42
#define DRV_NAME        "ac3200"
43
 
44
/* Offsets from the base address. */
45
#define AC_NIC_BASE     0x00
46
#define AC_SA_PROM      0x16                    /* The station address PROM. */
47
#define AC_ADDR0        0x00                    /* Prefix station address values. */
48
#define AC_ADDR1        0x40
49
#define AC_ADDR2        0x90
50
#define AC_ID_PORT      0xC80
51
#define AC_EISA_ID      0x0110d305
52
#define AC_RESET_PORT   0xC84
53
#define AC_RESET        0x00
54
#define AC_ENABLE       0x01
55
#define AC_CONFIG       0xC90   /* The configuration port. */
56
 
57
#define AC_IO_EXTENT 0x20
58
                                /* Actually accessed is:
59
                                                                 * AC_NIC_BASE (0-15)
60
                                                                 * AC_SA_PROM (0-5)
61
                                                                 * AC_ID_PORT (0-3)
62
                                                                 * AC_RESET_PORT
63
                                                                 * AC_CONFIG
64
                                                                 */
65
 
66
/* Decoding of the configuration register. */
67
static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
68
static int addrmap[8] =
69
{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
70
static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
71
 
72
#define config2irq(configval)   config2irqmap[((configval) >> 3) & 7]
73
#define config2mem(configval)   addrmap[(configval) & 7]
74
#define config2name(configval)  port_name[((configval) >> 6) & 3]
75
 
76
/* First and last 8390 pages. */
77
#define AC_START_PG             0x00    /* First page of 8390 TX buffer */
78
#define AC_STOP_PG              0x80    /* Last page +1 of the 8390 RX ring */
79
 
80
static int ac_probe1(int ioaddr, struct net_device *dev);
81
 
82
static int ac_open(struct net_device *dev);
83
static void ac_reset_8390(struct net_device *dev);
84
static void ac_block_input(struct net_device *dev, int count,
85
                                        struct sk_buff *skb, int ring_offset);
86
static void ac_block_output(struct net_device *dev, const int count,
87
                                                        const unsigned char *buf, const int start_page);
88
static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
89
                                        int ring_page);
90
 
91
static int ac_close_card(struct net_device *dev);
92
 
93
 
94
/*      Probe for the AC3200.
95
 
96
        The AC3200 can be identified by either the EISA configuration registers,
97
        or the unique value in the station address PROM.
98
        */
99
 
100
static int __init do_ac3200_probe(struct net_device *dev)
101
{
102
        unsigned short ioaddr = dev->base_addr;
103
        int irq = dev->irq;
104
        int mem_start = dev->mem_start;
105
 
106
        if (ioaddr > 0x1ff)             /* Check a single specified location. */
107
                return ac_probe1(ioaddr, dev);
108
        else if (ioaddr > 0)             /* Don't probe at all. */
109
                return -ENXIO;
110
 
111
        if ( ! EISA_bus)
112
                return -ENXIO;
113
 
114
        for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
115
                if (ac_probe1(ioaddr, dev) == 0)
116
                        return 0;
117
                dev->irq = irq;
118
                dev->mem_start = mem_start;
119
        }
120
 
121
        return -ENODEV;
122
}
123
 
124
#ifndef MODULE
125
struct net_device * __init ac3200_probe(int unit)
126
{
127
        struct net_device *dev = alloc_ei_netdev();
128
        int err;
129
 
130
        if (!dev)
131
                return ERR_PTR(-ENOMEM);
132
 
133
        sprintf(dev->name, "eth%d", unit);
134
        netdev_boot_setup_check(dev);
135
 
136
        err = do_ac3200_probe(dev);
137
        if (err)
138
                goto out;
139
        return dev;
140
out:
141
        free_netdev(dev);
142
        return ERR_PTR(err);
143
}
144
#endif
145
 
146
static int __init ac_probe1(int ioaddr, struct net_device *dev)
147
{
148
        int i, retval;
149
        DECLARE_MAC_BUF(mac);
150
 
151
        if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
152
                return -EBUSY;
153
 
154
        if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
155
                retval = -ENODEV;
156
                goto out;
157
        }
158
 
159
        if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
160
                retval = -ENODEV;
161
                goto out;
162
        }
163
 
164
#ifndef final_version
165
        printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
166
                   " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
167
                   inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
168
                   inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
169
#endif
170
 
171
        for (i = 0; i < 6; i++)
172
                dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
173
 
174
        printk(KERN_DEBUG "AC3200 in EISA slot %d, node %s",
175
               ioaddr/0x1000, print_mac(mac, dev->dev_addr));
176
#if 0
177
        /* Check the vendor ID/prefix. Redundant after checking the EISA ID */
178
        if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
179
                || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
180
                || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
181
                printk(", not found (invalid prefix).\n");
182
                retval = -ENODEV;
183
                goto out;
184
        }
185
#endif
186
 
187
        /* Assign and allocate the interrupt now. */
188
        if (dev->irq == 0) {
189
                dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
190
                printk(", using");
191
        } else {
192
                dev->irq = irq_canonicalize(dev->irq);
193
                printk(", assigning");
194
        }
195
 
196
        retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
197
        if (retval) {
198
                printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
199
                goto out1;
200
        }
201
 
202
        printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
203
 
204
        dev->base_addr = ioaddr;
205
 
206
#ifdef notyet
207
        if (dev->mem_start)     {               /* Override the value from the board. */
208
                for (i = 0; i < 7; i++)
209
                        if (addrmap[i] == dev->mem_start)
210
                                break;
211
                if (i >= 7)
212
                        i = 0;
213
                outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
214
        }
215
#endif
216
 
217
        dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
218
        dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
219
 
220
        printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
221
                        dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
222
 
223
        /*
224
         *  BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
225
         *  the card mem within the region covered by `normal' RAM  !!!
226
         *
227
         *  ioremap() will fail in that case.
228
         */
229
        ei_status.mem = ioremap(dev->mem_start, AC_STOP_PG*0x100);
230
        if (!ei_status.mem) {
231
                printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
232
                printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
233
                printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
234
                retval = -EINVAL;
235
                goto out1;
236
        }
237
        printk("ac3200.c: remapped %dkB card memory to virtual address %p\n",
238
                        AC_STOP_PG/4, ei_status.mem);
239
 
240
        dev->mem_start = (unsigned long)ei_status.mem;
241
        dev->mem_end = dev->mem_start + (AC_STOP_PG - AC_START_PG)*256;
242
 
243
        ei_status.name = "AC3200";
244
        ei_status.tx_start_page = AC_START_PG;
245
        ei_status.rx_start_page = AC_START_PG + TX_PAGES;
246
        ei_status.stop_page = AC_STOP_PG;
247
        ei_status.word16 = 1;
248
 
249
        if (ei_debug > 0)
250
                printk(version);
251
 
252
        ei_status.reset_8390 = &ac_reset_8390;
253
        ei_status.block_input = &ac_block_input;
254
        ei_status.block_output = &ac_block_output;
255
        ei_status.get_8390_hdr = &ac_get_8390_hdr;
256
 
257
        dev->open = &ac_open;
258
        dev->stop = &ac_close_card;
259
#ifdef CONFIG_NET_POLL_CONTROLLER
260
        dev->poll_controller = ei_poll;
261
#endif
262
        NS8390_init(dev, 0);
263
 
264
        retval = register_netdev(dev);
265
        if (retval)
266
                goto out2;
267
        return 0;
268
out2:
269
        if (ei_status.reg0)
270
                iounmap(ei_status.mem);
271
out1:
272
        free_irq(dev->irq, dev);
273
out:
274
        release_region(ioaddr, AC_IO_EXTENT);
275
        return retval;
276
}
277
 
278
static int ac_open(struct net_device *dev)
279
{
280
#ifdef notyet
281
        /* Someday we may enable the IRQ and shared memory here. */
282
        int ioaddr = dev->base_addr;
283
#endif
284
 
285
        ei_open(dev);
286
        return 0;
287
}
288
 
289
static void ac_reset_8390(struct net_device *dev)
290
{
291
        ushort ioaddr = dev->base_addr;
292
 
293
        outb(AC_RESET, ioaddr + AC_RESET_PORT);
294
        if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
295
 
296
        ei_status.txing = 0;
297
        outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
298
        if (ei_debug > 1) printk("reset done\n");
299
 
300
        return;
301
}
302
 
303
/* Grab the 8390 specific header. Similar to the block_input routine, but
304
   we don't need to be concerned with ring wrap as the header will be at
305
   the start of a page, so we optimize accordingly. */
306
 
307
static void
308
ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
309
{
310
        void __iomem *hdr_start = ei_status.mem + ((ring_page - AC_START_PG)<<8);
311
        memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
312
}
313
 
314
/*  Block input and output are easy on shared memory ethercards, the only
315
        complication is when the ring buffer wraps. */
316
 
317
static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
318
                                                  int ring_offset)
319
{
320
        void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;
321
 
322
        if (ring_offset + count > AC_STOP_PG*256) {
323
                /* We must wrap the input move. */
324
                int semi_count = AC_STOP_PG*256 - ring_offset;
325
                memcpy_fromio(skb->data, start, semi_count);
326
                count -= semi_count;
327
                memcpy_fromio(skb->data + semi_count,
328
                                ei_status.mem + TX_PAGES*256, count);
329
        } else {
330
                memcpy_fromio(skb->data, start, count);
331
        }
332
}
333
 
334
static void ac_block_output(struct net_device *dev, int count,
335
                                                        const unsigned char *buf, int start_page)
336
{
337
        void __iomem *shmem = ei_status.mem + ((start_page - AC_START_PG)<<8);
338
 
339
        memcpy_toio(shmem, buf, count);
340
}
341
 
342
static int ac_close_card(struct net_device *dev)
343
{
344
        if (ei_debug > 1)
345
                printk("%s: Shutting down ethercard.\n", dev->name);
346
 
347
#ifdef notyet
348
        /* We should someday disable shared memory and interrupts. */
349
        outb(0x00, ioaddr + 6); /* Disable interrupts. */
350
        free_irq(dev->irq, dev);
351
#endif
352
 
353
        ei_close(dev);
354
        return 0;
355
}
356
 
357
#ifdef MODULE
358
#define MAX_AC32_CARDS  4       /* Max number of AC32 cards per module */
359
static struct net_device *dev_ac32[MAX_AC32_CARDS];
360
static int io[MAX_AC32_CARDS];
361
static int irq[MAX_AC32_CARDS];
362
static int mem[MAX_AC32_CARDS];
363
module_param_array(io, int, NULL, 0);
364
module_param_array(irq, int, NULL, 0);
365
module_param_array(mem, int, NULL, 0);
366
MODULE_PARM_DESC(io, "I/O base address(es)");
367
MODULE_PARM_DESC(irq, "IRQ number(s)");
368
MODULE_PARM_DESC(mem, "Memory base address(es)");
369
MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
370
MODULE_LICENSE("GPL");
371
 
372
int __init init_module(void)
373
{
374
        struct net_device *dev;
375
        int this_dev, found = 0;
376
 
377
        for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
378
                if (io[this_dev] == 0 && this_dev != 0)
379
                        break;
380
                dev = alloc_ei_netdev();
381
                if (!dev)
382
                        break;
383
                dev->irq = irq[this_dev];
384
                dev->base_addr = io[this_dev];
385
                dev->mem_start = mem[this_dev];         /* Currently ignored by driver */
386
                if (do_ac3200_probe(dev) == 0) {
387
                        dev_ac32[found++] = dev;
388
                        continue;
389
                }
390
                free_netdev(dev);
391
                printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
392
                break;
393
        }
394
        if (found)
395
                return 0;
396
        return -ENXIO;
397
}
398
 
399
static void cleanup_card(struct net_device *dev)
400
{
401
        /* Someday free_irq may be in ac_close_card() */
402
        free_irq(dev->irq, dev);
403
        release_region(dev->base_addr, AC_IO_EXTENT);
404
        iounmap(ei_status.mem);
405
}
406
 
407
void __exit
408
cleanup_module(void)
409
{
410
        int this_dev;
411
 
412
        for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
413
                struct net_device *dev = dev_ac32[this_dev];
414
                if (dev) {
415
                        unregister_netdev(dev);
416
                        cleanup_card(dev);
417
                        free_netdev(dev);
418
                }
419
        }
420
}
421
#endif /* MODULE */

powered by: WebSVN 2.1.0

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