]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.53 1.1.53
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:41 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:41 +0000 (15:09 -0500)
30 files changed:
Makefile
drivers/char/console.c
drivers/net/3c501.c
drivers/net/3c503.c
drivers/net/3c507.c
drivers/net/3c509.c
drivers/net/8390.c
drivers/net/8390.h
drivers/net/at1700.c
drivers/net/auto_irq.c
drivers/net/hp-plus.c
drivers/net/hp.c
drivers/net/lance.c
drivers/net/loopback.c
drivers/net/ne.c
drivers/net/net_init.c
drivers/net/skeleton.c
drivers/net/smc-ultra.c
drivers/net/wd.c
drivers/net/znet.c
drivers/scsi/scsi.c
fs/nfs/proc.c
fs/nfs/sock.c
fs/nfs/symlink.c
include/linux/resource.h
include/linux/signal.h
kernel/sched.c
kernel/signal.c
kernel/vm86.c
net/inet/icmp.c

index 2915d6e47726fb68b6f371651cdcafe216ff9026..be288e78e330043850810bccd230637d64ecdd3f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 52
+SUBLEVEL = 53
 
 ARCH = i386
 
@@ -136,7 +136,11 @@ tools/version.h: $(CONFIGURE) Makefile
        @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h
-       @echo \#define LINUX_COMPILE_DOMAIN \"`domainname`\" >> tools/version.h
+       @if [ -x /bin/dnsdomainname ]; then \
+          echo \#define LINUX_COMPILE_DOMAIN \"`dnsdomainname`\"; \
+        else \
+          echo \#define LINUX_COMPILE_DOMAIN \"`domainname`\"; \
+        fi >> tools/version.h
        @echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> tools/version.h
 
 tools/build: tools/build.c $(CONFIGURE)
index 4d39b09acc6551127132031c564a6974eaf9586e..5f4b56742a72069c25a631111c6dfb2060cc044e 100644 (file)
@@ -1081,20 +1081,32 @@ static void reset_terminal(int currcons, int do_clear)
 }
 
 /*
- * Turn the Scroll-Lock LED on when the tty is stopped (with a ^S)
+ * Turn the Scroll-Lock LED on when the tty is stopped
  */
 static void con_stop(struct tty_struct *tty)
 {
-       set_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
+       int console_num;
+       if (!tty)
+               return;
+       console_num = MINOR(tty->device) - (tty->driver.minor_start);
+       if (console_num < 0 || console_num >= NR_CONSOLES)
+               return;
+       set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
        set_leds();
 }
 
 /*
- * Turn the Scroll-Lock LED off when the console is started (with a ^Q)
+ * Turn the Scroll-Lock LED off when the console is started
  */
 static void con_start(struct tty_struct *tty)
 {
-       clr_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
+       int console_num;
+       if (!tty)
+               return;
+       console_num = MINOR(tty->device) - (tty->driver.minor_start);
+       if (console_num < 0 || console_num >= NR_CONSOLES)
+               return;
+       clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
        set_leds();
 }
 
index e87a8124652b17efcf31f46482f6231cab9f10d0..b757b2558eaeaeab7874319aabe762fa12b91c56 100644 (file)
@@ -1,6 +1,6 @@
 /* 3c501.c: A 3Com 3c501 ethernet driver for linux. */
 /*
-    Copyright (C) 1992,1993  Donald Becker
+    Written 1992,1993,1994  Donald Becker
 
     Copyright 1993 United States Government as represented by the
     Director, National Security Agency.  This software may be used and
     Do not purchase this card, even as a joke.  It's performance is horrible,
     and it breaks in many ways.  
 
-    The Author may be reached as becker@super.org or
-    C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
-    I'll only accept bug fixes, not reports, for the 3c501 driver.
+    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+    Center of Excellence in Space Data and Information Sciences
+       Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 */
 
 static char *version =
-    "3c501.c: 3/3/94 Donald Becker (becker@super.org).\n";
+    "3c501.c: 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov).\n";
 
 /*
   Braindamage remaining:
@@ -32,6 +32,7 @@ static char *version =
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/malloc.h>
+#include <linux/string.h>
 #include <linux/ioport.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -46,16 +47,18 @@ static char *version =
 #include "../../tools/version.h"
 #endif
 
-#ifndef HAVE_AUTOIRQ
-/* From auto_irq.c, should be in a *.h file. */
-extern void autoirq_setup(int waittime);
-extern int autoirq_report(int waittime);
-extern struct device *irq2dev_map[16];
-#endif
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                   unsigned long *mem_startp);
+
+/* A zero-terminated list of I/O addresses to be probed.
+   The 3c501 can be at many locations, but here are the popular ones. */
+static unsigned int netcard_portlist[] =
+   { 0x280, 0x300, 0};
 
 \f
 /* Index to functions. */
 int el1_probe(struct device *dev);
+static int  el1_probe1(struct device *dev, int ioaddr);
 static int  el_open(struct device *dev);
 static int  el_start_xmit(struct sk_buff *skb, struct device *dev);
 static void el_interrupt(int reg_ptr);
@@ -65,37 +68,34 @@ static int  el1_close(struct device *dev);
 static struct enet_statistics *el1_get_stats(struct device *dev);
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 
-#define EL_NAME "EtherLink 3c501"
+#define EL1_IO_EXTENT  16
 
 #ifndef EL_DEBUG
 #define EL_DEBUG  2    /* use 0 for production, 1 for devel., >2 for debug */
 #endif                 /* Anything above 5 is wordy death! */
 static int el_debug = EL_DEBUG;
-static int el_base;
-static struct device *eldev;   /* Only for consistency checking.  */
  
-/* We could easily have this struct kmalloc()ed per-board, but
-   who would want more than one 3c501?. */
-static struct {
+/* Board-specific info in dev->priv. */
+struct net_local {
     struct enet_statistics stats;
     int tx_pkt_start;          /* The length of the current Tx packet. */
     int collisions;            /* Tx collisions this packet */
-} el_status;                   /* This should be stored per-board */
+};
 
 \f
-#define RX_STATUS (el_base + 0x06)
+#define RX_STATUS (ioaddr + 0x06)
 #define RX_CMD   RX_STATUS
-#define TX_STATUS (el_base + 0x07)
+#define TX_STATUS (ioaddr + 0x07)
 #define TX_CMD   TX_STATUS
-#define GP_LOW           (el_base + 0x08)
-#define GP_HIGH   (el_base + 0x09)
-#define RX_BUF_CLR (el_base + 0x0A)
-#define RX_LOW   (el_base + 0x0A)
-#define RX_HIGH   (el_base + 0x0B)
-#define SAPROM   (el_base + 0x0C)
-#define AX_STATUS (el_base + 0x0E)
+#define GP_LOW           (ioaddr + 0x08)
+#define GP_HIGH   (ioaddr + 0x09)
+#define RX_BUF_CLR (ioaddr + 0x0A)
+#define RX_LOW   (ioaddr + 0x0A)
+#define RX_HIGH   (ioaddr + 0x0B)
+#define SAPROM   (ioaddr + 0x0C)
+#define AX_STATUS (ioaddr + 0x0E)
 #define AX_CMD   AX_STATUS
-#define DATAPORT  (el_base + 0x0F)
+#define DATAPORT  (ioaddr + 0x0F)
 #define TX_RDY 0x08            /* In TX_STATUS */
 
 #define EL1_DATAPTR    0x08
@@ -128,37 +128,64 @@ static struct {
 #define RX_GOOD        0x30            /* Good packet 0x20, or simple overflow 0x10. */
 \f
 
+/* The boilerplate probe code. */
+#ifdef HAVE_DEVLIST
+struct netdev_entry el1_drv =
+{"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist};
+#else
 int
 el1_probe(struct device *dev)
 {
     int i;
-    int ioaddr;
-    unsigned char station_addr[6];
-    int autoirq = 0;
-
-    eldev = dev;               /* Store for debugging. */
-    el_base = dev->base_addr;
+    int base_addr = dev ? dev->base_addr : 0;
+
+    if (base_addr > 0x1ff)     /* Check a single specified location. */
+       return el1_probe1(dev, base_addr);
+    else if (base_addr != 0)   /* Don't probe at all. */
+       return ENXIO;
+
+    for (i = 0; netcard_portlist[i]; i++) {
+       int ioaddr = netcard_portlist[i];
+       if (check_region(ioaddr, EL1_IO_EXTENT))
+           continue;
+       if (el1_probe1(dev, ioaddr) == 0)
+           return 0;
+    }
 
-    if (el_base < 0x40)                /* Invalid?  Probe for it. */
-       el_base = 0x280;
+    return ENODEV;
+}
+#endif
 
-    ioaddr = el_base;
+/* The actual probe. */ 
+static int
+el1_probe1(struct device *dev, int ioaddr)
+{
+    char *mname;               /* Vendor name */
+    unsigned char station_addr[6];
+    int autoirq = 0;
+    int i;
 
     /* Read the station address PROM data from the special port.  */
     for (i = 0; i < 6; i++) {
        outw(i, ioaddr + EL1_DATAPTR);
        station_addr[i] = inb(ioaddr + EL1_SAPROM);
     }
-    /* Check the first three octets of the S.A. for 3Com's code. */ 
-    if (station_addr[0] != 0x02  ||  station_addr[1] != 0x60
-       || station_addr[2] != 0x8c) {
+    /* Check the first three octets of the S.A. for 3Com's prefix, or
+       for the Sager NP943 prefix. */ 
+    if (station_addr[0] == 0x02  &&  station_addr[1] == 0x60
+       && station_addr[2] == 0x8c) {
+       mname = "3c501";
+    } else if (station_addr[0] == 0x00  &&  station_addr[1] == 0x80
+       && station_addr[2] == 0xC8) {
+       mname = "NP943";
+    } else
        return ENODEV;
-    }
 
-#ifdef HAVE_PORTRESERVE
     /* Grab the region so we can find the another board if autoIRQ fails. */
-    snarf_region(ioaddr, 16);
-#endif
+    snarf_region(ioaddr, EL1_IO_EXTENT);
+
+    if (dev == NULL)
+       dev = init_etherdev(0, sizeof(struct net_local), 0);
 
     /* We auto-IRQ by shutting off the interrupt line and letting it float
        high. */
@@ -175,25 +202,33 @@ el1_probe(struct device *dev)
        autoirq = autoirq_report(1);
 
        if (autoirq == 0) {
-           printk("%s: 3c501 probe failed to detect IRQ line.\n", dev->name);
+           printk("%s probe at %#x failed to detect IRQ line.\n",
+                  mname, ioaddr);
            return EAGAIN;
        }
-       dev->irq = autoirq;
     }
 
     outb(AX_RESET+AX_LOOP, AX_CMD);                    /* Loopback mode. */
 
-    dev->base_addr = el_base;
+    dev->base_addr = ioaddr;
     memcpy(dev->dev_addr, station_addr, ETH_ALEN);
     if (dev->mem_start & 0xf)
        el_debug = dev->mem_start & 0x7;
+    if (autoirq)
+       dev->irq = autoirq;
 
-    printk("%s: 3c501 EtherLink at %#x, using %sIRQ %d, melting ethernet.\n",
-          dev->name, dev->base_addr, autoirq ? "auto":"assigned ", dev->irq);
+    printk("%s: %s EtherLink at %#x, using %sIRQ %d, melting ethernet.\n",
+          dev->name, mname, dev->base_addr,
+          autoirq ? "auto":"assigned ", dev->irq);
 
     if (el_debug)
        printk("%s", version);
 
+    /* Initialize the device structure. */
+    if (dev->priv == NULL)
+       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+    memset(dev->priv, 0, sizeof(struct net_local));
+
     /* The EL1-specific entries in the device structure. */
     dev->open = &el_open;
     dev->hard_start_xmit = &el_start_xmit;
@@ -210,36 +245,33 @@ el1_probe(struct device *dev)
 static int
 el_open(struct device *dev)
 {
+    int ioaddr = dev->base_addr;
 
-  if (el_debug > 2)
-      printk("%s: Doing el_open()...", dev->name);
+    if (el_debug > 2)
+       printk("%s: Doing el_open()...", dev->name);
 
-  if (request_irq(dev->irq, &el_interrupt, 0, "3c501")) {
-      if (el_debug > 2)
-         printk("interrupt busy, exiting el_open().\n");
-      return -EAGAIN;
-  }
-  irq2dev_map[dev->irq] = dev;
+    if (request_irq(dev->irq, &el_interrupt, 0, "3c501")) {
+       return -EAGAIN;
+    }
+    irq2dev_map[dev->irq] = dev;
 
-  el_reset(dev);
+    el_reset(dev);
 
-  dev->start = 1;
+    dev->start = 1;
 
-  outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */
-  if (el_debug > 2)
-     printk("finished el_open().\n");
+    outb(AX_RX, AX_CMD);       /* Aux control, irq and receive enabled */
 #ifdef MODULE
-  MOD_INC_USE_COUNT;
+    MOD_INC_USE_COUNT;
 #endif       
-  return (0);
+    return 0;
 }
 
 static int
 el_start_xmit(struct sk_buff *skb, struct device *dev)
 {
-    unsigned long flags;
-    
-    save_flags(flags);
+    struct net_local *lp = (struct net_local *)dev->priv;
+    int ioaddr = dev->base_addr;
+
     if (dev->tbusy) {
        if (jiffies - dev->trans_start < 20) {
            if (el_debug > 2)
@@ -249,18 +281,12 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
        if (el_debug)
            printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
                    dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
-       el_status.stats.tx_errors++;
-#ifdef oldway
-       el_reset(dev);
-#else
-       cli();
+       lp->stats.tx_errors++;
        outb(TX_NORM, TX_CMD);
        outb(RX_NORM, RX_CMD);
        outb(AX_OFF, AX_CMD);   /* Just trigger a false interrupt. */
-#endif
        outb(AX_RX, AX_CMD);    /* Aux control, irq and receive enabled */
        dev->tbusy = 0;
-       restore_flags(flags);
        dev->trans_start = jiffies;
     }
 
@@ -269,28 +295,21 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
        return 0;
     }
 
-    if (skb->len <= 0)
-       return 0;
-
     /* Avoid timer-based retransmission conflicts. */
-    cli();
     if (set_bit(0, (void*)&dev->tbusy) != 0)
-    {
        printk("%s: Transmitter access conflict.\n", dev->name);
-       restore_flags(flags);
-    } else {
+    else {
        int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
        unsigned char *buf = skb->data;
 
-       el_status.tx_pkt_start = gp_start;
-       el_status.collisions = 0;
+       lp->tx_pkt_start = gp_start;
+       lp->collisions = 0;
 
        outb(AX_SYS, AX_CMD);
        inb(RX_STATUS);
        inb(TX_STATUS);
-       outb(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */
+       outw(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */
        outw(gp_start, GP_LOW);
-       restore_flags(flags);
        outsb(DATAPORT,buf,skb->len);
        outw(gp_start, GP_LOW);
        outb(AX_XMIT, AX_CMD);          /* Trigger xmit.  */
@@ -310,18 +329,18 @@ static void
 el_interrupt(int reg_ptr)
 {
     int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
-    /*struct device *dev = (struct device *)(irq2dev_map[irq]);*/
-    struct device *dev = eldev;
+    struct device *dev = (struct device *)(irq2dev_map[irq]);
+    struct net_local *lp;
+    int ioaddr;
     int axsr;                  /* Aux. status reg. */
-    short ioaddr;
 
-    if (eldev->irq != irq) {
-       printk (EL_NAME ": irq %d for unknown device\n", irq);
+    if (dev == NULL  ||  dev->irq != irq) {
+       printk ("3c501 driver: irq %d for unknown device.\n", irq);
        return;
     }
 
     ioaddr = dev->base_addr;
-
+    lp = (struct net_local *)dev->priv;
     axsr = inb(AX_STATUS);
 
     if (el_debug > 3)
@@ -348,18 +367,18 @@ el_interrupt(int reg_ptr)
                printk("%s: Transmit failed 16 times, ethernet jammed?\n",
                       dev->name);
            outb(AX_SYS, AX_CMD);
-           el_status.stats.tx_aborted_errors++;
+           lp->stats.tx_aborted_errors++;
        } else if (txsr & TX_COLLISION) {       /* Retrigger xmit. */
            if (el_debug > 6)
                printk(" retransmitting after a collision.\n");
            outb(AX_SYS, AX_CMD);
-           outw(el_status.tx_pkt_start, GP_LOW);
+           outw(lp->tx_pkt_start, GP_LOW);
            outb(AX_XMIT, AX_CMD);
-           el_status.stats.collisions++;
+           lp->stats.collisions++;
            dev->interrupt = 0;
            return;
        } else {
-           el_status.stats.tx_packets++;
+           lp->stats.tx_packets++;
            if (el_debug > 6)
                printk(" Tx succeeded %s\n",
                       (txsr & TX_RDY) ? "." : "but tx is busy!");
@@ -374,24 +393,24 @@ el_interrupt(int reg_ptr)
 
        /* Just reading rx_status fixes most errors. */
        if (rxsr & RX_MISSED)
-           el_status.stats.rx_missed_errors++;
+           lp->stats.rx_missed_errors++;
        if (rxsr & RX_RUNT) {   /* Handled to avoid board lock-up. */
-           el_status.stats.rx_length_errors++;
+           lp->stats.rx_length_errors++;
            if (el_debug > 5) printk(" runt.\n");
        } else if (rxsr & RX_GOOD) {
-           el_receive(eldev);
+           el_receive(dev);
        } else {                        /* Nothing?  Something is broken! */
            if (el_debug > 2)
                printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n",
                       dev->name, rxsr);
-           el_reset(eldev);
+           el_reset(dev);
        }
        if (el_debug > 3)
            printk(".\n");
     }
 
     outb(AX_RX, AX_CMD);
-    outb(0x00, RX_BUF_CLR);
+    outw(0x00, RX_BUF_CLR);
     inb(RX_STATUS);            /* Be certain that interrupts are cleared. */
     inb(TX_STATUS);
     dev->interrupt = 0;
@@ -404,6 +423,8 @@ el_interrupt(int reg_ptr)
 static void
 el_receive(struct device *dev)
 {
+    struct net_local *lp = (struct net_local *)dev->priv;
+    int ioaddr = dev->base_addr;
     int pkt_len;
     struct sk_buff *skb;
 
@@ -415,7 +436,7 @@ el_receive(struct device *dev)
     if ((pkt_len < 60)  ||  (pkt_len > 1536)) {
        if (el_debug)
          printk("%s: bogus packet, length=%d\n", dev->name, pkt_len);
-       el_status.stats.rx_over_errors++;
+       lp->stats.rx_over_errors++;
        return;
     }
     outb(AX_SYS, AX_CMD);
@@ -424,7 +445,7 @@ el_receive(struct device *dev)
     outw(0x00, GP_LOW);
     if (skb == NULL) {
        printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-       el_status.stats.rx_dropped++;
+       lp->stats.rx_dropped++;
        return;
     } else {
        skb->len = pkt_len;
@@ -433,7 +454,7 @@ el_receive(struct device *dev)
        insb(DATAPORT, skb->data, pkt_len);
 
        netif_rx(skb);
-       el_status.stats.rx_packets++;
+       lp->stats.rx_packets++;
     }
     return;
 }
@@ -441,6 +462,8 @@ el_receive(struct device *dev)
 static void 
 el_reset(struct device *dev)
 {
+    int ioaddr = dev->base_addr;
+
     if (el_debug> 2)
        printk("3c501 reset...");
     outb(AX_RESET, AX_CMD);    /* Reset the chip */
@@ -448,10 +471,10 @@ el_reset(struct device *dev)
     {
        int i;
        for (i = 0; i < 6; i++) /* Set the station address. */
-           outb(dev->dev_addr[i], el_base + i);
+           outb(dev->dev_addr[i], ioaddr + i);
     }
     
-    outb(0, RX_BUF_CLR);               /* Set rx packet area to 0. */
+    outw(0, RX_BUF_CLR);               /* Set rx packet area to 0. */
     cli();                     /* Avoid glitch on writes to CMD regs */
     outb(TX_NORM, TX_CMD);             /* tx irq on done, collision */
     outb(RX_NORM, RX_CMD);     /* Set Rx commands. */
@@ -487,7 +510,8 @@ el1_close(struct device *dev)
 static struct enet_statistics *
 el1_get_stats(struct device *dev)
 {
-    return &el_status.stats;
+    struct net_local *lp = (struct net_local *)dev->priv;
+    return &lp->stats;
 }
 
 /* Set or clear the multicast filter for this adaptor.
@@ -499,6 +523,8 @@ el1_get_stats(struct device *dev)
 static void
 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
+    int ioaddr = dev->base_addr;
+
     if (num_addrs > 0) {
        outb(RX_MULT, RX_CMD);
        inb(RX_STATUS);         /* Clear status. */
@@ -510,14 +536,6 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
        inb(RX_STATUS);
     }
 }
-\f
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer  -m486 -c -o 3c501.o 3c501.c"
- *  kept-new-versions: 5
- * End:
- */
-
 #ifdef MODULE
 char kernel_version[] = UTS_RELEASE;
 static struct device dev_3c501 = {
@@ -545,3 +563,10 @@ cleanup_module(void)
        }
 }
 #endif /* MODULE */
+\f
+/*
+ * Local variables:
+ *  compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer  -m486 -c -o 3c501.o 3c501.c"
+ *  kept-new-versions: 5
+ * End:
+ */
index b57c14f22736b3db975fb5cce6a6e38e5070d0db..703b8288e256344cc4efbdf340079503fb33732f 100644 (file)
@@ -1,22 +1,29 @@
 /* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
 /*
-    Written 1992,1993 by Donald Becker.
+    Written 1992-94 by Donald Becker.
 
     Copyright 1993 United States Government as represented by the
     Director, National Security Agency.  This software may be used and
     distributed according to the terms of the GNU Public License,
     incorporated herein by reference.
 
+    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+    Center of Excellence in Space Data and Information Sciences
+       Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
     This driver should work with the 3c503 and 3c503/16.  It should be used
     in shared memory mode for best performance, although it may also work
     in programmed-I/O mode.
 
-    The Author may be reached as becker@super.org or
-    C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+    Sources:
+    EtherLink II Technical Reference Guide,
+    3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
+    
+    The Crynwr 3c503 packet driver.
 */
 
 static char *version =
-    "3c503.c:v0.99.15k 3/3/93 Donald Becker (becker@super.org)\n";
+    "3c503.c:v1.10 9/23/93  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -31,9 +38,27 @@ static char *version =
 #include "8390.h"
 #include "3c503.h"
 
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                   unsigned long *mem_startp);
+
 int el2_probe(struct device *dev);
-int el2_pio_autoprobe(struct device *dev);
-int el2probe1(int ioaddr, struct device *dev);
+int el2_pio_probe(struct device *dev);
+int el2_probe1(struct device *dev, int ioaddr);
+
+/* A zero-terminated list of I/O addresses to be probed in PIO mode. */
+static unsigned int netcard_portlist[] =
+       { 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
+
+#define EL2_IO_EXTENT  16
+
+#ifdef HAVE_DEVLIST
+/* The 3c503 uses two entries, one for the safe memory-mapped probe and
+   the other for the typical I/O probe. */
+struct netdev_entry el2_drv =
+{"3c503", el2_probe, EL1_IO_EXTENT, 0};
+struct netdev_entry el2pio_drv =
+{"3c503pio", el2_pioprobe1, EL1_IO_EXTENT, netcard_portlist};
+#endif
 
 static int el2_open(struct device *dev);
 static int el2_close(struct device *dev);
@@ -52,19 +77,16 @@ static int el2_block_input(struct device *dev, int count, char *buf,
    If the ethercard isn't found there is an optional probe for
    ethercard jumpered to programmed-I/O mode.
    */
-
-static int ports[] = {0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
-
 int
 el2_probe(struct device *dev)
 {
     int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
-    short ioaddr = dev->base_addr;
+    int base_addr = dev->base_addr;
 
-    if (ioaddr < 0)
-       return ENXIO;           /* Don't probe at all. */
-    if (ioaddr > 0)
-       return ! el2probe1(ioaddr, dev);
+    if (base_addr > 0x1ff)     /* Check a single specified location. */
+       return el2_probe1(dev, base_addr);
+    else if (base_addr != 0)           /* Don't probe at all. */
+       return ENXIO;
 
     for (addr = addrs; *addr; addr++) {
        int i;
@@ -75,86 +97,99 @@ el2_probe(struct device *dev)
                break;
        if (base_bits != 1)
            continue;
-#ifdef HAVE_PORTRESERVE
-       if (check_region(ports[i], 16))
+       if (check_region(netcard_portlist[i], EL2_IO_EXTENT))
            continue;
-#endif
-       if (el2probe1(ports[i], dev))
+       if (el2_probe1(dev, netcard_portlist[i]) == 0)
            return 0;
     }
-#ifndef no_probe_nonshared_memory
-    return el2_pio_autoprobe(dev);
+#if ! defined(no_probe_nonshared_memory) && ! defined (HAVE_DEVLIST)
+    return el2_pio_probe(dev);
 #else
     return ENODEV;
 #endif
 }
 
+#ifndef HAVE_DEVLIST
 /*  Try all of the locations that aren't obviously empty.  This touches
     a lot of locations, and is much riskier than the code above. */
 int
-el2_pio_autoprobe(struct device *dev)
+el2_pio_probe(struct device *dev)
 {
     int i;
-    for (i = 0; i < 8; i++) {
-#ifdef HAVE_PORTRESERVE
-       if (check_region(ports[i], 16))
-           continue;
-#endif
-       /* Reset and/or avoid any lurking NE2000 */
-       if (inb_p(ports[i] + 0x408) == 0xff)
+    int base_addr = dev ? dev->base_addr : 0;
+
+    if (base_addr > 0x1ff)     /* Check a single specified location. */
+       return el2_probe1(dev, base_addr);
+    else if (base_addr != 0)   /* Don't probe at all. */
+       return ENXIO;
+
+    for (i = 0; netcard_portlist[i]; i++) {
+       int ioaddr = netcard_portlist[i];
+       if (check_region(ioaddr, EL2_IO_EXTENT))
            continue;
-       if (inb(ports[i] + 0x403) == (0x80 >> i) /* Preliminary check */
-           && el2probe1(ports[i], dev))
+       if (el2_probe1(dev, ioaddr) == 0)
            return 0;
     }
+
     return ENODEV;
 }
+#endif
 
 /* Probe for the Etherlink II card at I/O port base IOADDR,
    returning non-zero on success.  If found, set the station
    address and memory parameters in DEVICE. */
 int
-el2probe1(int ioaddr, struct device *dev)
+el2_probe1(struct device *dev, int ioaddr)
 {
     int i, iobase_reg, membase_reg, saved_406;
-    unsigned char *station_addr = dev->dev_addr;
+    static unsigned version_printed = 0;
+
+    /* Reset and/or avoid any lurking NE2000 */
+    if (inb(ioaddr + 0x408) == 0xff)
+       return ENODEV;
 
     /* We verify that it's a 3C503 board by checking the first three octets
        of its ethernet address. */
-    printk("3c503 probe at %#3x:", ioaddr);
     iobase_reg = inb(ioaddr+0x403);
     membase_reg = inb(ioaddr+0x404);
-    /* Verify ASIC register that should be 0 or have a single bit set. */
+    /* ASIC location registers should be 0 or have only a single bit set. */
     if (   (iobase_reg  & (iobase_reg - 1))
        || (membase_reg & (membase_reg - 1))) {
-       printk("  not found.\n");
-       return 0;
+       return ENODEV;
     }
     saved_406 = inb_p(ioaddr + 0x406);
     outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
     outb_p(ECNTRL_THIN, ioaddr + 0x406);
     /* Map the station addr PROM into the lower I/O ports. */
     outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
-    for (i = 0; i < ETHER_ADDR_LEN; i++) {
-       printk(" %2.2X", (station_addr[i] = inb(ioaddr + i)));
-    }
-    if ( station_addr[0] != 0x02
-       || station_addr[1] != 0x60
-       || station_addr[2] != 0x8c) {
-       printk("  3C503 not found.\n");
+    if (   inb(ioaddr + 0) != 0x02
+       || inb(ioaddr + 1) != 0x60
+       || inb(ioaddr + 2) != 0x8c) {
        /* Restore the register we frobbed. */
        outb(saved_406, ioaddr + 0x406);
-       return 0;
+       return ENODEV;
     }
 
-#ifdef HAVE_PORTRESERVE
-    snarf_region(ioaddr, 16);
-#endif
+    snarf_region(ioaddr, EL2_IO_EXTENT);
+
+    if (dev == NULL)
+       dev = init_etherdev(0, sizeof(struct ei_device), 0);
+
+    if (ei_debug  &&  version_printed++ == 0)
+       printk(version);
+
+    dev->base_addr = ioaddr;
     ethdev_init(dev);
 
+    printk("%s: 3c503 at %#3x,", dev->name, ioaddr);
+
+    /* Retrive and print the ethernet address. */
+    for (i = 0; i < 6; i++)
+       printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
+
     /* Map the 8390 back into the window. */
     outb(ECNTRL_THIN, ioaddr + 0x406);
-    dev->base_addr = ioaddr;
+
     /* Probe for, turn on and clear the board's shared memory. */
     if (ei_debug > 2) printk(" memory jumpers %2.2x ", membase_reg);
     outb(EGACFR_NORM, ioaddr + 0x405); /* Enable RAM */
@@ -231,10 +266,11 @@ el2probe1(int ioaddr, struct device *dev)
     else
        printk("\n%s: %s using programmed I/O (REJUMPER for SHARED MEMORY).\n",
               dev->name, ei_status.name);
+
     if (ei_debug > 1)
        printk(version);
 
-    return ioaddr;
+    return 0;
 }
 \f
 static int
@@ -425,5 +461,6 @@ el2_block_input(struct device *dev, int count, char *buf, int ring_offset)
  * Local variables:
  *  version-control: t
  *  kept-new-versions: 5
+ *  c-indent-level: 4
  * End:
  */
index d923f452b1ca37498ab1a2e773f6328adf9a66e8..e8a8ae67340f5c428a3e5f8abac07db3f13a4d8c 100644 (file)
@@ -1,13 +1,16 @@
 /* 3c507.c: An EtherLink16 device driver for Linux. */
 /*
-       Written 1993 by Donald Becker.
-       Copyright 1993 United States Government as represented by the Director,
-       National Security Agency.  This software may only be used and distributed
-       according to the terms of the GNU Public License as modified by SRC,
-       incorporated herein by reference.
+       Written 1993,1994 by Donald Becker.
 
-       The author may be reached as becker@super.org or
-       C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
        Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
        and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
@@ -21,7 +24,7 @@
 */
 
 static char *version =
-       "3c507.c:v0.99-15f 2/17/94 Donald Becker (becker@super.org)\n";
+       "3c507.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/config.h>
 
@@ -32,8 +35,8 @@ static char *version =
        that filled in the gaping holes of the Intel documentation.  Three cheers
        for Russ Nelson.
 
-       Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough
-       info that the casual reader might think that it documents the i82586.
+       Intel Microcommunications Databook, Vol. 1, 1990.  It provides just enough
+       info that the casual reader might think that it documents the i82586 :-<.
 */
 
 #include <linux/kernel.h>
@@ -56,12 +59,20 @@ static char *version =
 #include <linux/skbuff.h>
 #include <linux/malloc.h>
 
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                                                       unsigned long *mem_startp);
+
+
 /* use 0 for production, 1 for verification, 2..7 for debug */
 #ifndef NET_DEBUG
 #define NET_DEBUG 1
 #endif
 static unsigned int net_debug = NET_DEBUG;
 
+/* A zero-terminated list of common I/O addresses to be probed. */
+static unsigned int netcard_portlist[] =
+       { 0x300, 0x320, 0x340, 0x280, 0};
+
 /*
                        Details of the i82586.
 
@@ -130,6 +141,7 @@ struct net_local {
 #define ROM_CONFIG     13
 #define MEM_CONFIG     14
 #define IRQ_CONFIG     15
+#define EL16_IO_EXTENT 16
 
 /* The ID port is used at boot-time to locate the ethercard. */
 #define ID_PORT                0x100
@@ -267,7 +279,7 @@ unsigned short init_words[] = {
 
 extern int el16_probe(struct device *dev);     /* Called from Space.c */
 
-static int     el16_probe1(struct device *dev, short ioaddr);
+static int     el16_probe1(struct device *dev, int ioaddr);
 static int     el16_open(struct device *dev);
 static int     el16_send_packet(struct sk_buff *skb, struct device *dev);
 static void    el16_interrupt(int reg_ptr);
@@ -279,6 +291,11 @@ static void hardware_send_packet(struct device *dev, void *buf, short length);
 void init_82586_mem(struct device *dev);
 
 \f
+#ifdef HAVE_DEVLIST
+struct netdev_entry netcard_drv =
+{"3c507", el16_probe1, EL16_IO_EXTENT, netcard_portlist};
+#endif
+
 /* Check for a network adaptor of this type, and return '0' iff one exists.
        If dev->base_addr == 0, probe all likely locations.
        If dev->base_addr == 1, always return failure.
@@ -288,55 +305,57 @@ void init_82586_mem(struct device *dev);
 int
 el16_probe(struct device *dev)
 {
-       /* Don't probe all settable addresses, 0x[23][0-F]0, just common ones. */
-       int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0};
-       int base_addr = dev->base_addr;
-       ushort lrs_state = 0xff, i;
+       int base_addr = dev ? dev->base_addr : 0;
+       int i;
 
        if (base_addr > 0x1ff)  /* Check a single specified location. */
                return el16_probe1(dev, base_addr);
-       else if (base_addr > 0)
+       else if (base_addr != 0)
                return ENXIO;           /* Don't probe at all. */
 
-       /* Send the ID sequence to the ID_PORT to enable the board. */
-       outb(0x00, ID_PORT);
-       for(i = 0; i < 255; i++) {
-               outb(lrs_state, ID_PORT);
-               lrs_state <<= 1;
-               if (lrs_state & 0x100)
-                       lrs_state ^= 0xe7;
-       }
-       outb(0x00, ID_PORT);
-
-       for (port = &ports[0]; *port; port++) {
-               short ioaddr = *port;
-#if 0
-               /* This is my original code. */
-               if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3'
-                       && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O'
-                       && el16_probe1(dev, *port) == 0)
+       for (i = 0; netcard_portlist[i]; i++) {
+               int ioaddr = netcard_portlist[i];
+               if (check_region(ioaddr, EL16_IO_EXTENT))
+                       continue;
+               if (el16_probe1(dev, ioaddr) == 0)
                        return 0;
-#else
-       /* This is code from jennings@Montrouge.SMR.slb.com, done so that
-          the string can be printed out. */
-               char res[5];
-               res[0] = inb(ioaddr); res[1] = inb(ioaddr+1);
-               res[2] = inb(ioaddr+2); res[3] = inb(ioaddr+3);
-               res[4] = 0;
-               if (res[0] == '*' && res[1] == '3'
-                       && res[2] == 'C' && res[3] == 'O'
-                       && el16_probe1(dev, *port) == 0)
-                 return 0;
-#endif
        }
 
        return ENODEV;                  /* ENODEV would be more accurate. */
 }
 
-int el16_probe1(struct device *dev, short ioaddr)
+int el16_probe1(struct device *dev, int ioaddr)
 {
+       static unsigned char init_ID_done = 0, version_printed = 0;
        int i, irq, irqval;
 
+       if (init_ID_done == 0) {
+               ushort lrs_state = 0xff;
+               /* Send the ID sequence to the ID_PORT to enable the board(s). */
+               outb(0x00, ID_PORT);
+               for(i = 0; i < 255; i++) {
+                       outb(lrs_state, ID_PORT);
+                       lrs_state <<= 1;
+                       if (lrs_state & 0x100)
+                               lrs_state ^= 0xe7;
+               }
+               outb(0x00, ID_PORT);
+               init_ID_done = 1;
+       }
+
+       if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3'
+               && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O')
+               ;
+       else
+               return ENODEV;
+
+       /* Allocate a new 'dev' if needed. */
+       if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct net_local), 0);
+
+       if (net_debug  &&  version_printed++ == 0)
+               printk(version);
+
        printk("%s: 3c507 at %#x,", dev->name, ioaddr);
 
        /* We should make a few more checks here, like the first three octets of
@@ -351,7 +370,7 @@ int el16_probe1(struct device *dev, short ioaddr)
        }
        
        /* We've committed to using the board, and can start filling in *dev. */
-       snarf_region(ioaddr, 16);
+       snarf_region(ioaddr, EL16_IO_EXTENT);
        dev->base_addr = ioaddr;
 
        outb(0x01, ioaddr + MISC_CTRL);
@@ -394,7 +413,8 @@ int el16_probe1(struct device *dev, short ioaddr)
                printk(version);
 
        /* Initialize the device structure. */
-       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+       if (dev->priv == NULL)
+               dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
        memset(dev->priv, 0, sizeof(struct net_local));
 
        dev->open               = el16_open;
index 752c99893d84d71b8f824f8c74704a106c3931d3..f8f363c6897cedd77edb3726691af4688d68d432 100644 (file)
@@ -2,12 +2,12 @@
 /*
        Written 1993,1994 by Donald Becker.
 
-       Copyright 1994 by Donald Becker. 
+       Copyright 1994 by Donald Becker.
        Copyright 1993 United States Government as represented by the
        Director, National Security Agency.      This software may be used and
        distributed according to the terms of the GNU Public License,
        incorporated herein by reference.
-       
+
        This driver is for the 3Com EtherLinkIII series.
 
        The author may be reached as becker@cesdis.gsfc.nasa.gov or
@@ -24,7 +24,7 @@
        practice this rarely happens.
 */
 
-static char *version = "3c509.c:1.01 7/5/94 becker@cesdis.gsfc.nasa.gov\n";
+static char *version = "3c509.c:1.03 10/8/94 becker@cesdis.gsfc.nasa.gov\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -65,7 +65,23 @@ int el3_debug = 2;
 #define ID_PORT 0x100
 #define         EEPROM_READ 0x80
 
-#define EL3WINDOW(win_num) outw(0x0800+(win_num), ioaddr + EL3_CMD)
+#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+
+
+/* The top five bits written to EL3_CMD are a command, the lower
+   11 bits are the parameter, if applicable. */
+enum c509cmd {
+       TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
+       RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
+       TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
+       FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrMask = 14<<11,
+       SetReadZero = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
+       SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
+       StatsDisable = 22<<11, StopCoax = 23<<11,};
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+       RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
 
 /* Register window 1 offsets, the window used in normal operation. */
 #define TX_FIFO                0x00
@@ -74,7 +90,8 @@ int el3_debug = 2;
 #define TX_STATUS      0x0B
 #define TX_FREE                0x0C            /* Remaining free bytes in Tx buffer. */
 
-#define WN4_MEDIA      0x0A            /* Window 4: Various transceiver/media bits. */
+#define WN0_IRQ                0x08            /* Window 0: Set IRQ line in bits 12-15. */
+#define WN4_MEDIA      0x0A            /* Window 4: Various transcvr/media bits. */
 #define  MEDIA_TP      0x00C0          /* Enable link beat and jabber for 10baseT. */
 
 struct el3_private {
@@ -116,9 +133,9 @@ int el3_probe(struct device *dev)
                                continue;
 
                        /* Change the register set to the configuration window 0. */
-                       outw(0x0800, ioaddr + 0xC80 + EL3_CMD);
+                       outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
 
-                       irq = inw(ioaddr + 8) >> 12;
+                       irq = inw(ioaddr + WN0_IRQ) >> 12;
                        if_port = inw(ioaddr + 6)>>14;
                        for (i = 0; i < 3; i++)
                                phys_addr[i] = htons(read_eeprom(ioaddr, i));
@@ -137,7 +154,7 @@ int el3_probe(struct device *dev)
                for (i = 0; i < 8; i++)
                        if ((mca_adaptor_id(i) | 1) == 0x627c) {
                                ioaddr = mca_pos_base_addr(i);
-                               irq = inw(ioaddr + 8) >> 12;
+                               irq = inw(ioaddr + WN0_IRQ) >> 12;
                                if_port = inw(ioaddr + 6)>>14;
                                for (i = 0; i < 3; i++)
                                        phys_addr[i] = htons(read_eeprom(ioaddr, i));
@@ -148,7 +165,7 @@ int el3_probe(struct device *dev)
                mca_adaptor_select_mode(0);
 
        }
-#endif   
+#endif
 
        /* Next check for all ISA bus boards by sending the ID sequence to the
           ID_PORT.  We find cards past the first by setting the 'current_tag'
@@ -201,6 +218,8 @@ int el3_probe(struct device *dev)
        if (inw(ioaddr) != 0x6d50)
                return -ENODEV;
 
+       /* Free the interrupt so that some other card can use it. */
+       outw(0x0f00, ioaddr + WN0_IRQ);
  found:
        dev->base_addr = ioaddr;
        dev->irq = irq;
@@ -257,7 +276,7 @@ static ushort read_eeprom(short ioaddr, int index)
 static ushort id_read_eeprom(int index)
 {
        int timer, bit, word = 0;
-       
+
        /* Issue read command, and pause for at least 162 us. for it to complete.
           Assume extra-fast 16Mhz bus. */
        outb(EEPROM_READ + index, ID_PORT);
@@ -268,7 +287,7 @@ static ushort id_read_eeprom(int index)
 
        for (bit = 15; bit >= 0; bit--)
                word = (word << 1) + (inb(ID_PORT) & 0x01);
-               
+
        if (el3_debug > 3)
                printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
 
@@ -283,6 +302,10 @@ el3_open(struct device *dev)
        int ioaddr = dev->base_addr;
        int i;
 
+       outw(TxReset, ioaddr + EL3_CMD);
+       outw(RxReset, ioaddr + EL3_CMD);
+       outw(SetReadZero | 0x00, ioaddr + EL3_CMD);
+
        if (request_irq(dev->irq, &el3_interrupt, 0, "3c509")) {
                return -EAGAIN;
        }
@@ -298,7 +321,7 @@ el3_open(struct device *dev)
        irq2dev_map[dev->irq] = dev;
 
        /* Set the IRQ line. */
-       outw((dev->irq << 12) | 0x0f00, ioaddr + 8);
+       outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
 
        /* Set the station address in window 2 each time opened. */
        EL3WINDOW(2);
@@ -308,25 +331,38 @@ el3_open(struct device *dev)
 
        if (dev->if_port == 3)
                /* Start the thinnet transceiver. We should really wait 50ms...*/
-               outw(0x1000, ioaddr + EL3_CMD);
+               outw(StartCoax, ioaddr + EL3_CMD);
        else if (dev->if_port == 0) {
                /* 10baseT interface, enabled link beat and jabber check. */
                EL3WINDOW(4);
                outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
        }
 
+       /* Switch to the stats window, and clear all stats by reading. */
+       outw(StatsDisable, ioaddr + EL3_CMD);
+       EL3WINDOW(6);
+       for (i = 0; i < 9; i++)
+               inb(ioaddr + i);
+       inb(ioaddr + 10);
+       inb(ioaddr + 12);
+
        /* Switch to register set 1 for normal use. */
        EL3WINDOW(1);
 
-       outw(0x8005, ioaddr + EL3_CMD); /* Accept b-case and phys addr only. */
-       outw(0xA800, ioaddr + EL3_CMD); /* Turn on statistics. */
-       outw(0x2000, ioaddr + EL3_CMD); /* Enable the receiver. */
-       outw(0x4800, ioaddr + EL3_CMD); /* Enable transmitter. */
-       outw(0x78ff, ioaddr + EL3_CMD); /* Allow all status bits to be seen. */
+       /* Accept b-case and phys addr only. */
+       outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
+       outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+
        dev->interrupt = 0;
        dev->tbusy = 0;
        dev->start = 1;
-       outw(0x7098, ioaddr + EL3_CMD); /* Set interrupt mask. */
+
+       outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+       outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+       /* Allow status bits to be seen. */
+       outw(SetReadZero | 0xff, ioaddr + EL3_CMD);
+       outw(AckIntr | 0x69, ioaddr + EL3_CMD); /* Ack IRQ */
+       outw(SetIntrMask | 0x98, ioaddr + EL3_CMD); /* Set interrupt mask. */
 
        if (el3_debug > 3)
                printk("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
@@ -353,8 +389,8 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
                           dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS));
                dev->trans_start = jiffies;
                /* Issue TX_RESET and TX_START commands. */
-               outw(0x5800, ioaddr + EL3_CMD); /* TX_RESET */
-               outw(0x4800, ioaddr + EL3_CMD); /* TX_START */
+               outw(TxReset, ioaddr + EL3_CMD);
+               outw(TxEnable, ioaddr + EL3_CMD);
                dev->tbusy = 0;
        }
 
@@ -371,7 +407,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
                           dev->name, skb->len, inw(ioaddr + EL3_STATUS));
        }
 #ifndef final_version
-       {       /* Error-checking code, delete for 1.00. */
+       {       /* Error-checking code, delete for 1.30. */
                ushort status = inw(ioaddr + EL3_STATUS);
                if (status & 0x0001             /* IRQ line active, missed one. */
                        && inw(ioaddr + EL3_STATUS) & 1) {                      /* Make sure. */
@@ -379,9 +415,10 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
                                   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
                                   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
                                   inw(ioaddr + RX_STATUS));
-                       outw(0x7800, ioaddr + EL3_CMD); /* Fake interrupt trigger. */
-                       outw(0x6899, ioaddr + EL3_CMD); /* Ack IRQ */
-                       outw(0x78ff, ioaddr + EL3_CMD); /* Set all status bits visible. */
+                       /* Fake interrupt trigger by masking, acknowledge interrupts. */
+                       outw(SetReadZero | 0x00, ioaddr + EL3_CMD);
+                       outw(AckIntr | 0x69, ioaddr + EL3_CMD); /* Ack IRQ */
+                       outw(SetReadZero | 0xff, ioaddr + EL3_CMD);
                }
        }
 #endif
@@ -395,13 +432,13 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
                outw(0x00, ioaddr + TX_FIFO);
                /* ... and the packet rounded to a doubleword. */
                outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-       
+
                dev->trans_start = jiffies;
                if (inw(ioaddr + TX_FREE) > 1536) {
-                       dev->tbusy=0;
+                       dev->tbusy = 0;
                } else
                        /* Interrupt us when the FIFO has room for max-sized packet. */
-                       outw(0x9000 + 1536, ioaddr + EL3_CMD);
+                       outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
        }
 
        dev_kfree_skb (skb, FREE_WRITE);
@@ -412,11 +449,9 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
                int i = 4;
 
                while (--i > 0  &&      (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
-                       if (el3_debug > 5)
-                               printk("                Tx status %4.4x.\n", tx_status);
                        if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
-                       if (tx_status & 0x30) outw(0x5800, ioaddr + EL3_CMD);
-                       if (tx_status & 0x3C) outw(0x4800, ioaddr + EL3_CMD);
+                       if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
+                       if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
                        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
                }
        }
@@ -446,8 +481,8 @@ el3_interrupt(int reg_ptr)
 
        if (el3_debug > 4)
                printk("%s: interrupt, status %4.4x.\n", dev->name, status);
-       
-       while ((status = inw(ioaddr + EL3_STATUS)) & 0x01) {
+
+       while ((status = inw(ioaddr + EL3_STATUS)) & 0x91) {
 
                if (status & 0x10)
                        el3_rx(dev);
@@ -456,29 +491,30 @@ el3_interrupt(int reg_ptr)
                        if (el3_debug > 5)
                                printk("        TX room bit was handled.\n");
                        /* There's room in the FIFO for a full-sized packet. */
-                       outw(0x6808, ioaddr + EL3_CMD); /* Ack IRQ */
+                       outw(AckIntr | 0x08, ioaddr + EL3_CMD);
                        dev->tbusy = 0;
                        mark_bh(NET_BH);
                }
                if (status & 0x80)                              /* Statistics full. */
                        update_stats(ioaddr, dev);
-               
+
                if (++i > 10) {
                        printk("%s: Infinite loop in interrupt, status %4.4x.\n",
                                   dev->name, status);
-                       /* Clear all interrupts we have handled */
-                       outw(0x68FF, ioaddr + EL3_CMD);
+                       /* Clear all interrupts. */
+                       outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
                        break;
                }
                /* Acknowledge the IRQ. */
-               outw(0x6891, ioaddr + EL3_CMD); /* Ack IRQ */
+               outw(AckIntr | 0x41, ioaddr + EL3_CMD); /* Ack IRQ */
+
        }
 
        if (el3_debug > 4) {
                printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
                           inw(ioaddr + EL3_STATUS));
        }
-       
+
        dev->interrupt = 0;
        return;
 }
@@ -488,10 +524,12 @@ static struct enet_statistics *
 el3_get_stats(struct device *dev)
 {
        struct el3_private *lp = (struct el3_private *)dev->priv;
+       unsigned long flags;
 
-       sti();
-       update_stats(dev->base_addr, dev);
+       save_flags(flags);
        cli();
+       update_stats(dev->base_addr, dev);
+       restore_flags(flags);
        return &lp->stats;
 }
 
@@ -507,7 +545,7 @@ static void update_stats(int ioaddr, struct device *dev)
        if (el3_debug > 5)
                printk("   Updating the statistics.\n");
        /* Turn off statistics updates while reading. */
-       outw(0xB000, ioaddr + EL3_CMD);
+       outw(StatsDisable, ioaddr + EL3_CMD);
        /* Switch to the stats window, and read everything. */
        EL3WINDOW(6);
        lp->stats.tx_carrier_errors     += inb(ioaddr + 0);
@@ -517,14 +555,14 @@ static void update_stats(int ioaddr, struct device *dev)
        lp->stats.tx_window_errors              += inb(ioaddr + 4);
        lp->stats.rx_fifo_errors                += inb(ioaddr + 5);
        lp->stats.tx_packets                    += inb(ioaddr + 6);
-       lp->stats.rx_packets                    += inb(ioaddr + 7);
+       /* Rx packets   */                              inb(ioaddr + 7);
        /* Tx deferrals */                              inb(ioaddr + 8);
        inw(ioaddr + 10);       /* Total Rx and Tx octets. */
        inw(ioaddr + 12);
 
        /* Back to window 1, and turn statistics back on. */
        EL3WINDOW(1);
-       outw(0xA800, ioaddr + EL3_CMD);
+       outw(StatsEnable, ioaddr + EL3_CMD);
        return;
 }
 
@@ -536,7 +574,7 @@ el3_rx(struct device *dev)
        short rx_status;
 
        if (el3_debug > 5)
-               printk("           In rx_packet(), status %4.4x, rx_status %4.4x.\n",
+               printk("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
                           inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
        while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
                if (rx_status & 0x4000) { /* Error, update stats. */
@@ -550,9 +588,7 @@ el3_rx(struct device *dev)
                        case 0x2000:            lp->stats.rx_frame_errors++; break;
                        case 0x2800:            lp->stats.rx_crc_errors++; break;
                        }
-               }
-               if ( (! (rx_status & 0x4000))
-                       || ! (rx_status & 0x1000)) { /* Dribble bits are OK. */
+               } else {
                        short pkt_len = rx_status & 0x7ff;
                        struct sk_buff *skb;
 
@@ -568,45 +604,21 @@ el3_rx(struct device *dev)
                                insl(ioaddr+RX_FIFO, skb->data,
                                                        (pkt_len + 3) >> 2);
 
-#ifdef HAVE_NETIF_RX
                                netif_rx(skb);
-                               outw(0x4000, ioaddr + EL3_CMD); /* Rx discard */
+                               outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+                               lp->stats.rx_packets++;
                                continue;
-#else
-                               skb->lock = 0;
-                               if (dev_rint((unsigned char *)skb, pkt_len,
-                                                        IN_SKBUFF,dev)== 0){
-                                       if (el3_debug > 6)
-                                               printk("         dev_rint() happy, status %4.4x.\n",
-                                               inb(ioaddr + EL3_STATUS));
-                                       outw(0x4000, ioaddr + EL3_CMD); /* Rx discard */
-                                       while (inw(ioaddr + EL3_STATUS) & 0x1000)
-                                         printk("      Waiting for 3c509 to discard packet, status %x.\n",
-                                                        inw(ioaddr + EL3_STATUS) );
-                                       if (el3_debug > 6)
-                                               printk("         discarded packet, status %4.4x.\n",
-                                               inb(ioaddr + EL3_STATUS));
-                                       continue;
-                               } else {
-                                       printk("%s: receive buffers full.\n", dev->name);
-                                       kfree_s(skb, FREE_READ);
-                               }
-#endif
                        } else if (el3_debug)
                                printk("%s: Couldn't allocate a sk_buff of size %d.\n",
                                           dev->name, pkt_len);
                }
                lp->stats.rx_dropped++;
-               outw(0x4000, ioaddr + EL3_CMD); /* Rx discard */
+               outw(RxDiscard, ioaddr + EL3_CMD);
                while (inw(ioaddr + EL3_STATUS) & 0x1000)
-                 printk("      Waiting for 3c509 to discard packet, status %x.\n",
-                                inw(ioaddr + EL3_STATUS) );
+                       printk("        Waiting for 3c509 to discard packet, status %x.\n",
+                                  inw(ioaddr + EL3_STATUS) );
        }
 
-       if (el3_debug > 5)
-               printk("           Exiting rx_packet(), status %4.4x, rx_status %4.4x.\n",
-                          inw(ioaddr+EL3_STATUS), inw(ioaddr+8));
-
        return 0;
 }
 
@@ -621,12 +633,15 @@ static void
 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
        short ioaddr = dev->base_addr;
+       if (el3_debug > 1)
+               printk("%s: Setting Rx mode to %d addresses.\n", dev->name, num_addrs);
        if (num_addrs > 0) {
-               outw(0x8007, ioaddr + EL3_CMD);
+               outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
        } else if (num_addrs < 0) {
-               outw(0x8008, ioaddr + EL3_CMD);
+               outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
+                        ioaddr + EL3_CMD);
        } else
-               outw(0x8005, ioaddr + EL3_CMD);
+               outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
 }
 #endif
 
@@ -641,16 +656,16 @@ el3_close(struct device *dev)
        dev->tbusy = 1;
        dev->start = 0;
 
-       /* Turn off statistics.  We update lp->stats below. */
-       outw(0xB000, ioaddr + EL3_CMD);
+       /* Turn off statistics ASAP.  We update lp->stats below. */
+       outw(StatsDisable, ioaddr + EL3_CMD);
 
        /* Disable the receiver and transmitter. */
-       outw(0x1800, ioaddr + EL3_CMD);
-       outw(0x5000, ioaddr + EL3_CMD);
+       outw(RxDisable, ioaddr + EL3_CMD);
+       outw(TxDisable, ioaddr + EL3_CMD);
 
        if (dev->if_port == 3)
-               /* Turn off thinnet power. */
-               outw(0xb800, ioaddr + EL3_CMD);
+               /* Turn off thinnet power.  Green! */
+               outw(StopCoax, ioaddr + EL3_CMD);
        else if (dev->if_port == 0) {
                /* Disable link beat and jabber, if_port may change ere next open(). */
                EL3WINDOW(4);
@@ -661,7 +676,7 @@ el3_close(struct device *dev)
        /* Switching back to window 0 disables the IRQ. */
        EL3WINDOW(0);
        /* But we explicitly zero the IRQ line select anyway. */
-       outw(0x0f00, ioaddr + 8);
+       outw(0x0f00, ioaddr + WN0_IRQ);
 
 
        irq2dev_map[dev->irq] = 0;
@@ -672,15 +687,7 @@ el3_close(struct device *dev)
 #endif
        return 0;
 }
-\f
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c509.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  tab-width: 4
- * End:
- */
+
 #ifdef MODULE
 char kernel_version[] = UTS_RELEASE;
 static struct device dev_3c509 = {
@@ -707,3 +714,12 @@ cleanup_module(void)
        }
 }
 #endif /* MODULE */
+\f
+/*
+ * Local variables:
+ *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c509.c"
+ *  version-control: t
+ *  kept-new-versions: 5
+ *  tab-width: 4
+ * End:
+ */
index e811fd1c61354d987fccabe4bade6b029fe4f160..5d1178d5803835e3951b2457da491425f7a0768e 100644 (file)
@@ -1,34 +1,33 @@
 /* 8390.c: A general NS8390 ethernet driver core for linux. */
 /*
-  Written 1992,1993 by Donald Becker.
+       Written 1992-94 by Donald Becker.
   
-  Copyright 1993 United States Government as represented by the
-  Director, National Security Agency.   This software may be used and
-  distributed according to the terms of the GNU Public License,
-  incorporated herein by reference.
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
   
   This is the chip-specific code for many 8390-based ethernet adaptors.
   This is not a complete driver, it must be combined with board-specific
   code such as ne.c, wd.c, 3c503.c, etc.
-  
-  The Author may be reached as becker@super.org or
-  C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
   */
 
 static char *version =
-    "8390.c:v0.99-15e 2/16/94 Donald Becker (becker@super.org)\n";
+    "8390.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 #include <linux/config.h>
 
 /*
   Braindamage remaining:
-  Much of this code should be cleaned up post-1.00, but it has been
-  extensively beta tested in the current form.
+  Much of this code should have been cleaned up, but every attempt 
+  has broken some clone part.
   
   Sources:
   The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
-  The NE* programming info came from the Crynwr packet driver, and figuring
-  out that the those boards are similar to the NatSemi evaluation board
-  described in AN-729. Thanks NS, no thanks to Novell/Eagle.
   */
 
 #include <linux/config.h>
@@ -302,7 +301,11 @@ void ei_interrupt(int reg_ptr)
     }
     
     if (interrupts && ei_debug) {
-               printk("%s: unknown interrupt %#2x\n", dev->name, interrupts);
+               if (boguscount == 9)
+                       printk("%s: Too much work at interrupt, status %#2.2x\n",
+                                  dev->name, interrupts);
+               else
+                       printk("%s: unknown interrupt %#2x\n", dev->name, interrupts);
                outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
                outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
     }
index d5c71968a51149bf730f332249a7192ce86a5b9e..f9b5ea1284e3d31b596e1f0fd93e4fd2d07fef14 100644 (file)
@@ -41,12 +41,12 @@ struct ei_device {
   void (*reset_8390)(struct device *);
   void (*block_output)(struct device *, int, const unsigned char *, int);
   int  (*block_input)(struct device *, int, char *, int);
-  int open:1;
-  int word16:1;        /* We have the 16-bit (vs 8-bit) version of the card. */
-  int txing:1;                 /* Transmit Active */
-  int dmaing:2;                        /* Remote DMA Active */
-  int irqlock:1;               /* 8390's intrs disabled when '1'. */
-  int pingpong:1;              /* Using the ping-pong driver */
+  unsigned open:1;
+  unsigned word16:1;  /* We have the 16-bit (vs 8-bit) version of the card. */
+  unsigned txing:1;            /* Transmit Active */
+  unsigned dmaing:2;           /* Remote DMA Active */
+  unsigned irqlock:1;          /* 8390's intrs disabled when '1'. */
+  unsigned pingpong:1;         /* Using the ping-pong driver */
   unsigned char tx_start_page, rx_start_page, stop_page;
   unsigned char current_page;  /* Read pointer in buffer  */
   unsigned char interface_num; /* Net port (AUI, 10bT.) to use. */
index 91d13840b667376304ca1d6f3efd281b607f58d4..7a2f6bd182406956f3c28e96d8706991cf15092b 100644 (file)
@@ -1,29 +1,38 @@
 /* at1700.c: A network device driver for  the Allied Telesis AT1700.
 
-   Written 1993 by Donald Becker.  This is a alpha test limited release.
-   This version may only be used and distributed according to the terms of the
-   GNU Public License, incorporated herein by reference.
+       Written 1993-94 by Donald Becker.
 
-   The author may be reached as becker@super.org or
-   C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
 
-   This is a device driver for the Allied Telesis AT1700, which is a
-   straightforward Fujitsu MB86965 implementation.
-*/
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
 
-static char *version =
-       "at1700.c:v0.06 3/3/94  Donald Becker (becker@super.org)\n";
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
-#include <linux/config.h>
+       This is a device driver for the Allied Telesis AT1700, which is a
+       straight-forward Fujitsu MB86965 implementation.
 
-/*
   Sources:
     The Fujitsu MB86695 datasheet.
 
-       After this driver was written, ATI provided their EEPROM configuration
-       code header file.  Thanks to Gerry Sockins of ATI.
+       After the initial version of this driver was written Gerry Sockins of
+       ATI provided their EEPROM configurationcode header file.
+    Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
+
+  Bugs:
+       The MB86695 has a design flaw that makes all probes unreliable.  Not
+       only is it difficult to detect, it also moves around in I/O space in
+       response to inb()s from other device probes!
 */
 
+static char *version =
+       "at1700.c:v1.10 9/24/94  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/config.h>
+
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -43,19 +52,16 @@ static char *version =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                                                       unsigned long *mem_startp);
 
-#ifndef HAVE_AUTOIRQ
-/* From auto_irq.c, in ioport.h for later versions. */
-extern void autoirq_setup(int waittime);
-extern int autoirq_report(int waittime);
-/* The map from IRQ number (as passed to the interrupt handler) to
-   'struct device'. */
-extern struct device *irq2dev_map[16];
-#endif
+/* This unusual address order is used to verify the CONFIG register. */
+static int at1700_probe_list[] =
+{0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0};
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
-#define NET_DEBUG 2
+#define NET_DEBUG 1
 #endif
 static unsigned int net_debug = NET_DEBUG;
 
@@ -87,6 +93,9 @@ struct net_local {
 #define MODE13                 13
 #define EEPROM_Ctrl    16
 #define EEPROM_Data    17
+#define IOCONFIG               19
+#define RESET                  31              /* Write to reset some parts of the chip. */
+#define AT1700_IO_EXTENT       32
 
 /*  EEPROM_Ctrl bits. */
 #define EE_SHIFT_CLK   0x40    /* EEPROM shift clock, in reg. 16. */
@@ -124,20 +133,26 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
    If dev->base_addr == 2, allocate space for the device and return success
    (detachable devices only).
    */
+#ifdef HAVE_DEVLIST
+/* Support for a alternate probe manager, which will eliminate the
+   boilerplate below. */
+struct netdev_entry at1700_drv =
+{"at1700", at1700_probe1, AT1700_IO_EXTENT, at1700_probe_list};
+#else
 int
 at1700_probe(struct device *dev)
 {
-       short ports[] = {0x300, 0x280, 0x380, 0x320, 0x340, 0x260, 0x2a0, 0x240, 0};
-       short *port, base_addr = dev->base_addr;
+       int i;
+       int base_addr = dev ? dev->base_addr : 0;
 
        if (base_addr > 0x1ff)          /* Check a single specified location. */
                return at1700_probe1(dev, base_addr);
-       else if (base_addr > 0)         /* Don't probe at all. */
+       else if (base_addr != 0)        /* Don't probe at all. */
                return ENXIO;
 
-       for (port = &ports[0]; *port; port++) {
-               int ioaddr = *port;
-               if (check_region(ioaddr, 32))
+       for (i = 0; at1700_probe_list[i]; i++) {
+               int ioaddr = at1700_probe_list[i];
+               if (check_region(ioaddr, AT1700_IO_EXTENT))
                        continue;
                if (at1700_probe1(dev, ioaddr) == 0)
                        return 0;
@@ -145,6 +160,7 @@ at1700_probe(struct device *dev)
 
        return ENODEV;
 }
+#endif
 
 /* The Fujitsu datasheet suggests that the NIC be probed for by checking its
    "signature", the default bit pattern after a reset.  This *doesn't* work --
@@ -156,29 +172,24 @@ at1700_probe(struct device *dev)
 
 int at1700_probe1(struct device *dev, short ioaddr)
 {
-       unsigned short signature[4]         = {0xffff, 0xffff, 0x7ff7, 0xff5f};
-       unsigned short signature_invalid[4] = {0xffff, 0xffff, 0x7ff7, 0xdf0f};
        char irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
-       unsigned short *station_address = (unsigned short *)dev->dev_addr;
        unsigned int i, irq;
 
        /* Resetting the chip doesn't reset the ISA interface, so don't bother.
           That means we have to be careful with the register values we probe for.
           */
-       for (i = 0; i < 4; i++)
-               if ((inw(ioaddr + 2*i) | signature_invalid[i]) != signature[i]) {
-                       if (net_debug > 2)
-                               printk("AT1700 signature match failed at %d (%04x vs. %04x)\n",
-                                          i, inw(ioaddr + 2*i), signature[i]);
-                       return -ENODEV;
-               }
-       if (read_eeprom(ioaddr, 4) != 0x0000
-               || read_eeprom(ioaddr, 5) & 0x00ff != 0x00F4)
+#ifdef notdef
+       printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n",
+                  ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5),
+                  read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl));
+#endif
+       if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr
+               || read_eeprom(ioaddr, 4) != 0x0000
+               || read_eeprom(ioaddr, 5) & 0xff00 != 0xF400)
                return -ENODEV;
 
-       /* Grab the region so that we can find another board if the IRQ request
-          fails. */
-       snarf_region(ioaddr, 32);
+       /* Reset the internal state machines. */
+       outb(0, ioaddr + RESET);
 
        irq = irqmap[(read_eeprom(ioaddr, 12)&0x04)
                                 | (read_eeprom(ioaddr, 0)>>14)];
@@ -190,6 +201,14 @@ int at1700_probe1(struct device *dev, short ioaddr)
                return EAGAIN;
        }
 
+       /* Allocate a new 'dev' if needed. */
+       if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct net_local), 0);
+
+       /* Grab the region so that we can find another board if the IRQ request
+          fails. */
+       snarf_region(ioaddr, AT1700_IO_EXTENT);
+
        printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name,
                   ioaddr, irq);
 
@@ -200,7 +219,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
        for(i = 0; i < 3; i++) {
                unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
                printk("%04x", eeprom_val);
-               station_address[i] = ntohs(eeprom_val);
+               ((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
        }
 
        /* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
@@ -214,8 +233,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
                ushort setup_value = read_eeprom(ioaddr, 12);
 
                dev->if_port = setup_value >> 8;
-               printk(" %s interface (%04x).\n", porttype[(dev->if_port>>3) & 3],
-                          setup_value);
+               printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
        }
 
        /* Set the station address in bank zero. */
@@ -243,7 +261,8 @@ int at1700_probe1(struct device *dev, short ioaddr)
                printk(version);
 
        /* Initialize the device structure. */
-       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+       if (dev->priv == NULL)
+               dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
        memset(dev->priv, 0, sizeof(struct net_local));
 
        dev->open               = net_open;
@@ -252,7 +271,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
        dev->get_stats  = net_get_stats;
        dev->set_multicast_list = &set_multicast_list;
 
-       /* Fill in the fields of the device structure with ethernet-generic values. */
+       /* Fill in the fields of 'dev' with ethernet-generic values. */
           
        ether_setup(dev);
        return 0;
@@ -400,7 +419,9 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
                        lp->tx_queue_len = 0;
                        dev->trans_start = jiffies;
                        lp->tx_started = 1;
-               } else if (lp->tx_queue_len < 4096 - 1502)      /* Room for one more packet? */
+                       dev->tbusy = 0;
+               } else if (lp->tx_queue_len < 4096 - 1502)
+                       /* Yes, there is room for one more packet. */
                        dev->tbusy = 0;
 
                /* Turn on Tx interrupts back on. */
@@ -453,10 +474,12 @@ net_interrupt(int reg_ptr)
                                /* Turn on Tx interrupts off. */
                                outb(0x00, ioaddr + TX_INTR);
                                dev->tbusy = 0;
+                               mark_bh(NET_BH);        /* Inform upper layers. */
                        }
                }
        }
 
+       dev->interrupt = 0;
        return;
 }
 
@@ -499,7 +522,7 @@ net_rx(struct device *dev)
                                lp->stats.rx_errors++;
                                break;
                        }
-                       skb = alloc_skb(pkt_len, GFP_ATOMIC);
+                       skb = alloc_skb(pkt_len+1, GFP_ATOMIC);
                        if (skb == NULL) {
                                printk("%s: Memory squeeze, dropping packet (len %d).\n",
                                           dev->name, pkt_len);
@@ -535,6 +558,7 @@ net_rx(struct device *dev)
                for (i = 0; i < 20; i++) {
                        if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
                                break;
+                       inw(ioaddr + DATAPORT);                         /* dummy status read */
                        outb(0x05, ioaddr + 14);
                }
 
@@ -592,9 +616,9 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
        short ioaddr = dev->base_addr;
        if (num_addrs) {
-               outw(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
+               outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
        } else
-               outw(2, ioaddr + RX_MODE);      /* Disable promiscuous, use normal mode */
+               outb(2, ioaddr + RX_MODE);      /* Disable promiscuous, use normal mode */
 }
 \f
 /*
@@ -603,5 +627,6 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
  *  version-control: t
  *  kept-new-versions: 5
  *  tab-width: 4
+ *  c-indent-level: 4
  * End:
  */
index 1efa2d069223fbca1c7508fa33188c66115b0d9d..0bab58cb133f4dccc8a71e2dec507e09733514a4 100644 (file)
@@ -1,9 +1,10 @@
 /* auto_irq.c: Auto-configure IRQ lines for linux. */
 /*
-    Written 1993 by Donald Becker.
+    Written 1994 by Donald Becker.
 
-    The Author may be reached as becker@super.org or
-    C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+    Center of Excellence in Space Data and Information Sciences
+      Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
     This code is a general-purpose IRQ line detector for devices with
     jumpered IRQ lines.  If you can make the device raise an IRQ (and
@@ -12,7 +13,7 @@
     device probes!
 
     To use this, first call autoirq_setup(timeout). TIMEOUT is how many
-    'jiffies' (1/18 sec.) to detect other devices that have active IRQ lines,
+    'jiffies' (1/100 sec.) to detect other devices that have active IRQ lines,
     and can usually be zero at boot.  'autoirq_setup()' returns the bit
     vector of nominally-available IRQ lines (lines may be physically in-use,
     but not yet registered to a device).
 
 
 #ifdef version
-static char *version="auto_irq.c:v0.02 1993 Donald Becker (becker@super.org)";
+static char *version=
+"auto_irq.c:v1.11 Donald Becker (becker@cesdis.gsfc.nasa.gov)";
 #endif
 
 /*#include <linux/config.h>*/
 /*#include <linux/kernel.h>*/
 #include <linux/sched.h>
+#include <linux/delay.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <linux/netdevice.h>
 /*#include <asm/system.h>*/
 
 struct device *irq2dev_map[16] = {0, 0, /* ... zeroed */};
 
-int irqs_busy = 0x01;          /* The set of fixed IRQs always enabled */
-int irqs_used = 0x01;          /* The set of fixed IRQs sometimes enabled. */
-int irqs_reserved = 0x00;      /* An advisory "reserved" table. */
-int irqs_shared = 0x00;                /* IRQ lines "shared" among conforming cards.*/
+int irqs_busy = 0x2147;                /* The set of fixed IRQs (keyboard, timer, etc) */
+int irqs_used = 0x0001;                /* The set of fixed IRQs sometimes enabled. */
+int irqs_reserved = 0x0000;    /* An advisory "reserved" table. */
+int irqs_shared = 0x0000;      /* IRQ lines "shared" among conforming cards.*/
 
 static volatile int irq_number;        /* The latest irq number we actually found. */
 static volatile int irq_bitmap; /* The irqs we actually found. */
@@ -53,56 +57,61 @@ static void autoirq_probe(int irq)
 {
        irq_number = irq;
        set_bit(irq, (void *)&irq_bitmap);      /* irq_bitmap |= 1 << irq; */
+       disable_irq(irq);
        return;
 }
 
 int autoirq_setup(int waittime)
 {
-    int i, mask;
-    int timeout = jiffies+waittime;
-
-    irq_handled = 0;
-    for (i = 0; i < 16; i++) {
-       if (!request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe"))
-           set_bit(i, (void *)&irq_handled);   /* irq_handled |= 1 << i;*/
-    }
-    /* Update our USED lists. */
-    irqs_used |= ~irq_handled;
-    irq_number = 0;
-    irq_bitmap = 0;
-
-    /* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
-    while (timeout > jiffies)
-       ;
-
-    for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) {
-       if (irq_bitmap & irq_handled & mask) {
-           irq_handled &= ~mask;
+       int i, mask;
+       int timeout = jiffies + waittime;
+       int boguscount = (waittime*loops_per_sec) / 100;
+
+       irq_handled = 0;
+       for (i = 0; i < 16; i++) {
+               if (test_bit(i, &irqs_busy) == 0
+                       && request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe") == 0)
+                       set_bit(i, (void *)&irq_handled);       /* irq_handled |= 1 << i;*/
+       }
+       /* Update our USED lists. */
+       irqs_used |= ~irq_handled;
+       irq_number = 0;
+       irq_bitmap = 0;
+
+       /* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
+       while (timeout > jiffies  &&  --boguscount > 0)
+               ;
+
+       for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) {
+               if (irq_bitmap & irq_handled & mask) {
+                       irq_handled &= ~mask;
 #ifdef notdef
-           printk(" Spurious interrupt on IRQ %d\n", i);
+                       printk(" Spurious interrupt on IRQ %d\n", i);
 #endif
-           free_irq(i);
+                       free_irq(i);
+               }
        }
-    }
-    return irq_handled;
+       return irq_handled;
 }
 
 int autoirq_report(int waittime)
 {
-    int i;
-    int timeout = jiffies+waittime;
-
-    /* Hang out at least <waittime> jiffies waiting for the IRQ. */
-    while (timeout > jiffies)
-       if (irq_number)
-           break;
-
-    /* Retract the irq handlers that we installed. */
-    for (i = 0; i < 16; i++) {
-       if (test_bit(i, (void *)&irq_handled))
-           free_irq(i);
-    }
-    return irq_number;
+       int i;
+       int timeout = jiffies+waittime;
+       int boguscount = (waittime*loops_per_sec) / 100;
+
+       /* Hang out at least <waittime> jiffies waiting for the IRQ. */
+
+       while (timeout > jiffies  &&  --boguscount > 0)
+               if (irq_number)
+                       break;
+
+       /* Retract the irq handlers that we installed. */
+       for (i = 0; i < 16; i++) {
+               if (test_bit(i, (void *)&irq_handled))
+                       free_irq(i);
+       }
+       return irq_number;
 }
 \f
 /*
@@ -110,5 +119,7 @@ int autoirq_report(int waittime)
  *  compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c"
  *  version-control: t
  *  kept-new-versions: 5
+ *  c-indent-level: 4
+ *  tab-width: 4
  * End:
  */
index d1c0077d0d71af769ef151002d9801147f024cf9..204eefc85f9ef1466527986c44567934224bffff 100644 (file)
@@ -19,7 +19,7 @@
 */
 
 static char *version =
-"hp-plus.c:v0.04 6/16/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+"hp-plus.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/config.h>
 #include <linux/string.h>              /* Important -- this inlines word moves. */
@@ -38,6 +38,12 @@ static char *version =
 #endif
 
 #include "8390.h"
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                                                       unsigned long *mem_startp);
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int hpplus_portlist[] =
+{0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}
 
 /*
    The HP EtherTwist chip implementation is a fairly routine DP8390
@@ -64,10 +70,6 @@ static char *version =
    register.
 */
 
-#define HPP_PROBE_LIST {0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}
-
-#define HP_IO_EXTENT   32
-
 #define HP_ID                  0x00    /* ID register, always 0x4850. */
 #define HP_PAGING              0x02    /* Registers visible @ 8-f, see PageName. */ 
 #define HPP_OPTION             0x04    /* Bitmapped options, see HP_Option.    */
@@ -75,6 +77,7 @@ static char *version =
 #define HPP_IN_ADDR            0x0A    /* I/O input location in Perf_Page.             */
 #define HP_DATAPORT            0x0c    /* I/O data transfer in Perf_Page.              */
 #define NIC_OFFSET             0x10    /* Offset to the 8390 registers.                */
+#define HP_IO_EXTENT   32
 
 #define HP_START_PG            0x00    /* First page of TX buffer */
 #define HP_STOP_PG             0x80    /* Last page +1 of RX ring */
@@ -111,26 +114,34 @@ static void hpp_io_block_output(struct device *dev, int count,
 \f
 /*     Probe a list of addresses for an HP LAN+ adaptor.
        This routine is almost boilerplate. */
+#ifdef HAVE_DEVLIST
+/* Support for a alternate probe manager, which will eliminate the
+   boilerplate below. */
+struct netdev_entry hpplus_drv =
+{"hpplus", hpp_probe1, HP_IO_EXTENT, hpplus_portlist};
+#else
 
 int hp_plus_probe(struct device *dev)
 {
-       int *port, ports[] = HPP_PROBE_LIST;
-       short ioaddr = dev->base_addr;
+       int i;
+       int base_addr = dev ? dev->base_addr : 0;
 
-       if (ioaddr > 0x1ff)                     /* Check a single specified location. */
-               return hpp_probe1(dev, ioaddr);
-       else if (ioaddr > 0)                            /* Don't probe at all. */
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return hpp_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
                return ENXIO;
 
-       for (port = &ports[0]; *port; port++) {
-               if (check_region(*port, HP_IO_EXTENT))
+       for (i = 0; hpplus_portlist[i]; i++) {
+               int ioaddr = hpplus_portlist[i];
+               if (check_region(ioaddr, HP_IO_EXTENT))
                        continue;
-               if (hpp_probe1(dev, *port) == 0) {
+               if (hpp_probe1(dev, ioaddr) == 0)
                        return 0;
-               }
        }
+
        return ENODEV;
 }
+#endif
 
 /* Do the interesting part of the probe at a single address. */
 int hpp_probe1(struct device *dev, int ioaddr)
@@ -138,7 +149,6 @@ int hpp_probe1(struct device *dev, int ioaddr)
        int i;
        unsigned char checksum = 0;
        char *name = "HP-PC-LAN+";
-       unsigned char *station_addr = dev->dev_addr;
        int mem_start;
 
        /* Check for the HP+ signature, 50 48 0x 53. */
@@ -146,7 +156,9 @@ int hpp_probe1(struct device *dev, int ioaddr)
                || (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300)
                return ENODEV;
 
-       /* OK, we think that we have it.  Get and checksum the physical address. */
+    if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct ei_device), 0);
+
        printk("%s: %s at %#3x,", dev->name, name, ioaddr);
 
        /* Retrieve and checksum the station address. */
@@ -154,7 +166,7 @@ int hpp_probe1(struct device *dev, int ioaddr)
 
        for(i = 0; i < ETHER_ADDR_LEN; i++) {
                unsigned char inval = inb(ioaddr + 8 + i);
-               station_addr[i] = inval;
+               dev->dev_addr[i] = inval;
                checksum += inval;
                printk(" %2.2x", inval);
        }
index 315a4f1c31c938e4e2803c70213228d31719c0fc..b76f590f46910dae8f5e6814fcc62f04296e24aa 100644 (file)
@@ -1,19 +1,25 @@
 /* hp.c: A HP LAN ethernet driver for linux. */
 /*
-       Written 1993 by Donald Becker.
+       Written 1993-94 by Donald Becker.
+
        Copyright 1993 United States Government as represented by the
-       Director, National Security Agency.      This software may be used and
-       distributed according to the terms of the GNU Public License,
-       incorporated herein by reference.
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
-       This is a driver for the HP LAN adaptors.
+       This is a driver for the HP PC-LAN adaptors.
 
-       The Author may be reached as becker@super.org or
-       C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+       Sources:
+         The Crynwr packet driver.
 */
 
 static char *version =
-       "hp.c:v0.99.15k 3/3/94 Donald Becker (becker@super.org)\n";
+       "hp.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -26,10 +32,12 @@ static char *version =
 #include <linux/netdevice.h>
 #include "8390.h"
 
-#ifndef HAVE_PORTRESERVE
-#define check_region(ioaddr, size)                             0
-#define snarf_region(ioaddr, size);                            do ; while (0)
-#endif
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                                                       unsigned long *mem_startp);
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int hppclan_portlist[] =
+{ 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
 
 #define HP_IO_EXTENT   32
 
@@ -46,7 +54,7 @@ static char *version =
 #define HP_16BSTOP_PG  0xFF    /* Same, for 16 bit cards. */
 
 int hp_probe(struct device *dev);
-int hpprobe1(struct device *dev, int ioaddr);
+int hp_probe1(struct device *dev, int ioaddr);
 
 static void hp_reset_8390(struct device *dev);
 static int hp_block_input(struct device *dev, int count,
@@ -63,32 +71,37 @@ static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
 /*     Probe for an HP LAN adaptor.
        Also initialize the card and fill in STATION_ADDR with the station
        address. */
+#ifdef HAVE_DEVLIST
+struct netdev_entry netcard_drv =
+{"hp", hp_probe1, HP_IO_EXTENT, hppclan_portlist};
+#else
 
 int hp_probe(struct device *dev)
 {
-       int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
-       short ioaddr = dev->base_addr;
+       int i;
+       int base_addr = dev ? dev->base_addr : 0;
 
-       if (ioaddr > 0x1ff)                     /* Check a single specified location. */
-               return hpprobe1(dev, ioaddr);
-       else if (ioaddr > 0)                            /* Don't probe at all. */
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return hp_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
                return ENXIO;
 
-       for (port = &ports[0]; *port; port++) {
-               if (check_region(*port, HP_IO_EXTENT))
+       for (i = 0; hppclan_portlist[i]; i++) {
+               int ioaddr = hppclan_portlist[i];
+               if (check_region(ioaddr, HP_IO_EXTENT))
                        continue;
-               if (hpprobe1(dev, *port) == 0) {
+               if (hp_probe1(dev, ioaddr) == 0)
                        return 0;
-               }
        }
+
        return ENODEV;
 }
+#endif
 
-int hpprobe1(struct device *dev, int ioaddr)
+int hp_probe1(struct device *dev, int ioaddr)
 {
        int i, board_id, wordmode;
        char *name;
-       unsigned char *station_addr = dev->dev_addr;
 
        /* Check for the HP physical address, 08 00 09 xx xx xx. */
        /* This really isn't good enough: we may pick up HP LANCE boards
@@ -100,7 +113,7 @@ int hpprobe1(struct device *dev, int ioaddr)
                return ENODEV;
 
        /* Set up the parameters based on the board ID.
-          If you have additional mappings, please mail them to becker@super.org. */
+          If you have additional mappings, please mail them to me -djb. */
        if ((board_id = inb(ioaddr + HP_ID)) & 0x80) {
                name = "HP27247";
                wordmode = 1;
@@ -109,13 +122,16 @@ int hpprobe1(struct device *dev, int ioaddr)
                wordmode = 0;
        }
 
+       if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct ei_device), 0);
+
        /* Grab the region so we can find another board if something fails. */
        snarf_region(ioaddr, HP_IO_EXTENT);
 
        printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr);
 
        for(i = 0; i < ETHER_ADDR_LEN; i++)
-               printk(" %2.2x", station_addr[i] = inb(ioaddr + i));
+               printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
 
        /* Snarf the interrupt now.  Someday this could be moved to open(). */
        if (dev->irq < 2) {
index ff69b4247152a7103bf037e77c8dcdf184d6f87a..7be5877f2edff6e841d6cb5adbd82bb3f00879ad 100644 (file)
@@ -15,7 +15,7 @@
           Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 */
 
-static char *version = "lance.c:v1.01 8/31/94 becker@cesdis.gsfc.nasa.gov\n";
+static char *version = "lance.c:v1.05 9/23/94 becker@cesdis.gsfc.nasa.gov\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -72,7 +72,7 @@ have on-board buffer memory needed to support the slower shared memory mode.)
 Most ISA boards have jumpered settings for the I/O base, IRQ line, and DMA
 channel.  This driver probes the likely base addresses:
 {0x300, 0x320, 0x340, 0x360}.
-After the board is found it generates a DMA-timeout interrupt and uses
+After the board is found it generates an DMA-timeout interrupt and uses
 autoIRQ to find the IRQ line.  The DMA channel can be set with the low bits
 of the otherwise-unused dev->mem_start value (aka PARAM1).  If unset it is
 probed for by enabling each free DMA channel in turn and checking if
@@ -102,14 +102,14 @@ statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to
 avoid the administrative overhead. For the Rx side this avoids dynamically
 allocating full-sized buffers "just in case", at the expense of a
 memory-to-memory data copy for each packet received.  For most systems this
-is a good tradeoff: the Rx buffer will always be in low memory, the copy
+is an good tradeoff: the Rx buffer will always be in low memory, the copy
 is inexpensive, and it primes the cache for later packet processing.  For Tx
 the buffers are only used when needed as low-memory bounce buffers.
 
 IIIB. 16M memory limitations.
 For the ISA bus master mode all structures used directly by the LANCE,
 the initialization block, Rx and Tx rings, and data buffers, must be
-accessible from the ISA bus, i.e. in the lower 16M of real memory.
+accessable from the ISA bus, i.e. in the lower 16M of real memory.
 This is a problem for current Linux kernels on >16M machines. The network
 devices are initialized after memory initialization, and the kernel doles out
 memory from the top of memory downward.         The current solution is to have a
@@ -170,7 +170,7 @@ struct lance_rx_head {
 };
 
 struct lance_tx_head {
-       int base;
+       int       base;
        short length;                           /* Length is 2s complement (negative)! */
        short misc;
 };
@@ -206,16 +206,18 @@ struct lance_private {
        int pad0, pad1;                         /* Used for 8-byte alignment */
 };
 
-/* A mapping from the chip ID number to the part number and features. */
+/* A mapping from the chip ID number to the part number and features.
+   These are fro the datasheets -- in real life the '970 version
+   reportedly has the same ID as the '965. */
 static struct lance_chip_type {
        int id_number;
        char *name;
        int flags;
 } chip_table[] = {
-       {0x0000, "LANCE 7990", 0},              /* Ancient lance chip.  */
+       {0x0000, "LANCE 7990", 0},                      /* Ancient lance chip.  */
        {0x0003, "PCnet/ISA 79C960", 0},        /* 79C960 PCnet/ISA.  */
-       {0x2260, "PCnet/ISA+ 79C961", 0},       /* 79C961 PCnet/ISA+ for Plug-n-Play.  */
-       {0x2420, "PCnet/PCI 79C970", 0},        /* 79C970 or 79C974 PCnet-SCSI for PCI  */
+       {0x2260, "PCnet/ISA+ 79C961", 0},       /* 79C961 PCnet/ISA+, Plug-n-Play.  */
+       {0x2420, "PCnet/PCI 79C970", 0},        /* 79C970 or 79C974 PCnet-SCSI, PCI. */
        {0x2430, "PCnet/VLB 79C965", 0},        /* 79C965 PCnet for VL bus. */
        {0x0,    "PCnet (unknown)", 0},
 };
@@ -237,7 +239,7 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 
 /* This lance probe is unlike the other board probes in 1.0.*.  The LANCE may
    have to allocate a contiguous low-memory region for bounce buffers.
-   This requirement is satisfied by having the lance initialization occur before the
+   This requirement is satified by having the lance initialization occur before the
    memory management system is started, and thus well before the other probes. */
 unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
 {
@@ -260,6 +262,7 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
 {
        struct device *dev;
        struct lance_private *lp;
+       short dma_channels;                                     /* Mark spuriously-busy DMA channels */
        int i, reset_val, lance_version;
        /* Flags for specific chips or boards. */
        unsigned char hpJ2405A = 0;                                             /* HP ISA adaptor */
@@ -268,18 +271,18 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
 
        /* First we look for special cases.
           Check for HP's on-board ethernet by looking for 'HP' in the BIOS.
-          This method provided by Laurent Julliard, Laurent_Julliard@grenoble.hp.com.
+          There are two HP versions, check the BIOS for the configuration port.
+          This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com.
           */
        if ( *((unsigned short *) 0x000f0102) == 0x5048)  {
                short ioaddr_table[] = { 0x300, 0x320, 0x340, 0x360};
-               /* There are two HP versions, check the BIOS for the configuration port. */
                int hp_port = ( *((unsigned char *) 0x000f00f1) & 1)  ? 0x499 : 0x99;
                /* We can have boards other than the built-in!  Verify this is on-board. */
                if ((inb(hp_port) & 0xc0) == 0x80
                        && ioaddr_table[inb(hp_port) & 3] == ioaddr)
                        hp_builtin = hp_port;
        }
-       /* We might misrecognize the HP Vectra on-board here, but we check below. */
+       /* We also recognize the HP Vectra on-board here, but check below. */
        hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00
                                && inb(ioaddr+2) == 0x09);
 
@@ -388,6 +391,12 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
                        dev->dma = dev->mem_start & 0x07;
        }
 
+       if (dev->dma == 0) {
+               /* Read the DMA channel status register, so that we can avoid
+                  stuck DMA channels in the DMA detection below. */
+               dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
+                       (inb(DMA2_STAT_REG) & 0xf0);
+       }
        if (dev->irq >= 2)
                printk(" assigned IRQ %d", dev->irq);
        else {
@@ -422,15 +431,20 @@ unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
                } else
                        printk(", assigned DMA %d.\n", dev->dma);
        } else {                        /* OK, we have to auto-DMA. */
-               int dmas[] = {5, 6, 7, 3}, boguscnt;
+               int dmas[] = { 5, 6, 7, 3 }, boguscnt;
+
                for (i = 0; i < 4; i++) {
                        int dma = dmas[i];
 
+                       /* Don't enable a permanently busy DMA channel, or the machine
+                          will hang. */
+                       if (test_bit(dma, &dma_channels))
+                               continue;
                        outw(0x7f04, ioaddr+LANCE_DATA); /* Clear the memory error bits. */
                        if (request_dma(dma, "lance"))
                                continue;
-                       enable_dma(dma);
                        set_dma_mode(dma, DMA_MODE_CASCADE);
+                       enable_dma(dma);
 
                        /* Trigger an initialization. */
                        outw(0x0001, ioaddr+LANCE_DATA);
@@ -493,8 +507,10 @@ lance_open(struct device *dev)
        inw(ioaddr+LANCE_RESET);
 
        /* The DMA controller is used as a no-operation slave, "cascade mode". */
-       enable_dma(dev->dma);
-       set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+       if (dev->dma != 4) {
+               enable_dma(dev->dma);
+               set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+       }
 
        /* Un-Reset the LANCE, needed only for the NE2100. */
        if (lp->chip_version == OLD_LANCE)
@@ -580,24 +596,25 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
        /* Transmitter timeout, serious problems. */
        if (dev->tbusy) {
                int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 10)
+               if (tickssofar < 20)
                        return 1;
                outw(0, ioaddr+LANCE_ADDR);
                printk("%s: transmit timed out, status %4.4x, resetting.\n",
                           dev->name, inw(ioaddr+LANCE_DATA));
-               outw(0x0001, ioaddr+LANCE_DATA);
+               outw(0x0004, ioaddr+LANCE_DATA);
                lp->stats.tx_errors++;
 #ifndef final_version
                {
                        int i;
-                       printk(" Ring data dump: dirty_tx %d cur_tx %d cur_rx %d.",
-                                  lp->dirty_tx, lp->cur_tx, lp->cur_rx);
+                       printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
+                                  lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
+                                  lp->cur_rx);
                        for (i = 0 ; i < RX_RING_SIZE; i++)
                                printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
                                           lp->rx_ring[i].base, -lp->rx_ring[i].buf_length,
                                           lp->rx_ring[i].msg_length);
                        for (i = 0 ; i < TX_RING_SIZE; i++)
-                               printk(" %s%08x %04x %04x", i & 0x3 ? "" : "\n ",
+                               printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
                                           lp->tx_ring[i].base, -lp->tx_ring[i].length,
                                           lp->tx_ring[i].misc);
                        printk("\n");
@@ -635,7 +652,7 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
        }
 
        if (set_bit(0, (void*)&lp->lock) != 0) {
-               if (lance_debug > 2)
+               if (lance_debug > 0)
                        printk("%s: tx queue lock!.\n", dev->name);
                /* don't clear dev->tbusy flag. */
                return 1;
@@ -698,7 +715,7 @@ lance_interrupt(int reg_ptr)
        int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
        struct device *dev = (struct device *)(irq2dev_map[irq]);
        struct lance_private *lp;
-       int csr0, ioaddr;
+       int csr0, ioaddr, boguscnt=10;
 
        if (dev == NULL) {
                printk ("lance_interrupt(): irq %d for unknown device.\n", irq);
@@ -713,79 +730,94 @@ lance_interrupt(int reg_ptr)
        dev->interrupt = 1;
 
        outw(0x00, dev->base_addr + LANCE_ADDR);
-       csr0 = inw(dev->base_addr + LANCE_DATA);
-
-       /* Acknowledge all of the current interrupt sources ASAP. */
-       outw(csr0 & ~0x004f, dev->base_addr + LANCE_DATA);
+       while ((csr0 = inw(dev->base_addr + LANCE_DATA)) & 0x8600
+                  && --boguscnt >= 0) {
+               /* Acknowledge all of the current interrupt sources ASAP. */
+               outw(csr0 & ~0x004f, dev->base_addr + LANCE_DATA);
 
-       if (lance_debug > 5)
-               printk("%s: interrupt  csr0=%#2.2x new csr=%#2.2x.\n",
-                          dev->name, csr0, inw(dev->base_addr + LANCE_DATA));
+               if (lance_debug > 5)
+                       printk("%s: interrupt  csr0=%#2.2x new csr=%#2.2x.\n",
+                                  dev->name, csr0, inw(dev->base_addr + LANCE_DATA));
 
-       if (csr0 & 0x0400)                      /* Rx interrupt */
-               lance_rx(dev);
+               if (csr0 & 0x0400)                      /* Rx interrupt */
+                       lance_rx(dev);
 
-       if (csr0 & 0x0200) {            /* Tx-done interrupt */
-               int dirty_tx = lp->dirty_tx;
+               if (csr0 & 0x0200) {            /* Tx-done interrupt */
+                       int dirty_tx = lp->dirty_tx;
 
-               while (dirty_tx < lp->cur_tx) {
-                       int entry = dirty_tx & TX_RING_MOD_MASK;
-                       int status = lp->tx_ring[entry].base;
+                       while (dirty_tx < lp->cur_tx) {
+                               int entry = dirty_tx & TX_RING_MOD_MASK;
+                               int status = lp->tx_ring[entry].base;
                        
-                       if (status < 0)
-                               break;                  /* It still hasn't been Txed */
-
-                       lp->tx_ring[entry].base = 0;
-
-                       if (status & 0x40000000) { /* There was a major error, log it. */
-                               int err_status = lp->tx_ring[entry].misc;
-                               lp->stats.tx_errors++;
-                               if (err_status & 0x0400) lp->stats.tx_aborted_errors++;
-                               if (err_status & 0x0800) lp->stats.tx_carrier_errors++;
-                               if (err_status & 0x1000) lp->stats.tx_window_errors++;
-                               if (err_status & 0x4000) lp->stats.tx_fifo_errors++;
-                               /* Perhaps we should re-init() after the FIFO error. */
-                       } else {
-                               if (status & 0x18000000)
-                                       lp->stats.collisions++;
-                               lp->stats.tx_packets++;
-                       }
+                               if (status < 0)
+                                       break;                  /* It still hasn't been Txed */
+
+                               lp->tx_ring[entry].base = 0;
+
+                               if (status & 0x40000000) {
+                                       /* There was an major error, log it. */
+                                       int err_status = lp->tx_ring[entry].misc;
+                                       lp->stats.tx_errors++;
+                                       if (err_status & 0x0400) lp->stats.tx_aborted_errors++;
+                                       if (err_status & 0x0800) lp->stats.tx_carrier_errors++;
+                                       if (err_status & 0x1000) lp->stats.tx_window_errors++;
+                                       if (err_status & 0x4000) {
+                                               /* Ackk!  On FIFO errors the Tx unit is turned off! */
+                                               lp->stats.tx_fifo_errors++;
+                                               /* Remove this verbosity later! */
+                                               printk("%s: Tx FIFO error! Status %4.4x.\n",
+                                                          dev->name, csr0);
+                                               /* Restart the chip. */
+                                               outw(0x0002, dev->base_addr + LANCE_DATA);
+                                       }
+                               } else {
+                                       if (status & 0x18000000)
+                                               lp->stats.collisions++;
+                                       lp->stats.tx_packets++;
+                               }
 
-                       /* We must free the original skb if it's not a data-only copy
-                          in the bounce buffer. */
-                       if (lp->tx_skbuff[entry]) {
-                               dev_kfree_skb(lp->tx_skbuff[entry],FREE_WRITE);
-                               lp->tx_skbuff[entry] = 0;
+                               /* We must free the original skb if it's not a data-only copy
+                                  in the bounce buffer. */
+                               if (lp->tx_skbuff[entry]) {
+                                       dev_kfree_skb(lp->tx_skbuff[entry],FREE_WRITE);
+                                       lp->tx_skbuff[entry] = 0;
+                               }
+                               dirty_tx++;
                        }
-                       dirty_tx++;
-               }
 
 #ifndef final_version
-               if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
-                       printk("out-of-sync dirty pointer, %d vs. %d.\n",
-                                  dirty_tx, lp->cur_tx);
-                       dirty_tx += TX_RING_SIZE;
-               }
+                       if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
+                               printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+                                          dirty_tx, lp->cur_tx, lp->tx_full);
+                               dirty_tx += TX_RING_SIZE;
+                       }
 #endif
 
-               if (lp->tx_full && dev->tbusy && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
-                       /* The ring is no longer full, clear tbusy. */
-                       lp->tx_full = 0;
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);
-               }
+                       if (lp->tx_full && dev->tbusy
+                               && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+                               /* The ring is no longer full, clear tbusy. */
+                               lp->tx_full = 0;
+                               dev->tbusy = 0;
+                               mark_bh(NET_BH);
+                       }
 
-               lp->dirty_tx = dirty_tx;
-       }
+                       lp->dirty_tx = dirty_tx;
+               }
 
-       if (csr0 & 0x8000) {            /* Check the error summary bit. */
+               /* Log misc errors. */
                if (csr0 & 0x4000) lp->stats.tx_errors++; /* Tx babble. */
                if (csr0 & 0x1000) lp->stats.rx_errors++; /* Missed a Rx frame. */
+               if (csr0 & 0x0800) {
+                       printk("%s: Bus master arbitration failure, status %4.4x.\n",
+                                  dev->name, csr0);
+                       /* Restart the chip. */
+                       outw(0x0002, dev->base_addr + LANCE_DATA);
+               }
        }
 
-    /* Clear any other interrupt. */
+    /* Clear any other interrupt, and set interrupt enable. */
     outw(0x0000, dev->base_addr + LANCE_ADDR);
-    outw(0x7f40, dev->base_addr + LANCE_DATA);
+    outw(0x7940, dev->base_addr + LANCE_DATA);
 
        if (lance_debug > 4)
                printk("%s: exiting interrupt, csr%d=%#4.4x.\n",
@@ -808,7 +840,7 @@ lance_rx(struct device *dev)
                int status = lp->rx_ring[entry].base >> 24;
 
                if (status != 0x03) {                   /* There was an error. */
-                       /* There is a tricky error noted by John Murphy,
+                       /* There is an tricky error noted by John Murphy,
                           <murf@perftech.com> to Russ Nelson: Even with full-sized
                           buffers it's possible for a jabber packet to use two
                           buffers, with only the last correctly noting the error. */
@@ -847,10 +879,10 @@ lance_rx(struct device *dev)
                        lp->stats.rx_packets++;
                }
 
-               lp->rx_ring[entry].base |= 0x80000000;
                /* The docs say that the buffer length isn't touched, but Andrew Boyd
                   of QNX reports that some revs of the 79C965 clear it. */
                lp->rx_ring[entry].buf_length = -PKT_BUF_SZ;
+               lp->rx_ring[entry].base |= 0x80000000;
                entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
        }
 
@@ -869,9 +901,10 @@ lance_close(struct device *dev)
        dev->start = 0;
        dev->tbusy = 1;
 
-       outw(112, ioaddr+LANCE_ADDR);
-       lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA);
-
+       if (lp->chip_version != OLD_LANCE) {
+               outw(112, ioaddr+LANCE_ADDR);
+               lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA);
+       }
        outw(0, ioaddr+LANCE_ADDR);
 
        if (lance_debug > 1)
@@ -882,7 +915,8 @@ lance_close(struct device *dev)
           memory if we don't. */
        outw(0x0004, ioaddr+LANCE_DATA);
 
-       disable_dma(dev->dma);
+       if (dev->dma != 4)
+               disable_dma(dev->dma);
 
        free_irq(dev->irq);
 
@@ -898,12 +932,14 @@ lance_get_stats(struct device *dev)
        short ioaddr = dev->base_addr;
        short saved_addr;
 
-       cli();
-       saved_addr = inw(ioaddr+LANCE_ADDR);
-       outw(112, ioaddr+LANCE_ADDR);
-       lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA);
-       outw(saved_addr, ioaddr+LANCE_ADDR);
-       sti();
+       if (lp->chip_version != OLD_LANCE) {
+               cli();
+               saved_addr = inw(ioaddr+LANCE_ADDR);
+               outw(112, ioaddr+LANCE_ADDR);
+               lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA);
+               outw(saved_addr, ioaddr+LANCE_ADDR);
+               sti();
+       }
 
        return &lp->stats;
 }
index 20908d6058964be352eb0ea86200424eb6057ab1..4927dfedbe5d4ce8d3090192e8cea70666988972 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Donald Becker, <becker@super.org>
+ *             Donald Becker, <becker@cesdis.gsfc.nasa.gov>
  *
  *             Alan Cox        :       Fixed oddments for NET3.014
  *
index c86d82ebc2a56d71e1e9b7bdc9cad6e60f5709f4..425d00f12737468bbcfbd39f05fdea73896d598d 100644 (file)
@@ -1,23 +1,26 @@
 /* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
 /*
-    Written 1992,1993 by Donald Becker.
+    Written 1992-94 by Donald Becker.
 
     Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU Public License,
-    incorporated herein by reference.
+    Director, National Security Agency.
 
-    This driver should work with many 8390-based ethernet boards.  Currently
-    it support the NE1000, NE2000, clones, and some Cabletron products.
+    This software may be used and distributed according to the terms
+    of the GNU Public License, incorporated herein by reference.
 
-    The Author may be reached as becker@super.org or
-    C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+    Center of Excellence in Space Data and Information Sciences
+        Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+    This driver should work with many programmed-I/O 8390-based ethernet
+    boards.  Currently it support the NE1000, NE2000, many clones,
+    and some Cabletron products.
 */
 
 /* Routines for the NatSemi-based designs (NE[12]000). */
 
 static char *version =
-    "ne.c:v0.99-15k 3/3/94 Donald Becker (becker@super.org)\n";
+    "ne.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -28,11 +31,28 @@ static char *version =
 
 #include <linux/netdevice.h>
 #include "8390.h"
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                   unsigned long *mem_startp);
+
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int netcard_portlist[] =
+{ 0x300, 0x280, 0x320, 0x340, 0x360, 0};
+
+/* A list of bad clones that we none-the-less recognize. */
+static struct { char *name8, *name16; unsigned char SAprefix[4];}
+bad_clone_list[] = {
+    {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
+    {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
+    {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh?  */
+    {0,}
+};
 
 #define NE_BASE         (dev->base_addr)
 #define NE_CMD         0x00
 #define NE_DATAPORT    0x10    /* NatSemi-defined port window offset. */
 #define NE_RESET       0x1f    /* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT   0x20
 
 #define NE1SM_START_PG 0x20    /* First page of TX buffer */
 #define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
@@ -40,7 +60,7 @@ static char *version =
 #define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
 
 int ne_probe(struct device *dev);
-static int neprobe1(int ioaddr, struct device *dev, int verbose);
+static int ne_probe1(struct device *dev, int ioaddr);
 
 static void ne_reset_8390(struct device *dev);
 static int ne_block_input(struct device *dev, int count,
@@ -70,44 +90,47 @@ static void ne_block_output(struct device *dev, const int count,
        E2010    starts at 0x100 and ends at 0x4000.
        E2010-x starts at 0x100 and ends at 0xffff.  */
 
+#ifdef HAVE_DEVLIST
+struct netdev_entry netcard_drv =
+{"ne", ne_probe1, NE_IO_EXTENT, netcard_portlist};
+#else
+
 int ne_probe(struct device *dev)
 {
-    int *port, ports[] = {0x300, 0x280, 0x320, 0x340, 0x360, 0};
-    short ioaddr = dev->base_addr;
+    int i;
+    int base_addr = dev ? dev->base_addr : 0;
 
-    if (ioaddr < 0)
-       return ENXIO;           /* Don't probe at all. */
-    if (ioaddr > 0x100)
-       return ! neprobe1(ioaddr, dev, 1);
+    if (base_addr > 0x1ff)     /* Check a single specified location. */
+       return ne_probe1(dev, base_addr);
+    else if (base_addr != 0)   /* Don't probe at all. */
+       return ENXIO;
 
-    for (port = &ports[0]; *port; port++) {
-#ifdef HAVE_PORTRESERVE
-       if (check_region(*port, 32))
+    for (i = 0; netcard_portlist[i]; i++) {
+       int ioaddr = netcard_portlist[i];
+       if (check_region(ioaddr, NE_IO_EXTENT))
            continue;
-#endif
-       if (inb_p(*port) != 0xff && neprobe1(*port, dev, 0)) {
-           dev->base_addr = *port;
+       if (ne_probe1(dev, ioaddr) == 0)
            return 0;
-       }
     }
-    dev->base_addr = ioaddr;
+
     return ENODEV;
 }
+#endif
 
-static int neprobe1(int ioaddr, struct device *dev, int verbose)
+static int ne_probe1(struct device *dev, int ioaddr)
 {
     int i;
     unsigned char SA_prom[32];
     int wordlength = 2;
-    char *name;
+    char *name = NULL;
     int start_page, stop_page;
-    int neX000, ctron, dlink, dfi;
+    int neX000, ctron;
     int reg0 = inb(ioaddr);
 
     if ( reg0 == 0xFF)
-       return 0;
+       return ENODEV;
 
-    /* Do a quick preliminary check that we have a 8390. */
+    /* Do a preliminary verification that we have a 8390. */
     {  int regd;
        outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
        regd = inb_p(ioaddr + 0x0d);
@@ -117,14 +140,13 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
        if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
            outb_p(reg0, ioaddr);
            outb(regd, ioaddr + 0x0d);  /* Restore the old values. */
-           return 0;
+           return ENODEV;
        }
     }
 
     printk("NE*000 ethercard probe at %#3x:", ioaddr);
 
-    /* Read the 16 bytes of station address prom, returning 1 for
-       an eight-bit interface and 2 for a 16-bit interface.
+    /* Read the 16 bytes of station address PROM.
        We must first initialize registers, similar to NS8390_init(eifdev, 0).
        We can't reliably read the SAPROM address without this.
        (I learned the hard way!). */
@@ -162,44 +184,54 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
        /* Un-double the SA_prom values. */
        for (i = 0; i < 16; i++)
            SA_prom[i] = SA_prom[i+i];
+       start_page = NESM_START_PG;
+       stop_page = NESM_STOP_PG;
+    } else {
+       start_page = NE1SM_START_PG;
+       stop_page = NE1SM_STOP_PG;
     }
 
-#if defined(show_all_SAPROM)
-    /* If your ethercard isn't detected define this to see the SA_PROM. */
-    for(i = 0; i < sizeof(SA_prom); i++)
-       printk(" %2.2x", SA_prom[i]);
-#else
     for(i = 0; i < ETHER_ADDR_LEN; i++) {
        dev->dev_addr[i] = SA_prom[i];
        printk(" %2.2x", SA_prom[i]);
     }
-#endif
 
     neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
     ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
-    dlink =  (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01);
-    dfi   =  (SA_prom[0] == 'D' && SA_prom[1] == 'F' && SA_prom[2] == 'I');
 
     /* Set up the rest of the parameters. */
-    if (neX000 || dlink || dfi) {
-       if (wordlength == 2) {
-           name = dlink ? "DE200" : "NE2000";
-           start_page = NESM_START_PG;
-           stop_page = NESM_STOP_PG;
-       } else {
-           name = dlink ? "DE100" : "NE1000";
-           start_page = NE1SM_START_PG;
-           stop_page = NE1SM_STOP_PG;
-       }
+    if (neX000) {
+       name = (wordlength == 2) ? "NE2000" : "NE1000";
     } else if (ctron) {
        name = "Cabletron";
        start_page = 0x01;
        stop_page = (wordlength == 2) ? 0x40 : 0x20;
     } else {
-       printk(" not found.\n");
-       return 0;
+       /* Ack!  Well, there might be a *bad* NE*000 clone there.
+          Check for total bogus addresses. */
+       for (i = 0; bad_clone_list[i].name8; i++) {
+           if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
+               SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
+               SA_prom[2] == bad_clone_list[i].SAprefix[2]) {
+               if (wordlength == 2) {
+                   name = bad_clone_list[i].name16;
+               } else {
+                   name = bad_clone_list[i].name8;
+               }
+               break;
+           }
+       }
+       if (bad_clone_list[i].name8 == NULL) {
+           printk(" not found (invalid signature %2.2x %2.2x).\n",
+                  SA_prom[14], SA_prom[15]);
+           return ENXIO;
+       }
     }
 
+
+    if (dev == NULL)
+       dev = init_etherdev(0, sizeof(struct ei_device), 0);
+
     if (dev->irq < 2) {
        autoirq_setup(0);
        outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
@@ -221,15 +253,16 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
        int irqval = request_irq (dev->irq, ei_interrupt, 0, "ne");
        if (irqval) {
            printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
-           return 0;
+           return EAGAIN;
        }
     }
 
     dev->base_addr = ioaddr;
 
-#ifdef HAVE_PORTRESERVE
-    snarf_region(ioaddr, 32);
-#endif
+    snarf_region(ioaddr, NE_IO_EXTENT);
+
+    for(i = 0; i < ETHER_ADDR_LEN; i++)
+       dev->dev_addr[i] = SA_prom[i];
 
     ethdev_init(dev);
     printk("\n%s: %s found at %#x, using IRQ %d.\n",
@@ -253,7 +286,7 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
     ei_status.block_input = &ne_block_input;
     ei_status.block_output = &ne_block_output;
     NS8390_init(dev, 0);
-    return dev->base_addr;
+    return 0;
 }
 
 /* Hard reset the card.  This used to pause for the same period that a
@@ -289,9 +322,10 @@ ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
 
     if (ei_status.dmaing) {
        if (ei_debug > 0)
-           printk("%s: DMAing conflict in ne_block_input."
-                  "[DMAstat:%1x][irqlock:%1x]\n",
-                  dev->name, ei_status.dmaing, ei_status.irqlock);
+           printk("%s: DMAing conflict in ne_block_input "
+                  "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+                  dev->name, ei_status.dmaing, ei_status.irqlock,
+                  dev->interrupt);
        return 0;
     }
     ei_status.dmaing |= 0x01;
@@ -348,8 +382,9 @@ ne_block_output(struct device *dev, int count,
     if (ei_status.dmaing) {
        if (ei_debug > 0)
            printk("%s: DMAing conflict in ne_block_output."
-                  "[DMAstat:%1x][irqlock:%1x]\n",
-                  dev->name, ei_status.dmaing, ei_status.irqlock);
+                  "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+                  dev->name, ei_status.dmaing, ei_status.irqlock,
+                  dev->interrupt);
        return;
     }
     ei_status.dmaing |= 0x02;
index b0f037cc3c4b69be80266f9db97b3a61609cbe05..a78dbf3f149ebd80003a796e0157bcf88d7cb833 100644 (file)
@@ -1,13 +1,10 @@
 /* netdrv_init.c: Initialization for network devices. */
 /*
-       Written 1993 by Donald Becker.
-       Copyright 1993 United States Government as represented by the Director,
-       National Security Agency.  This software may only be used and distributed
-       according to the terms of the GNU Public License as modified by SRC,
-       incorporated herein by reference.
+       Written 1993,1994 by Donald Becker.
 
-       The author may be reached as becker@super.org or
-       C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+       The author may be reached as becker@cesdis.gsfc.nasa.gov or
+       C/O Center of Excellence in Space Data and Information Sciences
+               Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
        This file contains the initialization for the "pl14+" style ethernet
        drivers.  It should eventually replace most of drivers/net/Space.c.
@@ -94,8 +91,11 @@ init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp)
        int i;
 
        if (dev == NULL) {
-               int alloc_size = sizeof(struct device) + sizeof("eth%d   ")
-                       + sizeof_private;
+               int alloc_size = sizeof(struct device) + sizeof("eth%d  ")
+                       + sizeof_private + 3;
+
+               alloc_size &= ~3;               /* Round to dword boundary. */
+
                if (mem_startp && *mem_startp ) {
                        dev = (struct device *)*mem_startp;
                        *mem_startp += alloc_size;
index 34325ab8576a3b777f09cb4eeb632ea79fd019e2..490e1c83c2045aee38e64f0ba46fcf5a694ef15e 100644 (file)
@@ -1,13 +1,16 @@
-/* skeleton.c: A sample network driver core for linux. */
+/* skeleton.c: A network driver outline for linux. */
 /*
-       Written 1993 by Donald Becker.
-       Copyright 1993 United States Government as represented by the Director,
-       National Security Agency.  This software may only be used and distributed
-       according to the terms of the GNU Public License as modified by SRC,
-       incorporated herein by reference.
+       Written 1993-94 by Donald Becker.
 
-       The author may be reached as becker@super.org or
-       C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
        This file is an outline for writing a network device driver for the
        the Linux operating system.
@@ -19,7 +22,7 @@
 */
 
 static char *version =
-       "skeleton.c:v0.05 11/16/93 Donald Becker (becker@super.org)\n";
+       "skeleton.c:v1.51 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 /* Always include 'config.h' first in case the user wants to turn on
    or override something. */
@@ -59,20 +62,13 @@ static char *version =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                                                       unsigned long *mem_startp);
 
-#ifndef HAVE_AUTOIRQ
-/* From auto_irq.c, in ioport.h for later versions. */
-extern void autoirq_setup(int waittime);
-extern int autoirq_report(int waittime);
-/* The map from IRQ number (as passed to the interrupt handler) to
-   'struct device'. */
-extern struct device *irq2dev_map[16];
-#endif
-
-#ifndef HAVE_PORTRESERVE
-#define check_region(ioaddr, size)             0
-#define        snarf_region(ioaddr, size);             do ; while (0)
-#endif
+/* First, a few definitions that the brave might change. */
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int netcard_portlist[] =
+   { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
@@ -80,15 +76,15 @@ extern struct device *irq2dev_map[16];
 #endif
 static unsigned int net_debug = NET_DEBUG;
 
+/* The number of low I/O ports used by the ethercard. */
+#define NETCARD_IO_EXTENT      32
+
 /* Information that need to be kept for each board. */
 struct net_local {
        struct enet_statistics stats;
        long open_time;                         /* Useless example local info. */
 };
 
-/* The number of low I/O ports used by the ethercard. */
-#define ETHERCARD_TOTAL_SIZE   16
-
 /* The station (ethernet) address prefix, used for IDing the board. */
 #define SA_ADDR0 0x00
 #define SA_ADDR1 0x42
@@ -98,7 +94,7 @@ struct net_local {
 
 extern int netcard_probe(struct device *dev);
 
-static int netcard_probe1(struct device *dev, short ioaddr);
+static int netcard_probe1(struct device *dev, int ioaddr);
 static int net_open(struct device *dev);
 static int     net_send_packet(struct sk_buff *skb, struct device *dev);
 static void net_interrupt(int reg_ptr);
@@ -119,54 +115,75 @@ extern void chipset_init(struct device *dev, int startp);
    If dev->base_addr == 2, allocate space for the device and return success
    (detachable devices only).
    */
+#ifdef HAVE_DEVLIST
+/* Support for a alternate probe manager, which will eliminate the
+   boilerplate below. */
+struct netdev_entry netcard_drv =
+{"netcard", netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist};
+#else
 int
 netcard_probe(struct device *dev)
 {
-       int *port, ports[] = {0x300, 0x280, 0};
-       int base_addr = dev->base_addr;
+       int i;
+       int base_addr = dev ? dev->base_addr : 0;
 
        if (base_addr > 0x1ff)          /* Check a single specified location. */
                return netcard_probe1(dev, base_addr);
-       else if (base_addr > 0)         /* Don't probe at all. */
+       else if (base_addr != 0)        /* Don't probe at all. */
                return ENXIO;
 
-       for (port = &ports[0]; *port; port++) {
-               int ioaddr = *port;
-               if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
-                       continue;
-               if (inb(ioaddr) != 0x57)
+       for (i = 0; netcard_portlist[i]; i++) {
+               int ioaddr = netcard_portlist[i];
+               if (check_region(ioaddr, NETCARD_IO_EXTENT))
                        continue;
-               dev->base_addr = ioaddr;
                if (netcard_probe1(dev, ioaddr) == 0)
                        return 0;
        }
 
-       dev->base_addr = base_addr;
        return ENODEV;
 }
+#endif
+
+/* This is the real probe routine.  Linux has a history of friendly device
+   probes on the ISA bus.  A good device probes avoids doing writes, and
+   verifies that the correct device exists and functions.  */
 
-int netcard_probe1(struct device *dev, short ioaddr)
+static int netcard_probe1(struct device *dev, int ioaddr)
 {
-       unsigned char station_addr[6];
+       static unsigned version_printed = 0;
        int i;
 
-       /* Read the station address PROM.  */
-       for (i = 0; i < 6; i++) {
-               station_addr[i] = inb(ioaddr + i);
-       }
-       /* Check the first three octets of the S.A. for the manufacturer's code. */ 
-       if (station_addr[0] != SA_ADDR0
-               ||       station_addr[1] != SA_ADDR1 || station_addr[2] != SA_ADDR2) {
+       /* For ethernet adaptors the first three octets of the station address contains
+          the manufacturer's unique code.  That might be a good probe method.
+          Ideally you would add additional checks.  */ 
+       if (inb(ioaddr + 0) != SA_ADDR0
+               ||       inb(ioaddr + 1) != SA_ADDR1
+               ||       inb(ioaddr + 2) != SA_ADDR2) {
                return ENODEV;
        }
 
-       printk("%s: %s found at %#3x, IRQ %d.\n", dev->name,
-                  "network card", dev->base_addr, dev->irq);
+       /* Allocate a new 'dev' if needed. */
+       if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct net_local), 0);
+
+       if (net_debug  &&  version_printed++ == 0)
+               printk(version);
+
+       printk("%s: %s found at %#3x, ", dev->name, "network card", ioaddr);
+
+       /* Fill in the 'dev' fields. */
+       dev->base_addr = ioaddr;
+
+       /* Retrive and print the ethernet address. */
+       for (i = 0; i < 6; i++)
+               printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
 
 #ifdef jumpered_interrupts
        /* If this board has jumpered interrupts, snarf the interrupt vector
           now.  There is no point in waiting since no other device can use
-          the interrupt, and this marks the irq as busy. */
+          the interrupt, and this marks the irq as busy.
+          Jumpered interrupts are typically not reported by the boards, and
+          we must used autoIRQ to find them. */
 
        if (dev->irq == -1)
                ;                       /* Do nothing: a user-level program will set it. */
@@ -190,15 +207,51 @@ int netcard_probe1(struct device *dev, short ioaddr)
                 }
         }
 #endif /* jumpered interrupt */
+#ifdef jumpered_dma
+       /* If we use a jumpered DMA channel, that should be probed for and
+          allocated here as well.  See lance.c for an example. */
+       if (dev->dma == 0) {
+               if (request_dma(dev->dma, "netcard")) {
+                       printk("DMA %d allocation failed.\n", dev->dma);
+                       return EAGAIN;
+               } else
+                       printk(", assigned DMA %d.\n", dev->dma);
+       } else {
+               short dma_status, new_dma_status;
+
+               /* Read the DMA channel status registers. */
+               dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
+                       (inb(DMA2_STAT_REG) & 0xf0);
+               /* Trigger a DMA request, perhaps pause a bit. */
+               outw(0x1234, ioaddr + 8);
+               /* Re-read the DMA status registers. */
+               new_dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
+                       (inb(DMA2_STAT_REG) & 0xf0);
+               /* Eliminate the old and floating requests and DMA4, the cascade. */
+               new_dma_status ^= dma_status;
+               new_dma_status &= ~0x10;
+               for (i = 7; i > 0; i--)
+                       if (test_bit(new_dma, &new_dma_status)) {
+                               dev->dma = i;
+                               break;
+                       }
+               if (i <= 0) {
+                       printk("DMA probe failed.\n");
+                       return EAGAIN;
+               } 
+               if (request_dma(dev->dma, "netcard")) {
+                       printk("probed DMA %d allocation failed.\n", dev->dma);
+                       return EAGAIN;
+               }
+       }
+#endif /* jumpered DMA */
 
        /* Grab the region so we can find another board if autoIRQ fails. */
-       snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE);
-
-       if (net_debug)
-               printk(version);
+       snarf_region(ioaddr, NETCARD_IO_EXTENT);
 
        /* Initialize the device structure. */
-       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+       if (dev->priv == NULL)
+               dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
        memset(dev->priv, 0, sizeof(struct net_local));
 
        dev->open               = net_open;
@@ -207,8 +260,7 @@ int netcard_probe1(struct device *dev, short ioaddr)
        dev->get_stats  = net_get_stats;
        dev->set_multicast_list = &set_multicast_list;
 
-       /* Fill in the fields of the device structure with ethernet-generic values. */
-       
+       /* Fill in the fields of the device structure with ethernet values. */
        ether_setup(dev);
 
        return 0;
@@ -234,15 +286,14 @@ net_open(struct device *dev)
                return -EAGAIN;
        }
 
-
-       /* Always snarf a DMA channel after the IRQ. */
+       /* Always snarf the DMA channel after the IRQ, and clean up on failure. */
        if (request_dma(dev->dma,"skeleton ethernet")) {
                free_irq(dev->irq);
                return -EAGAIN;
        }
        irq2dev_map[dev->irq] = dev;
 
-       /* Reset the hardware here. */
+       /* Reset the hardware here.  Don't forget to set the station address. */
        /*chipset_init(dev, 1);*/
        outb(0x00, ioaddr);
        lp->open_time = jiffies;
@@ -337,6 +388,7 @@ net_interrupt(int reg_ptr)
                }
        } while (++boguscount < 20) ;
 
+       dev->interrupt = 0;
        return;
 }
 
index 3296f4a5fe784680e9cd08f89e93618b20acca57..45ff88eaffcb4ce50495f8258e448acf2af6476c 100644 (file)
@@ -1,20 +1,23 @@
 /* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
 /*
-    Written 1993 by Donald Becker.  If released, this code will be
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU Public License,
-    incorporated herein by reference.
-    
-    This is a driver for the SMC Ultra ethercard.
+       Written 1993-94 by Donald Becker.
 
-    The Author may be reached as becker@super.org or
-    C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+               Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+       This is a driver for the SMC Ultra ethercard.
 
 */
 
 static char *version =
-    "smc-ultra.c:v0.07 3/1/94 Donald Becker (becker@super.org)\n";
+       "smc-ultra.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -26,180 +29,192 @@ static char *version =
 
 #include <linux/netdevice.h>
 #include "8390.h"
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                                                       unsigned long *mem_startp);
 
-/* Compatibility definitions for earlier kernel versions. */
-#ifndef HAVE_PORTRESERVE
-#define check_region(ioaddr, size)              0
-#define snarf_region(ioaddr, size);             do ; while (0)
-#endif
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int ultra_portlist[] =
+{0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
 
-int ultraprobe(int ioaddr, struct device *dev);
-int ultraprobe1(int ioaddr, struct device *dev);
+int ultra_probe(struct device *dev);
+int ultra_probe1(struct device *dev, int ioaddr);
 
 static int ultra_open(struct device *dev);
 static void ultra_reset_8390(struct device *dev);
 static int ultra_block_input(struct device *dev, int count,
-                         char *buf, int ring_offset);
+                                                 char *buf, int ring_offset);
 static void ultra_block_output(struct device *dev, int count,
-                           const unsigned char *buf, const start_page);
+                                                       const unsigned char *buf, const start_page);
 static int ultra_close_card(struct device *dev);
 
 \f
-#define START_PG       0x00    /* First page of TX buffer */
+#define START_PG               0x00    /* First page of TX buffer */
 
-#define ULTRA_CMDREG   0       /* Offset to ASIC command register. */
-#define  ULTRA_RESET   0x80    /* Board reset, in ULTRA_CMDREG. */
-#define  ULTRA_MEMENB  0x40    /* Enable the shared memory. */
+#define ULTRA_CMDREG   0               /* Offset to ASIC command register. */
+#define         ULTRA_RESET    0x80    /* Board reset, in ULTRA_CMDREG. */
+#define         ULTRA_MEMENB   0x40    /* Enable the shared memory. */
 #define ULTRA_NIC_OFFSET  16   /* NIC register offset from the base_addr. */
+#define ULTRA_IO_EXTENT 32
 \f
-/*  Probe for the Ultra.  This looks like a 8013 with the station
-    address PROM at I/O ports <base>+8 to <base>+13, with a checksum
-    following.
+/*     Probe for the Ultra.  This looks like a 8013 with the station
+       address PROM at I/O ports <base>+8 to <base>+13, with a checksum
+       following.
 */
+#ifdef HAVE_DEVLIST
+struct netdev_entry ultra_drv =
+{"ultra", ultra_probe1, NETCARD_IO_EXTENT, netcard_portlist};
+#else
 
 int ultra_probe(struct device *dev)
 {
-    int *port, ports[] = {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
-    unsigned short ioaddr = dev->base_addr;
-
-    if (ioaddr > 0x1ff)
-       return ultraprobe1(ioaddr, dev);
-    else if (ioaddr > 0)
-       return ENXIO;           /* Don't probe at all. */
-
-    for (port = &ports[0]; *port; port++) {
-       if (check_region(*port, 32))
-           continue;
-       if ((inb(*port + 7) & 0xF0) == 0x20     /* Check chip ID nibble. */
-           && ultraprobe1(*port, dev) == 0)
-           return 0;
-    }
-    dev->base_addr = ioaddr;
-    return ENODEV;
+       int i;
+       int base_addr = dev ? dev->base_addr : 0;
+
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return ultra_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return ENXIO;
+
+       for (i = 0; ultra_portlist[i]; i++) {
+               int ioaddr = ultra_portlist[i];
+               if (check_region(ioaddr, ULTRA_IO_EXTENT))
+                       continue;
+               if (ultra_probe1(dev, ioaddr) == 0)
+                       return 0;
+       }
+
+       return ENODEV;
 }
+#endif
 
-int ultraprobe1(int ioaddr, struct device *dev)
+int ultra_probe1(struct device *dev, int ioaddr)
 {
-  int i;
-  unsigned char *station_addr = dev->dev_addr;
-  int checksum = 0;
-  char *model_name;
-  unsigned char eeprom_irq = 0;
-  /* Values from various config regs. */
-  unsigned char num_pages, irqreg, addr, reg4 = inb(ioaddr + 4) & 0x7f;
-
-
-  /* Select the station address register set. */
-  outb(reg4, ioaddr + 4);
-
-  for (i = 0; i < 8; i++)
-      checksum += inb(ioaddr + 8 + i);
-  if ((checksum & 0xff) != 0xFF)
-      return ENODEV;
-  
-  printk("%s: SMC Ultra at %#3x,", dev->name, ioaddr);
-  for (i = 0; i < 6; i++)
-      printk(" %2.2X", station_addr[i] = inb(ioaddr + 8 + i));
-
-  /* Switch from the station address to the alternate register set and
-     read the useful registers there. */
-  outb(0x80 | reg4, ioaddr + 4);
-
-  /* Enabled FINE16 mode to avoid BIOS ROM width mismatches during reboot. */
-  outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
-  irqreg = inb(ioaddr + 0xd);
-  addr = inb(ioaddr + 0xb);
-
-  /* Switch back to the station address register set so that the MS-DOS driver
-     can find the card after a warm boot. */
-  outb(reg4, ioaddr + 4);
-
-  model_name = "SMC Ultra";
-
-  if (dev->irq < 2) {
-      unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
-      int irq;
-
-      /* The IRQ bits are split. */
-      irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
-
-      if (irq == 0) {
-         printk(", failed to detect IRQ line.\n");
-         return -EAGAIN;
-      }
-      dev->irq = irq;
-      eeprom_irq = 1;
-  }
-
-
-  /* OK, were are certain this is going to work.  Setup the device. */
-  snarf_region(ioaddr, 32);
-
-  /* The 8390 isn't at the base address, so fake the offset */
-  dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
-
-  { 
-      int addr_tbl[4] = {0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000};
-      short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff};
-
-      dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
-      num_pages = num_pages_tbl[(addr >> 4) & 3];
-  }
-
-  ethdev_init(dev);
-
-  ei_status.name = model_name;
-  ei_status.word16 = 1;
-  ei_status.tx_start_page = START_PG;
-  ei_status.rx_start_page = START_PG + TX_PAGES;
-  ei_status.stop_page = num_pages;
-
-  dev->rmem_start = dev->mem_start + TX_PAGES*256;
-  dev->mem_end = dev->rmem_end
-      = dev->mem_start + (ei_status.stop_page - START_PG)*256;
-
-  printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
-        dev->irq, dev->mem_start, dev->mem_end-1);
-  if (ei_debug > 0)
-      printk(version);
-
-  ei_status.reset_8390 = &ultra_reset_8390;
-  ei_status.block_input = &ultra_block_input;
-  ei_status.block_output = &ultra_block_output;
-  dev->open = &ultra_open;
-  dev->stop = &ultra_close_card;
-  NS8390_init(dev, 0);
-
-  return 0;
+       int i;
+       int checksum = 0;
+       char *model_name;
+       unsigned char eeprom_irq = 0;
+       /* Values from various config regs. */
+       unsigned char num_pages, irqreg, addr, reg4 = inb(ioaddr + 4) & 0x7f;
+
+       /* Check the ID nibble. */
+       if ((inb(ioaddr + 7) & 0xF0) != 0x20)
+               return ENODEV;
+
+       /* Select the station address register set. */
+       outb(reg4, ioaddr + 4);
+
+       for (i = 0; i < 8; i++)
+               checksum += inb(ioaddr + 8 + i);
+       if ((checksum & 0xff) != 0xFF)
+               return ENODEV;
+
+       if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct ei_device), 0);
+
+       printk("%s: SMC Ultra at %#3x,", dev->name, ioaddr);
+
+       for (i = 0; i < 6; i++)
+               printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
+
+       /* Switch from the station address to the alternate register set and
+          read the useful registers there. */
+       outb(0x80 | reg4, ioaddr + 4);
+
+       /* Enabled FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
+       outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
+       irqreg = inb(ioaddr + 0xd);
+       addr = inb(ioaddr + 0xb);
+
+       /* Switch back to the station address register set so that the MS-DOS driver
+          can find the card after a warm boot. */
+       outb(reg4, ioaddr + 4);
+
+       model_name = "SMC Ultra";
+
+       if (dev->irq < 2) {
+               unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
+               int irq;
+
+               /* The IRQ bits are split. */
+               irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
+
+               if (irq == 0) {
+                       printk(", failed to detect IRQ line.\n");
+                       return -EAGAIN;
+               }
+               dev->irq = irq;
+               eeprom_irq = 1;
+       }
+
+
+       /* OK, were are certain this is going to work.  Setup the device. */
+       snarf_region(ioaddr, 32);
+
+       /* The 8390 isn't at the base address, so fake the offset */
+       dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
+
+       {
+               int addr_tbl[4] = {0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000};
+               short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff};
+
+               dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
+               num_pages = num_pages_tbl[(addr >> 4) & 3];
+       }
+
+       ethdev_init(dev);
+
+       ei_status.name = model_name;
+       ei_status.word16 = 1;
+       ei_status.tx_start_page = START_PG;
+       ei_status.rx_start_page = START_PG + TX_PAGES;
+       ei_status.stop_page = num_pages;
+
+       dev->rmem_start = dev->mem_start + TX_PAGES*256;
+       dev->mem_end = dev->rmem_end
+               = dev->mem_start + (ei_status.stop_page - START_PG)*256;
+
+       printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
+                  dev->irq, dev->mem_start, dev->mem_end-1);
+       if (ei_debug > 0)
+               printk(version);
+
+       ei_status.reset_8390 = &ultra_reset_8390;
+       ei_status.block_input = &ultra_block_input;
+       ei_status.block_output = &ultra_block_output;
+       dev->open = &ultra_open;
+       dev->stop = &ultra_close_card;
+       NS8390_init(dev, 0);
+
+       return 0;
 }
 
 static int
 ultra_open(struct device *dev)
 {
-  int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 
-  if (request_irq(dev->irq, ei_interrupt, 0, "SMC Ultra"))
-      return -EAGAIN;
+       if (request_irq(dev->irq, ei_interrupt, 0, "SMC Ultra"))
+               return -EAGAIN;
 
-  outb(ULTRA_MEMENB, ioaddr);  /* Enable memory, 16 bit mode. */
-  outb(0x80, ioaddr + 5);
-  outb(0x01, ioaddr + 6);      /* Enable interrupts and memory. */
-  return ei_open(dev);
+       outb(ULTRA_MEMENB, ioaddr);     /* Enable memory, 16 bit mode. */
+       outb(0x80, ioaddr + 5);
+       outb(0x01, ioaddr + 6);         /* Enable interrupts and memory. */
+       return ei_open(dev);
 }
 
 static void
 ultra_reset_8390(struct device *dev)
 {
-    int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
+       int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
 
-    outb(ULTRA_RESET, cmd_port);
-    if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
-    ei_status.txing = 0;
+       outb(ULTRA_RESET, cmd_port);
+       if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
+       ei_status.txing = 0;
 
-    outb(ULTRA_MEMENB, cmd_port);
+       outb(ULTRA_MEMENB, cmd_port);
 
-    if (ei_debug > 1) printk("reset done\n");
-    return;
+       if (ei_debug > 1) printk("reset done\n");
+       return;
 }
 
 /* Block input and output are easy on shared memory ethercards, the only
@@ -208,54 +223,54 @@ ultra_reset_8390(struct device *dev)
 static int
 ultra_block_input(struct device *dev, int count, char *buf, int ring_offset)
 {
-    void *xfer_start = (void *)(dev->mem_start + ring_offset
-                               - (START_PG<<8));
-
-    if (xfer_start + count > (void*) dev->rmem_end) {
-       /* We must wrap the input move. */
-       int semi_count = (void*)dev->rmem_end - xfer_start;
-       memcpy(buf, xfer_start, semi_count);
-       count -= semi_count;
-       memcpy(buf + semi_count, (char *)dev->rmem_start, count);
-       return dev->rmem_start + count;
-    }
-    memcpy(buf, xfer_start, count);
-
-    return ring_offset + count;
+       void *xfer_start = (void *)(dev->mem_start + ring_offset
+                                                               - (START_PG<<8));
+
+       if (xfer_start + count > (void*) dev->rmem_end) {
+               /* We must wrap the input move. */
+               int semi_count = (void*)dev->rmem_end - xfer_start;
+               memcpy(buf, xfer_start, semi_count);
+               count -= semi_count;
+               memcpy(buf + semi_count, (char *)dev->rmem_start, count);
+               return dev->rmem_start + count;
+       }
+       memcpy(buf, xfer_start, count);
+
+       return ring_offset + count;
 }
 
 static void
 ultra_block_output(struct device *dev, int count, const unsigned char *buf,
-               int start_page)
+                               int start_page)
 {
-    unsigned char *shmem
-       = (unsigned char *)dev->mem_start + ((start_page - START_PG)<<8);
+       unsigned char *shmem
+               = (unsigned char *)dev->mem_start + ((start_page - START_PG)<<8);
 
-    memcpy(shmem, buf, count);
+       memcpy(shmem, buf, count);
 
 }
 
 static int
 ultra_close_card(struct device *dev)
 {
-    int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
 
-    dev->start = 0;
-    dev->tbusy = 1;
+       dev->start = 0;
+       dev->tbusy = 1;
 
-    if (ei_debug > 1)
-       printk("%s: Shutting down ethercard.\n", dev->name);
+       if (ei_debug > 1)
+               printk("%s: Shutting down ethercard.\n", dev->name);
 
-    outb(0x00, ioaddr + 6);    /* Disable interrupts. */
-    free_irq(dev->irq);
-    irq2dev_map[dev->irq] = 0;
+       outb(0x00, ioaddr + 6);         /* Disable interrupts. */
+       free_irq(dev->irq);
+       irq2dev_map[dev->irq] = 0;
 
-    NS8390_init(dev, 0);
+       NS8390_init(dev, 0);
 
-    /* We should someday disable shared memory and change to 8-bit mode
-       "just in case"... */
+       /* We should someday disable shared memory and change to 8-bit mode
+          "just in case"... */
 
-    return 0;
+       return 0;
 }
 \f
 
@@ -264,5 +279,7 @@ ultra_close_card(struct device *dev)
  *  compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c"
  *  version-control: t
  *  kept-new-versions: 5
+ *  c-indent-level: 4
+ *  tab-width: 4
  * End:
  */
index 6a11be410697778680cd9198ac61eb2ba23eb9d8..9dba2ea2a77e18544d331669b0a0c6ae14073788 100644 (file)
@@ -1,21 +1,24 @@
 /* wd.c: A WD80x3 ethernet driver for linux. */
 /*
-       Written 1993 by Donald Becker.
+       Written 1993-94 by Donald Becker.
+
        Copyright 1993 United States Government as represented by the
-       Director, National Security Agency.      This software may be used and
-       distributed according to the terms of the GNU Public License,
-       incorporated herein by reference.
-       
-       This is a driver for WD8003 and WD8013 "compatible" ethercards.
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
-       The Author may be reached as becker@super.org or
-       C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+       This is a driver for WD8003 and WD8013 "compatible" ethercards.
 
        Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
 */
 
 static char *version =
-       "wd.c:v0.99-14 11/21/93 Donald Becker (becker@super.org)\n";
+       "wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -27,15 +30,15 @@ static char *version =
 
 #include <linux/netdevice.h>
 #include "8390.h"
+extern struct device *init_etherdev(struct device *dev, int sizeof_private,
+                                                                       unsigned long *mem_startp);
 
-/* Compatibility definitions for earlier kernel versions. */
-#ifndef HAVE_PORTRESERVE
-#define check_region(ioaddr, size)             0
-#define snarf_region(ioaddr, size)             do ; while (0)
-#endif
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int wd_portlist[] =
+{0x300, 0x280, 0x380, 0x240, 0};
 
 int wd_probe(struct device *dev);
-int wdprobe1(int ioaddr, struct device *dev);
+int wd_probe1(struct device *dev, int ioaddr);
 
 static int wd_open(struct device *dev);
 static void wd_reset_8390(struct device *dev);
@@ -56,56 +59,67 @@ static int wd_close_card(struct device *dev);
 #define WD_CMDREG5             5               /* Offset to 16-bit-only ASIC register 5. */
 #define         ISA16                  0x80    /* Enable 16 bit access from the ISA bus. */
 #define         NIC16                  0x40    /* Enable 16 bit access from the 8390. */
-#define WD_NIC_OFFSET  16              /* Offset to the 8390 NIC from the base_addr. */
+#define WD_NIC_OFFSET  16              /* Offset to the 8390 from the base_addr. */
+#define WD_IO_EXTENT   32
+
 \f
 /*     Probe for the WD8003 and WD8013.  These cards have the station
        address PROM at I/O ports <base>+8 to <base>+13, with a checksum
        following. A Soundblaster can have the same checksum as an WDethercard,
        so we have an extra exclusionary check for it.
 
-       The wdprobe1() routine initializes the card and fills the
+       The wd_probe1() routine initializes the card and fills the
        station address field. */
 
+#ifdef HAVE_DEVLIST
+struct netdev_entry wd_drv =
+{"wd", wd_probe1, WD_IO_EXTENT, wd_portlist};
+#else
+
 int wd_probe(struct device *dev)
 {
-       int *port, ports[] = {0x300, 0x280, 0x380, 0x240, 0};
-       short ioaddr = dev->base_addr;
+       int i;
+       int base_addr = dev ? dev->base_addr : 0;
 
-       if (ioaddr < 0)
-               return ENXIO;                   /* Don't probe at all. */
-       if (ioaddr > 0x100)
-               return ! wdprobe1(ioaddr, dev);
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return wd_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return ENXIO;
 
-       for (port = &ports[0]; *port; port++) {
-               if (check_region(*port, 32))
+       for (i = 0; wd_portlist[i]; i++) {
+               int ioaddr = wd_portlist[i];
+               if (check_region(ioaddr, WD_IO_EXTENT))
                        continue;
-               if (inb(*port + 8) != 0xff
-                       && inb(*port + 9) != 0xff /* Extra check to avoid soundcard. */
-                       && wdprobe1(*port, dev))
+               if (wd_probe1(dev, ioaddr) == 0)
                        return 0;
        }
-       dev->base_addr = ioaddr;
+
        return ENODEV;
 }
+#endif
 
-int wdprobe1(int ioaddr, struct device *dev)
+int wd_probe1(struct device *dev, int ioaddr)
 {
        int i;
-       unsigned char *station_addr = dev->dev_addr;
        int checksum = 0;
        int ancient = 0;                        /* An old card without config registers. */
        int word16 = 0;                         /* 0 = 8 bit, 1 = 16 bit */
        char *model_name;
-       
+
        for (i = 0; i < 8; i++)
                checksum += inb(ioaddr + 8 + i);
-       if ((checksum & 0xff) != 0xFF)
-               return 0;
-       
+       if (inb(ioaddr + 8) == 0xff     /* Extra check to avoid soundcard. */
+               || inb(ioaddr + 9) == 0xff
+               || (checksum & 0xff) != 0xFF)
+               return ENODEV;
+
+       if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct ei_device), 0);
+
        printk("%s: WD80x3 at %#3x, ", dev->name, ioaddr);
        for (i = 0; i < 6; i++)
-               printk(" %2.2X", station_addr[i] = inb(ioaddr + 8 + i));
-       
+               printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
+
        /* The following PureData probe code was contributed by
           Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
           configuration differently from others so we have to check for them.
@@ -113,7 +127,7 @@ int wdprobe1(int ioaddr, struct device *dev)
           */
        if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
                unsigned char reg5 = inb(ioaddr+5);
-               
+
                switch (inb(ioaddr+2)) {
                case 0x03: word16 = 0; model_name = "PDI8023-8";        break;
                case 0x05: word16 = 0; model_name = "PDUC8023"; break;
@@ -160,7 +174,7 @@ int wdprobe1(int ioaddr, struct device *dev)
                                   word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8);
 #endif
        }
-       
+
 #if defined(WD_SHMEM) && WD_SHMEM > 0x80000
        /* Allow a compile-time override.        */
        dev->mem_start = WD_SHMEM;
@@ -181,17 +195,17 @@ int wdprobe1(int ioaddr, struct device *dev)
                }
        }
 #endif
-       
+
        /* The 8390 isn't at the base address -- the ASIC regs are there! */
        dev->base_addr = ioaddr+WD_NIC_OFFSET;
-       
+
        if (dev->irq < 2) {
                int irqmap[] = {9,3,5,7,10,11,15,4};
                int reg1 = inb(ioaddr+1);
                int reg4 = inb(ioaddr+4);
                if (ancient || reg1 == 0xff) {  /* Ack!! No way to read the IRQ! */
                        short nic_addr = ioaddr+WD_NIC_OFFSET;
-                       
+
                        /* We have an old-style ethercard that doesn't report its IRQ
                           line.  Do autoirq to find the IRQ line. Note that this IS NOT
                           a reliable way to trigger an interrupt. */
@@ -204,7 +218,7 @@ int wdprobe1(int ioaddr, struct device *dev)
                        outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
                        dev->irq = autoirq_report(2);
                        outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */
-                       
+
                        if (ei_debug > 2)
                                printk(" autoirq is %d", dev->irq);
                        if (dev->irq < 2)
@@ -213,42 +227,42 @@ int wdprobe1(int ioaddr, struct device *dev)
                        dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
        } else if (dev->irq == 2)               /* Fixup bogosity: IRQ2 is really IRQ9 */
                dev->irq = 9;
-       
+
        /* Snarf the interrupt now.  There's no point in waiting since we cannot
           share and the board will usually be enabled. */
        if (request_irq(dev->irq, ei_interrupt, 0, "wd")) {
                printk (" unable to get IRQ %d.\n", dev->irq);
-               return 0;
+               return EAGAIN;
        }
-       
+
        /* OK, were are certain this is going to work.  Setup the device. */
-       snarf_region(ioaddr, 32);
+       snarf_region(ioaddr, WD_IO_EXTENT);
        ethdev_init(dev);
-       
+
        ei_status.name = model_name;
        ei_status.word16 = word16;
        ei_status.tx_start_page = WD_START_PG;
        ei_status.rx_start_page = WD_START_PG + TX_PAGES;
        ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
-       
+
        /* Don't map in the shared memory until the board is actually opened. */
        dev->rmem_start = dev->mem_start + TX_PAGES*256;
        dev->mem_end = dev->rmem_end
                = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
-       
+
        printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
                   model_name, dev->irq, dev->mem_start, dev->mem_end-1);
        if (ei_debug > 0)
                printk(version);
-       
+
        ei_status.reset_8390 = &wd_reset_8390;
        ei_status.block_input = &wd_block_input;
        ei_status.block_output = &wd_block_output;
        dev->open = &wd_open;
        dev->stop = &wd_close_card;
        NS8390_init(dev, 0);
-       
-       return dev->base_addr;
+
+       return 0;
 }
 
 static int
index a2180013a49fb3faff378cd087f0cda6d5d1422b..21df8831f08f260315282a9a8db47a01e48de49d 100644 (file)
@@ -1,6 +1,6 @@
 /* znet.c: An Zenith Z-Note ethernet driver for linux. */
 
-static char *version = "znet.c:v1.01 7/1/94 becker@cesdis.gsfc.nasa.gov\n";
+static char *version = "znet.c:v1.02 9/23/94 becker@cesdis.gsfc.nasa.gov\n";
 
 /*
        Written by Donald Becker.
@@ -81,7 +81,7 @@ static char *version = "znet.c:v1.01 7/1/94 becker@cesdis.gsfc.nasa.gov\n";
 #include <linux/if_arp.h>
 
 #ifndef ZNET_DEBUG
-#define ZNET_DEBUG 3
+#define ZNET_DEBUG 1
 #endif
 static unsigned int znet_debug = ZNET_DEBUG;
 
index 88ab535d4cd7799adb22d108d0d232af3b096c22..c7acc1404cc623f370a5b6fe9011519f951ad4f0 100644 (file)
@@ -1804,7 +1804,7 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end
                               host->hostt->cmd_per_lun;
          
          if(host->unchecked_isa_dma &&
-            memory_end > ISA_DMA_THRESHOLD &&
+            memory_end - 1 > ISA_DMA_THRESHOLD &&
             SDpnt->type != TYPE_TAPE) {
            dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
              host->hostt->cmd_per_lun;
index d06e988f8d98a215cb689e72596eb5b9253da0bd..e06c63d240977139967415e6f681235a9a18b0e7 100644 (file)
@@ -80,7 +80,7 @@ static inline int *nfs_rpc_alloc(int size)
 #if 1
        /* Allow for the NFS crap as well as buffer */
        return (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL);
-#else
+#else 
        /* If kmalloc fails, then we will give an EIO to user level.
           (Please correct me, I am wron here... ??) This is not
           desirable, but it is also not desirable to execute the
index 1a1dc5486ceebf951a2afe278050ee8bcb2c94e2..2455d938a4ff4493f1062479ff72e0ff7aa88b1d 100644 (file)
@@ -209,7 +209,9 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int
                                  size + 1024, 1, 0, NULL,
                        /* Here is NFS_SLACK_SPACE..., hack */
                                  &addrlen);
-       if (result < addrlen) {
+       if (result < 0) {
+               printk("NFS: notice message: result=%d\n", result);
+       } else if (result < addrlen) {
                printk("NFS: just caught a too small read memory size..., email to NET channel\n");
                printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
                result = -EIO;
index c7f80e2898a2d29a8f09ba83c1d81869512c3bb3..a0d595d61b272754c3184a029f11d30a70a58cbe 100644 (file)
@@ -71,10 +71,16 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode,
        }
        error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
                &res, &len, NFS_MAXPATHLEN);
+#if 1
        if ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
                printk("NFS: no memory in nfs_follow_link\n");
                error = -EIO;
        }
+#else
+       while ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
+               schedule();
+       }
+#endif
        if (error) {
                iput(inode);
                iput(dir);
index 9d9bc161c2525bcc82ee7ebb98f2fc3e3d75028d..fb3226db68252043b21fd40f8f9675cffd768db4 100644 (file)
@@ -54,7 +54,7 @@ struct        rusage {
 
 #define RLIM_NLIMITS   6
 
-#define RLIM_INFINITY  0x7FFFFFFF
+#define RLIM_INFINITY  ((long)(~0UL>>1))
 
 struct rlimit {
        int     rlim_cur;
index d27681471c1a7648d99e5be59e3d1ea7af81fb22..ed625098fd4b45d6c335ad8716514503386ef21b 100644 (file)
@@ -13,7 +13,7 @@ typedef unsigned int sigset_t;                /* 32 bits */
 #define SIGTRAP                 5
 #define SIGABRT                 6
 #define SIGIOT          6
-#define SIGUNUSED       7
+#define SIGBUS          7
 #define SIGFPE          8
 #define SIGKILL                 9
 #define SIGUSR1                10
@@ -29,32 +29,19 @@ typedef unsigned int sigset_t;              /* 32 bits */
 #define SIGTSTP                20
 #define SIGTTIN                21
 #define SIGTTOU                22
-
-/*
- * Most of these aren't used yet (and perhaps never will),
- * so they are commented out.
- */
-
-
 #define SIGIO          23
 #define SIGPOLL                SIGIO
 #define SIGURG         SIGIO
 #define SIGXCPU                24
 #define SIGXFSZ                25
-
-
 #define SIGVTALRM      26
 #define SIGPROF                27
-
 #define SIGWINCH       28
-
 /*
 #define SIGLOST                29
 */
 #define SIGPWR         30
-
-/* Arggh. Bad user source code wants this.. */
-#define SIGBUS         SIGUNUSED
+#define        SIGUNUSED       31
 
 /*
  * sa_flags values: SA_STACK is not currently supported, but will allow the
index edc2cec95f6ac0336c4294fd710fc02a81d9cd67..bbd8f5010c2e452c7b0406ea37093fc4e6d2aa30 100644 (file)
@@ -600,7 +600,7 @@ static void do_timer(struct pt_regs * regs)
        unsigned long mask;
        struct timer_struct *tp;
 
-       long ltemp;
+       long ltemp, psecs;
 
        /* Advance the phase, once it gets to one microsecond, then
         * advance the tick more.
@@ -679,12 +679,20 @@ static void do_timer(struct pt_regs * regs)
        /*
         * check the cpu time limit on the process.
         */
-       if ((current->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
-           (((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_cur))
-               send_sig(SIGXCPU, current, 1);
        if ((current->rlim[RLIMIT_CPU].rlim_max != RLIM_INFINITY) &&
            (((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_max))
                send_sig(SIGKILL, current, 1);
+       if ((current->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
+           (((current->stime + current->utime) % HZ) == 0)) {
+               psecs = (current->stime + current->utime) / HZ;
+               /* send when equal */
+               if (psecs == current->rlim[RLIMIT_CPU].rlim_cur)
+                       send_sig(SIGXCPU, current, 1);
+               /* and every five seconds thereafter. */
+               else if ((psecs > current->rlim[RLIMIT_CPU].rlim_cur) &&
+                       ((psecs - current->rlim[RLIMIT_CPU].rlim_cur) % 5) == 0)
+                       send_sig(SIGXCPU, current, 1);
+       }
 
        if (current != task[0] && 0 > --current->counter) {
                current->counter = 0;
index 72c89f856856ebae8043226bcb0be0e87ffec416..df7324294e74445585764dafc0baeee057716864 100644 (file)
@@ -217,8 +217,8 @@ if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
        COPY(ebx);
        COPY(esp); COPY(ebp);
        COPY(edi); COPY(esi);
-       regs->eflags &= ~0xCD5;
-       regs->eflags |= context.eflags & 0xCD5;
+       regs->eflags &= ~0x40DD5;
+       regs->eflags |= context.eflags & 0x40DD5;
        regs->orig_eax = -1;            /* disable syscall checks */
        return context.eax;
 badframe:
index 144d93a024c700f68ed03f606520d550981a487e..1c56954a75854bbb9aab246d52adda996e8dae9f 100644 (file)
@@ -45,8 +45,8 @@
 #define set_flags(X,new,mask) \
 ((X) = ((X) & ~(mask)) | ((new) & (mask)))
 
-#define SAFE_MASK      (0xDD5)
-#define RETURN_MASK    (0xDFF)
+#define SAFE_MASK      (0x40DD5)
+#define RETURN_MASK    (0x40DFF)
 
 asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs)
 {
index 5825002e8f1f75e245d7f5d424f0349b5b5f40d4..f751bd7bde42fc9e413961510f94c90a65512b6a 100644 (file)
@@ -23,6 +23,7 @@
  *             Alan Cox        :       Removed old debugging junk
  *             Alan Cox        :       Fixed the ICMP error status of net/host unreachable
  *     Gerhard Koerting        :       Fixed broadcast ping properly
+ *             Ulrich Kunitz   :       Fixed ICMP timestamp reply
  *
  * 
  *
@@ -424,8 +425,21 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
        int size, offset;
        unsigned long *timeptr, midtime;
        struct device *ndev=NULL;
-       size = dev->hard_header_len + 64 + len;
+
+        if (len != 20)
+       {
+               printk(
+                 "ICMP: Size (%d) of ICMP_TIMESTAMP request should be 20!\n",
+                 len);
+               icmp_statistics.IcmpInErrors++;         
+#if 1
+                /* correct answers are possible for everything >= 12 */
+               if (len < 12)
+#endif
+                       return;
+       }
+
+       size = dev->hard_header_len + 84;
 
        if (! (skb2 = alloc_skb(size, GFP_ATOMIC))) 
        {
@@ -454,14 +468,14 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
        /*
         *      Re-adjust length according to actual IP header size. 
         */
-       skb2->len = offset + len;
+       skb2->len = offset + 20;
  
        /*
         *      Build ICMP_TIMESTAMP Response message. 
         */
 
        icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
-       memcpy((char *) icmphr, (char *) icmph, len);
+       memcpy((char *) icmphr, (char *) icmph, 12);
        icmphr->type = ICMP_TIMESTAMPREPLY;
        icmphr->code = icmphr->checksum = 0;
 
@@ -473,7 +487,7 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
         */
        timeptr [1] = timeptr [2] = htonl(midtime);
 
-       icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, len);
+       icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, 20);
 
        /*
         *      Ship it out - free it when done