Root/drivers/net/wd.c

1/* wd.c: A WD80x3 ethernet driver for linux. */
2/*
3    Written 1993-94 by Donald Becker.
4
5    Copyright 1993 United States Government as represented by the
6    Director, National Security Agency.
7
8    This software may be used and distributed according to the terms
9    of the GNU General Public License, incorporated herein by reference.
10
11    The author may be reached as becker@scyld.com, or C/O
12    Scyld Computing Corporation
13    410 Severn Ave., Suite 210
14    Annapolis MD 21403
15
16    This is a driver for WD8003 and WD8013 "compatible" ethercards.
17
18    Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
19
20    Changelog:
21
22    Paul Gortmaker : multiple card support for module users, support
23              for non-standard memory sizes.
24
25
26*/
27
28static const char version[] =
29    "wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
30
31#include <linux/module.h>
32#include <linux/kernel.h>
33#include <linux/errno.h>
34#include <linux/string.h>
35#include <linux/init.h>
36#include <linux/interrupt.h>
37#include <linux/delay.h>
38#include <linux/netdevice.h>
39#include <linux/etherdevice.h>
40
41#include <asm/io.h>
42#include <asm/system.h>
43
44#include "8390.h"
45
46#define DRV_NAME "wd"
47
48/* A zero-terminated list of I/O addresses to be probed. */
49static unsigned int wd_portlist[] __initdata =
50{0x300, 0x280, 0x380, 0x240, 0};
51
52static int wd_probe1(struct net_device *dev, int ioaddr);
53
54static int wd_open(struct net_device *dev);
55static void wd_reset_8390(struct net_device *dev);
56static void wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
57                        int ring_page);
58static void wd_block_input(struct net_device *dev, int count,
59                          struct sk_buff *skb, int ring_offset);
60static void wd_block_output(struct net_device *dev, int count,
61                            const unsigned char *buf, int start_page);
62static int wd_close(struct net_device *dev);
63
64
65#define WD_START_PG 0x00 /* First page of TX buffer */
66#define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */
67#define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */
68
69#define WD_CMDREG 0 /* Offset to ASIC command register. */
70#define WD_RESET 0x80 /* Board reset, in WD_CMDREG. */
71#define WD_MEMENB 0x40 /* Enable the shared memory. */
72#define WD_CMDREG5 5 /* Offset to 16-bit-only ASIC register 5. */
73#define ISA16 0x80 /* Enable 16 bit access from the ISA bus. */
74#define NIC16 0x40 /* Enable 16 bit access from the 8390. */
75#define WD_NIC_OFFSET 16 /* Offset to the 8390 from the base_addr. */
76#define WD_IO_EXTENT 32
77
78
79/* Probe for the WD8003 and WD8013. These cards have the station
80    address PROM at I/O ports <base>+8 to <base>+13, with a checksum
81    following. A Soundblaster can have the same checksum as an WDethercard,
82    so we have an extra exclusionary check for it.
83
84    The wd_probe1() routine initializes the card and fills the
85    station address field. */
86
87static int __init do_wd_probe(struct net_device *dev)
88{
89    int i;
90    struct resource *r;
91    int base_addr = dev->base_addr;
92    int irq = dev->irq;
93    int mem_start = dev->mem_start;
94    int mem_end = dev->mem_end;
95
96    if (base_addr > 0x1ff) { /* Check a user specified location. */
97        r = request_region(base_addr, WD_IO_EXTENT, "wd-probe");
98        if ( r == NULL)
99            return -EBUSY;
100        i = wd_probe1(dev, base_addr);
101        if (i != 0)
102            release_region(base_addr, WD_IO_EXTENT);
103        else
104            r->name = dev->name;
105        return i;
106    }
107    else if (base_addr != 0) /* Don't probe at all. */
108        return -ENXIO;
109
110    for (i = 0; wd_portlist[i]; i++) {
111        int ioaddr = wd_portlist[i];
112        r = request_region(ioaddr, WD_IO_EXTENT, "wd-probe");
113        if (r == NULL)
114            continue;
115        if (wd_probe1(dev, ioaddr) == 0) {
116            r->name = dev->name;
117            return 0;
118        }
119        release_region(ioaddr, WD_IO_EXTENT);
120        dev->irq = irq;
121        dev->mem_start = mem_start;
122        dev->mem_end = mem_end;
123    }
124
125    return -ENODEV;
126}
127
128#ifndef MODULE
129struct net_device * __init wd_probe(int unit)
130{
131    struct net_device *dev = alloc_ei_netdev();
132    int err;
133
134    if (!dev)
135        return ERR_PTR(-ENOMEM);
136
137    sprintf(dev->name, "eth%d", unit);
138    netdev_boot_setup_check(dev);
139
140    err = do_wd_probe(dev);
141    if (err)
142        goto out;
143    return dev;
144out:
145    free_netdev(dev);
146    return ERR_PTR(err);
147}
148#endif
149
150static const struct net_device_ops wd_netdev_ops = {
151    .ndo_open = wd_open,
152    .ndo_stop = wd_close,
153    .ndo_start_xmit = ei_start_xmit,
154    .ndo_tx_timeout = ei_tx_timeout,
155    .ndo_get_stats = ei_get_stats,
156    .ndo_set_multicast_list = ei_set_multicast_list,
157    .ndo_validate_addr = eth_validate_addr,
158    .ndo_set_mac_address = eth_mac_addr,
159    .ndo_change_mtu = eth_change_mtu,
160#ifdef CONFIG_NET_POLL_CONTROLLER
161    .ndo_poll_controller = ei_poll,
162#endif
163};
164
165static int __init wd_probe1(struct net_device *dev, int ioaddr)
166{
167    int i;
168    int err;
169    int checksum = 0;
170    int ancient = 0; /* An old card without config registers. */
171    int word16 = 0; /* 0 = 8 bit, 1 = 16 bit */
172    const char *model_name;
173    static unsigned version_printed;
174
175    for (i = 0; i < 8; i++)
176        checksum += inb(ioaddr + 8 + i);
177    if (inb(ioaddr + 8) == 0xff /* Extra check to avoid soundcard. */
178        || inb(ioaddr + 9) == 0xff
179        || (checksum & 0xff) != 0xFF)
180        return -ENODEV;
181
182    /* Check for semi-valid mem_start/end values if supplied. */
183    if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) {
184        printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
185        dev->mem_start = 0;
186        dev->mem_end = 0;
187    }
188
189    if (ei_debug && version_printed++ == 0)
190        printk(version);
191
192    for (i = 0; i < 6; i++)
193        dev->dev_addr[i] = inb(ioaddr + 8 + i);
194
195    printk("%s: WD80x3 at %#3x, %pM",
196           dev->name, ioaddr, dev->dev_addr);
197
198    /* The following PureData probe code was contributed by
199       Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
200       configuration differently from others so we have to check for them.
201       This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card.
202       */
203    if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
204        unsigned char reg5 = inb(ioaddr+5);
205
206        switch (inb(ioaddr+2)) {
207        case 0x03: word16 = 0; model_name = "PDI8023-8"; break;
208        case 0x05: word16 = 0; model_name = "PDUC8023"; break;
209        case 0x0a: word16 = 1; model_name = "PDI8023-16"; break;
210            /* Either 0x01 (dumb) or they've released a new version. */
211        default: word16 = 0; model_name = "PDI8023"; break;
212        }
213        dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12;
214        dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1;
215    } else { /* End of PureData probe */
216        /* This method of checking for a 16-bit board is borrowed from the
217           we.c driver. A simpler method is just to look in ASIC reg. 0x03.
218           I'm comparing the two method in alpha test to make certain they
219           return the same result. */
220        /* Check for the old 8 bit board - it has register 0/8 aliasing.
221           Do NOT check i>=6 here -- it hangs the old 8003 boards! */
222        for (i = 0; i < 6; i++)
223            if (inb(ioaddr+i) != inb(ioaddr+8+i))
224                break;
225        if (i >= 6) {
226            ancient = 1;
227            model_name = "WD8003-old";
228            word16 = 0;
229        } else {
230            int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */
231            outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */
232            if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */
233                && (tmp & 0x01) == 0x01 ) { /* In a 16 slot. */
234                int asic_reg5 = inb(ioaddr+WD_CMDREG5);
235                /* Magic to set ASIC to word-wide mode. */
236                outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
237                outb(tmp, ioaddr+1);
238                model_name = "WD8013";
239                word16 = 1; /* We have a 16bit board here! */
240            } else {
241                model_name = "WD8003";
242                word16 = 0;
243            }
244            outb(tmp, ioaddr+1); /* Restore original reg1 value. */
245        }
246#ifndef final_version
247        if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01))
248            printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
249                   word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8);
250#endif
251    }
252
253#if defined(WD_SHMEM) && WD_SHMEM > 0x80000
254    /* Allow a compile-time override. */
255    dev->mem_start = WD_SHMEM;
256#else
257    if (dev->mem_start == 0) {
258        /* Sanity and old 8003 check */
259        int reg0 = inb(ioaddr);
260        if (reg0 == 0xff || reg0 == 0) {
261            /* Future plan: this could check a few likely locations first. */
262            dev->mem_start = 0xd0000;
263            printk(" assigning address %#lx", dev->mem_start);
264        } else {
265            int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
266            /* Some boards don't have the register 5 -- it returns 0xff. */
267            if (high_addr_bits == 0x1f || word16 == 0)
268                high_addr_bits = 0x01;
269            dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19);
270        }
271    }
272#endif
273
274    /* The 8390 isn't at the base address -- the ASIC regs are there! */
275    dev->base_addr = ioaddr+WD_NIC_OFFSET;
276
277    if (dev->irq < 2) {
278        int irqmap[] = {9,3,5,7,10,11,15,4};
279        int reg1 = inb(ioaddr+1);
280        int reg4 = inb(ioaddr+4);
281        if (ancient || reg1 == 0xff) { /* Ack!! No way to read the IRQ! */
282            short nic_addr = ioaddr+WD_NIC_OFFSET;
283            unsigned long irq_mask;
284
285            /* We have an old-style ethercard that doesn't report its IRQ
286               line. Do autoirq to find the IRQ line. Note that this IS NOT
287               a reliable way to trigger an interrupt. */
288            outb_p(E8390_NODMA + E8390_STOP, nic_addr);
289            outb(0x00, nic_addr+EN0_IMR); /* Disable all intrs. */
290
291            irq_mask = probe_irq_on();
292            outb_p(0xff, nic_addr + EN0_IMR); /* Enable all interrupts. */
293            outb_p(0x00, nic_addr + EN0_RCNTLO);
294            outb_p(0x00, nic_addr + EN0_RCNTHI);
295            outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
296            mdelay(20);
297            dev->irq = probe_irq_off(irq_mask);
298
299            outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */
300
301            if (ei_debug > 2)
302                printk(" autoirq is %d", dev->irq);
303            if (dev->irq < 2)
304                dev->irq = word16 ? 10 : 5;
305        } else
306            dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
307    } else if (dev->irq == 2) /* Fixup bogosity: IRQ2 is really IRQ9 */
308        dev->irq = 9;
309
310    /* Snarf the interrupt now. There's no point in waiting since we cannot
311       share and the board will usually be enabled. */
312    i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
313    if (i) {
314        printk (" unable to get IRQ %d.\n", dev->irq);
315        return i;
316    }
317
318    /* OK, were are certain this is going to work. Setup the device. */
319    ei_status.name = model_name;
320    ei_status.word16 = word16;
321    ei_status.tx_start_page = WD_START_PG;
322    ei_status.rx_start_page = WD_START_PG + TX_PAGES;
323
324    /* Don't map in the shared memory until the board is actually opened. */
325
326    /* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
327    if (dev->mem_end != 0) {
328        ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
329        ei_status.priv = dev->mem_end - dev->mem_start;
330    } else {
331        ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
332        dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
333        ei_status.priv = (ei_status.stop_page - WD_START_PG)*256;
334    }
335
336    ei_status.mem = ioremap(dev->mem_start, ei_status.priv);
337    if (!ei_status.mem) {
338        free_irq(dev->irq, dev);
339        return -ENOMEM;
340    }
341
342    printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
343           model_name, dev->irq, dev->mem_start, dev->mem_end-1);
344
345    ei_status.reset_8390 = &wd_reset_8390;
346    ei_status.block_input = &wd_block_input;
347    ei_status.block_output = &wd_block_output;
348    ei_status.get_8390_hdr = &wd_get_8390_hdr;
349
350    dev->netdev_ops = &wd_netdev_ops;
351    NS8390_init(dev, 0);
352
353#if 1
354    /* Enable interrupt generation on softconfig cards -- M.U */
355    /* .. but possibly potentially unsafe - Donald */
356    if (inb(ioaddr+14) & 0x20)
357        outb(inb(ioaddr+4)|0x80, ioaddr+4);
358#endif
359
360    err = register_netdev(dev);
361    if (err)
362        free_irq(dev->irq, dev);
363    return err;
364}
365
366static int
367wd_open(struct net_device *dev)
368{
369  int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
370
371  /* Map in the shared memory. Always set register 0 last to remain
372     compatible with very old boards. */
373  ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB;
374  ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16;
375
376  if (ei_status.word16)
377      outb(ei_status.reg5, ioaddr+WD_CMDREG5);
378  outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
379
380  return ei_open(dev);
381}
382
383static void
384wd_reset_8390(struct net_device *dev)
385{
386    int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
387
388    outb(WD_RESET, wd_cmd_port);
389    if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies);
390    ei_status.txing = 0;
391
392    /* Set up the ASIC registers, just in case something changed them. */
393    outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port);
394    if (ei_status.word16)
395        outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5);
396
397    if (ei_debug > 1) printk("reset done\n");
398    return;
399}
400
401/* Grab the 8390 specific header. Similar to the block_input routine, but
402   we don't need to be concerned with ring wrap as the header will be at
403   the start of a page, so we optimize accordingly. */
404
405static void
406wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
407{
408
409    int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
410    void __iomem *hdr_start = ei_status.mem + ((ring_page - WD_START_PG)<<8);
411
412    /* We'll always get a 4 byte header read followed by a packet read, so
413       we enable 16 bit mode before the header, and disable after the body. */
414    if (ei_status.word16)
415        outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
416
417#ifdef __BIG_ENDIAN
418    /* Officially this is what we are doing, but the readl() is faster */
419    /* unfortunately it isn't endian aware of the struct */
420    memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
421    hdr->count = le16_to_cpu(hdr->count);
422#else
423    ((unsigned int*)hdr)[0] = readl(hdr_start);
424#endif
425}
426
427/* Block input and output are easy on shared memory ethercards, and trivial
428   on the Western digital card where there is no choice of how to do it.
429   The only complications are that the ring buffer wraps, and need to map
430   switch between 8- and 16-bit modes. */
431
432static void
433wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
434{
435    int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
436    unsigned long offset = ring_offset - (WD_START_PG<<8);
437    void __iomem *xfer_start = ei_status.mem + offset;
438
439    if (offset + count > ei_status.priv) {
440        /* We must wrap the input move. */
441        int semi_count = ei_status.priv - offset;
442        memcpy_fromio(skb->data, xfer_start, semi_count);
443        count -= semi_count;
444        memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
445    } else {
446        /* Packet is in one chunk -- we can copy + cksum. */
447        memcpy_fromio(skb->data, xfer_start, count);
448    }
449
450    /* Turn off 16 bit access so that reboot works. ISA brain-damage */
451    if (ei_status.word16)
452        outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
453}
454
455static void
456wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
457                int start_page)
458{
459    int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
460    void __iomem *shmem = ei_status.mem + ((start_page - WD_START_PG)<<8);
461
462
463    if (ei_status.word16) {
464        /* Turn on and off 16 bit access so that reboot works. */
465        outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
466        memcpy_toio(shmem, buf, count);
467        outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
468    } else
469        memcpy_toio(shmem, buf, count);
470}
471
472
473static int
474wd_close(struct net_device *dev)
475{
476    int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
477
478    if (ei_debug > 1)
479        printk("%s: Shutting down ethercard.\n", dev->name);
480    ei_close(dev);
481
482    /* Change from 16-bit to 8-bit shared memory so reboot works. */
483    if (ei_status.word16)
484        outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 );
485
486    /* And disable the shared memory. */
487    outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg);
488
489    return 0;
490}
491
492
493#ifdef MODULE
494#define MAX_WD_CARDS 4 /* Max number of wd cards per module */
495static struct net_device *dev_wd[MAX_WD_CARDS];
496static int io[MAX_WD_CARDS];
497static int irq[MAX_WD_CARDS];
498static int mem[MAX_WD_CARDS];
499static int mem_end[MAX_WD_CARDS]; /* for non std. mem size */
500
501module_param_array(io, int, NULL, 0);
502module_param_array(irq, int, NULL, 0);
503module_param_array(mem, int, NULL, 0);
504module_param_array(mem_end, int, NULL, 0);
505MODULE_PARM_DESC(io, "I/O base address(es)");
506MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)");
507MODULE_PARM_DESC(mem, "memory base address(es)(ignored for PureData boards)");
508MODULE_PARM_DESC(mem_end, "memory end address(es)");
509MODULE_DESCRIPTION("ISA Western Digital wd8003/wd8013 ; SMC Elite, Elite16 ethernet driver");
510MODULE_LICENSE("GPL");
511
512/* This is set up so that only a single autoprobe takes place per call.
513ISA device autoprobes on a running machine are not recommended. */
514
515int __init init_module(void)
516{
517    struct net_device *dev;
518    int this_dev, found = 0;
519
520    for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
521        if (io[this_dev] == 0) {
522            if (this_dev != 0) break; /* only autoprobe 1st one */
523            printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n");
524        }
525        dev = alloc_ei_netdev();
526        if (!dev)
527            break;
528        dev->irq = irq[this_dev];
529        dev->base_addr = io[this_dev];
530        dev->mem_start = mem[this_dev];
531        dev->mem_end = mem_end[this_dev];
532        if (do_wd_probe(dev) == 0) {
533            dev_wd[found++] = dev;
534            continue;
535        }
536        free_netdev(dev);
537        printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]);
538        break;
539    }
540    if (found)
541        return 0;
542    return -ENXIO;
543}
544
545static void cleanup_card(struct net_device *dev)
546{
547    free_irq(dev->irq, dev);
548    release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
549    iounmap(ei_status.mem);
550}
551
552void __exit
553cleanup_module(void)
554{
555    int this_dev;
556
557    for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
558        struct net_device *dev = dev_wd[this_dev];
559        if (dev) {
560            unregister_netdev(dev);
561            cleanup_card(dev);
562            free_netdev(dev);
563        }
564    }
565}
566#endif /* MODULE */
567

Archive Download this file



interactive