fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / eepro.c
index 9f5ea60..b446309 100644 (file)
@@ -23,6 +23,7 @@
        This is a compatibility hardware problem.
 
        Versions:
+       0.13b   basic ethtool support (aris, 09/13/2004)
        0.13a   in memory shortage, drop packets also in board
                (Michael Westermann <mw@microdata-pos.de>, 07/30/2002)
        0.13    irq sharing, rewrote probe function, fixed a nasty bug in
 */
 
 static const char version[] =
-       "eepro.c: v0.13 11/08/2001 aris@cathedrallabs.org\n";
+       "eepro.c: v0.13b 09/13/2004 aris@cathedrallabs.org\n";
 
 #include <linux/module.h>
 
@@ -145,20 +146,22 @@ static const char version[] =
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/ethtool.h>
 
 #include <asm/system.h>
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
 #define DRV_NAME "eepro"
+#define DRV_VERSION "0.13c"
 
 #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
 /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
 #define SLOW_DOWN inb(0x80)
 /* udelay(2) */
 #define compat_init_data     __initdata
-
+enum iftype { AUI=0, BNC=1, TPE=2 };
 
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
@@ -214,6 +217,7 @@ struct eepro_local {
        short rcv_lower_limit;
        short rcv_upper_limit;
        unsigned char eeprom_reg;
+       unsigned short word[8];
 };
 
 /* The station (ethernet) address prefix, used for IDing the board. */
@@ -307,7 +311,7 @@ struct eepro_local {
 static int     eepro_probe1(struct net_device *dev, int autoprobe);
 static int     eepro_open(struct net_device *dev);
 static int     eepro_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t eepro_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t eepro_interrupt(int irq, void *dev_id);
 static void    eepro_rx(struct net_device *dev);
 static void    eepro_transmit_interrupt(struct net_device *dev);
 static int     eepro_close(struct net_device *dev);
@@ -548,8 +552,7 @@ static int __init do_eepro_probe(struct net_device *dev)
        {
                unsigned short int WS[32]=WakeupSeq;
 
-               if (check_region(WakeupPort, 2)==0) {
-
+               if (request_region(WakeupPort, 2, "eepro wakeup")) {
                        if (net_debug>5)
                                printk(KERN_DEBUG "Waking UP\n");
 
@@ -559,7 +562,10 @@ static int __init do_eepro_probe(struct net_device *dev)
                                outb_p(WS[i],WakeupPort);
                                if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
                        }
-               } else printk(KERN_WARNING "Checkregion Failed!\n");
+
+                       release_region(WakeupPort, 2);
+               } else
+                       printk(KERN_WARNING "PnP wakeup region busy!\n");
        }
 #endif
 
@@ -596,28 +602,29 @@ struct net_device * __init eepro_probe(int unit)
        err = do_eepro_probe(dev);
        if (err)
                goto out;
-       err = register_netdev(dev);
-       if (err)
-               goto out1;
        return dev;
-out1:
-       release_region(dev->base_addr, EEPRO_IO_EXTENT);
 out:
        free_netdev(dev);
        return ERR_PTR(err);
 }
 #endif
 
-static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
+static void __init printEEPROMInfo(struct net_device *dev)
 {
+       struct eepro_local *lp = (struct eepro_local *)dev->priv;
+       int ioaddr = dev->base_addr;
        unsigned short Word;
        int i,j;
 
-       for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
-               j+=read_eeprom(ioaddr,i,dev);
+       j = ee_Checksum;
+       for (i = 0; i < 8; i++)
+               j += lp->word[i];
+       for ( ; i < ee_SIZE; i++)
+               j += read_eeprom(ioaddr, i, dev);
+
        printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff);
 
-       Word=read_eeprom(ioaddr, 0, dev);
+       Word = lp->word[0];
        printk(KERN_DEBUG "Word0:\n");
        printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
        printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
@@ -625,7 +632,7 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
        printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
 
        if (net_debug>4)  {
-               Word=read_eeprom(ioaddr, 1, dev);
+               Word = lp->word[1];
                printk(KERN_DEBUG "Word1:\n");
                printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);
                printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));
@@ -636,7 +643,7 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
                printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
        }
 
-       Word=read_eeprom(ioaddr, 5, dev);
+       Word = lp->word[5];
        printk(KERN_DEBUG "Word5:\n");
        printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
        printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
@@ -646,12 +653,12 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
        if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI ");
        printk(KERN_DEBUG "port(s) \n");
 
-       Word=read_eeprom(ioaddr, 6, dev);
+       Word = lp->word[6];
        printk(KERN_DEBUG "Word6:\n");
        printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
        printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
 
-       Word=read_eeprom(ioaddr, 7, dev);
+       Word = lp->word[7];
        printk(KERN_DEBUG "Word7:\n");
        printk(KERN_DEBUG " INT to IRQ:\n");
 
@@ -700,7 +707,7 @@ static void __init eepro_print_info (struct net_device *dev)
                                        dev->name, (unsigned)dev->base_addr);
                        break;
                case LAN595FX:
-                       printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 
+                       printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
                                        dev->name, (unsigned)dev->base_addr);
                        break;
                case LAN595TX:
@@ -708,7 +715,7 @@ static void __init eepro_print_info (struct net_device *dev)
                                        dev->name, (unsigned)dev->base_addr);
                        break;
                case LAN595:
-                       printk("%s: Intel 82595-based lan card at %#x,", 
+                       printk("%s: Intel 82595-based lan card at %#x,",
                                        dev->name, (unsigned)dev->base_addr);
        }
 
@@ -721,11 +728,11 @@ static void __init eepro_print_info (struct net_device *dev)
 
        if (dev->irq > 2)
                printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]);
-       else 
+       else
                printk(", %s.\n", ifmap[dev->if_port]);
 
        if (net_debug > 3) {
-               i = read_eeprom(dev->base_addr, 5, dev);
+               i = lp->word[5];
                if (i & 0x2000) /* bit 13 of EEPROM word 5 */
                        printk(KERN_DEBUG "%s: Concurrent Processing is "
                                "enabled but not used!\n", dev->name);
@@ -733,23 +740,25 @@ static void __init eepro_print_info (struct net_device *dev)
 
        /* Check the station address for the manufacturer's code */
        if (net_debug>3)
-               printEEPROMInfo(dev->base_addr, dev);
+               printEEPROMInfo(dev);
 }
 
+static const struct ethtool_ops eepro_ethtool_ops;
+
 /* This is the real probe routine.  Linux has a history of friendly device
    probes on the ISA bus.  A good device probe avoids doing writes, and
    verifies that the correct device exists and functions.  */
 
 static int __init eepro_probe1(struct net_device *dev, int autoprobe)
 {
-       unsigned short station_addr[6], id, counter;
+       unsigned short station_addr[3], id, counter;
        int i;
        struct eepro_local *lp;
-       enum iftype { AUI=0, BNC=1, TPE=2 };
        int ioaddr = dev->base_addr;
+       int err;
 
        /* Grab the region so we can find another board if autoIRQ fails. */
-       if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { 
+       if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) {
                if (!autoprobe)
                        printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n",
                                ioaddr);
@@ -796,11 +805,16 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
                lp->xmt_bar = XMT_BAR_10;
                station_addr[0] = read_eeprom(ioaddr, 2, dev);
        }
-       station_addr[1] = read_eeprom(ioaddr, 3, dev);
-       station_addr[2] = read_eeprom(ioaddr, 4, dev);
+
+       /* get all words at once. will be used here and for ethtool */
+       for (i = 0; i < 8; i++) {
+               lp->word[i] = read_eeprom(ioaddr, i, dev);
+       }
+       station_addr[1] = lp->word[3];
+       station_addr[2] = lp->word[4];
 
        if (!lp->eepro) {
-               if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ)
+               if (lp->word[7] == ee_FX_INT2IRQ)
                        lp->eepro = 2;
                else if (station_addr[2] == SA_ADDR1)
                        lp->eepro = 1;
@@ -817,24 +831,24 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
        /* calculate {xmt,rcv}_{lower,upper}_limit */
        eepro_recalc(dev);
 
-       if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
+       if (GetBit(lp->word[5], ee_BNC_TPE))
                dev->if_port = BNC;
        else
                dev->if_port = TPE;
 
        if (dev->irq < 2 && lp->eepro != 0) {
                /* Mask off INT number */
-               int count = read_eeprom(ioaddr, 1, dev) & 7;
-               unsigned irqMask = read_eeprom(ioaddr, 7, dev);
+               int count = lp->word[1] & 7;
+               unsigned irqMask = lp->word[7];
+
                while (count--)
                        irqMask &= irqMask - 1;
+
                count = ffs(irqMask);
+
                if (count)
                        dev->irq = count - 1;
+
                if (dev->irq < 2) {
                        printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n");
                        goto exit;
@@ -842,7 +856,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
                        dev->irq = 9;
                }
        }
+
        dev->open               = eepro_open;
        dev->stop               = eepro_close;
        dev->hard_start_xmit    = eepro_send_packet;
@@ -850,16 +864,23 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
        dev->set_multicast_list = &set_multicast_list;
        dev->tx_timeout         = eepro_tx_timeout;
        dev->watchdog_timeo     = TX_TIMEOUT;
+       dev->ethtool_ops        = &eepro_ethtool_ops;
+
        /* print boot time info */
        eepro_print_info(dev);
 
        /* reset 82595 */
        eepro_reset(ioaddr);
+
+       err = register_netdev(dev);
+       if (err)
+               goto err;
        return 0;
 exit:
+       err = -ENODEV;
+err:
        release_region(dev->base_addr, EEPRO_IO_EXTENT);
-       return -ENODEV;
+       return err;
 }
 
 /* Open/initialize the board.  This is called (in the current kernel)
@@ -899,7 +920,7 @@ static int  eepro_grab_irq(struct net_device *dev)
 
                eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
 
-               if (request_irq (*irqp, NULL, SA_SHIRQ, "bogus", dev) != EBUSY) {
+               if (request_irq (*irqp, NULL, IRQF_SHARED, "bogus", dev) != EBUSY) {
                        unsigned long irq_mask;
                        /* Twinkle the interrupt, and check if it's seen */
                        irq_mask = probe_irq_on();
@@ -941,7 +962,7 @@ static int eepro_open(struct net_device *dev)
        if (net_debug > 3)
                printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
 
-       irqMask = read_eeprom(ioaddr,7,dev);
+       irqMask = lp->word[7];
 
        if (lp->eepro == LAN595FX_10ISA) {
                if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n");
@@ -973,16 +994,6 @@ static int eepro_open(struct net_device *dev)
                return -EAGAIN;
        }
 
-#ifdef irq2dev_map
-       if  (((irq2dev_map[dev->irq] != 0)
-               || (irq2dev_map[dev->irq] = dev) == 0) &&
-               (irq2dev_map[dev->irq]!=dev)) {
-               /* printk("%s: IRQ map wrong\n", dev->name); */
-               free_irq(dev->irq, dev);
-               return -EAGAIN;
-       }
-#endif
-
        /* Initialize the 82595. */
 
        eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
@@ -1028,8 +1039,8 @@ static int eepro_open(struct net_device *dev)
 
 
        /* Initialize the RCV and XMT upper and lower limits */
-       outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG); 
-       outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG); 
+       outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
+       outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
        outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg);
        outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg);
 
@@ -1046,12 +1057,12 @@ static int eepro_open(struct net_device *dev)
        eepro_clear_int(ioaddr);
 
        /* Initialize RCV */
-       outw(lp->rcv_lower_limit, ioaddr + RCV_BAR); 
+       outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
        lp->rx_start = lp->rcv_lower_limit;
-       outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP); 
+       outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
 
        /* Initialize XMT */
-       outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar); 
+       outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
        lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
        lp->tx_last = 0;
 
@@ -1070,8 +1081,6 @@ static int eepro_open(struct net_device *dev)
                old9 = inb(ioaddr + 9);
 
                if (irqMask==ee_FX_INT2IRQ) {
-                       enum iftype { AUI=0, BNC=1, TPE=2 };
-
                        if (net_debug > 3) {
                                printk(KERN_DEBUG "IrqMask: %#x\n",irqMask);
                                printk(KERN_DEBUG "i82595FX detected!\n");
@@ -1135,8 +1144,7 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
                printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
 
        if (length < ETH_ZLEN) {
-               skb = skb_padto(skb, ETH_ZLEN);
-               if (skb == NULL)
+               if (skb_padto(skb, ETH_ZLEN))
                        return 0;
                length = ETH_ZLEN;
        }
@@ -1178,19 +1186,13 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
        Handle the network interface interrupts. */
 
 static irqreturn_t
-eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+eepro_interrupt(int irq, void *dev_id)
 {
-       struct net_device *dev =  (struct net_device *)dev_id;
-                             /* (struct net_device *)(irq2dev_map[irq]);*/
+       struct net_device *dev = dev_id;
        struct eepro_local *lp;
        int ioaddr, status, boguscount = 20;
        int handled = 0;
 
-       if (dev == NULL) {
-                printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);
-                return IRQ_NONE;
-        }
-
        lp = netdev_priv(dev);
 
         spin_lock(&lp->lock);
@@ -1270,10 +1272,6 @@ static int eepro_close(struct net_device *dev)
        /* release the interrupt */
        free_irq(dev->irq, dev);
 
-#ifdef irq2dev_map
-       irq2dev_map[dev->irq] = 0;
-#endif
-
        /* Update the statistics here. What statistics? */
 
        return 0;
@@ -1315,7 +1313,6 @@ set_multicast_list(struct net_device *dev)
                mode = inb(ioaddr + REG3);
                outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
                eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
-               printk(KERN_INFO "%s: promiscuous mode enabled.\n", dev->name);
        }
 
        else if (dev->mc_count==0 )
@@ -1394,7 +1391,7 @@ set_multicast_list(struct net_device *dev)
                                outb(0x08, ioaddr + STATUS_REG);
 
                                if (i & 0x20) { /* command ABORTed */
-                                       printk(KERN_NOTICE "%s: multicast setup failed.\n", 
+                                       printk(KERN_NOTICE "%s: multicast setup failed.\n",
                                                dev->name);
                                        break;
                                } else if ((i & 0x0f) == 0x03)  { /* MC-Done */
@@ -1495,7 +1492,7 @@ hardware_send_packet(struct net_device *dev, void *buf, short length)
                end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
 
        if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */
-               if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {   
+               if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
                                /* Arrrr!!!, must keep the xmt header together,
                                several days were lost to chase this one down. */
                        last = lp->xmt_lower_limit;
@@ -1626,7 +1623,7 @@ eepro_rx(struct net_device *dev)
                        else if (rcv_status & 0x0800)
                                lp->stats.rx_crc_errors++;
 
-                       printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n", 
+                       printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
                                dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
                }
 
@@ -1657,10 +1654,10 @@ eepro_transmit_interrupt(struct net_device *dev)
 {
        struct eepro_local *lp = netdev_priv(dev);
        short ioaddr = dev->base_addr;
-       short boguscount = 25; 
+       short boguscount = 25;
        short xmt_status;
 
-       while ((lp->tx_start != lp->tx_end) && boguscount--) { 
+       while ((lp->tx_start != lp->tx_end) && boguscount--) {
 
                outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
                xmt_status = inw(ioaddr+IO_PORT);
@@ -1701,12 +1698,72 @@ eepro_transmit_interrupt(struct net_device *dev)
        }
 }
 
+static int eepro_ethtool_get_settings(struct net_device *dev,
+                                       struct ethtool_cmd *cmd)
+{
+       struct eepro_local      *lp = (struct eepro_local *)dev->priv;
+
+       cmd->supported =        SUPPORTED_10baseT_Half |
+                               SUPPORTED_10baseT_Full |
+                               SUPPORTED_Autoneg;
+       cmd->advertising =      ADVERTISED_10baseT_Half |
+                               ADVERTISED_10baseT_Full |
+                               ADVERTISED_Autoneg;
+
+       if (GetBit(lp->word[5], ee_PortTPE)) {
+               cmd->supported |= SUPPORTED_TP;
+               cmd->advertising |= ADVERTISED_TP;
+       }
+       if (GetBit(lp->word[5], ee_PortBNC)) {
+               cmd->supported |= SUPPORTED_BNC;
+               cmd->advertising |= ADVERTISED_BNC;
+       }
+       if (GetBit(lp->word[5], ee_PortAUI)) {
+               cmd->supported |= SUPPORTED_AUI;
+               cmd->advertising |= ADVERTISED_AUI;
+       }
+
+       cmd->speed = SPEED_10;
+
+       if (dev->if_port == TPE && lp->word[1] & ee_Duplex) {
+               cmd->duplex = DUPLEX_FULL;
+       }
+       else {
+               cmd->duplex = DUPLEX_HALF;
+       }
+
+       cmd->port = dev->if_port;
+       cmd->phy_address = dev->base_addr;
+       cmd->transceiver = XCVR_INTERNAL;
+
+       if (lp->word[0] & ee_AutoNeg) {
+               cmd->autoneg = 1;
+       }
+
+       return 0;
+}
+
+static void eepro_ethtool_get_drvinfo(struct net_device *dev,
+                                       struct ethtool_drvinfo *drvinfo)
+{
+       strcpy(drvinfo->driver, DRV_NAME);
+       strcpy(drvinfo->version, DRV_VERSION);
+       sprintf(drvinfo->bus_info, "ISA 0x%lx", dev->base_addr);
+}
+
+static const struct ethtool_ops eepro_ethtool_ops = {
+       .get_settings   = eepro_ethtool_get_settings,
+       .get_drvinfo    = eepro_ethtool_get_drvinfo,
+};
+
 #ifdef MODULE
 
 #define MAX_EEPRO 8
 static struct net_device *dev_eepro[MAX_EEPRO];
 
-static int io[MAX_EEPRO];
+static int io[MAX_EEPRO] = {
+  [0 ... MAX_EEPRO-1] = -1
+};
 static int irq[MAX_EEPRO];
 static int mem[MAX_EEPRO] = {  /* Size of the rx buffer in KB */
   [0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024
@@ -1716,37 +1773,38 @@ static int autodetect;
 static int n_eepro;
 /* For linux 2.1.xx */
 
-MODULE_AUTHOR("Pascal Dupuis, and aris@cathedrallabs.org");
+MODULE_AUTHOR("Pascal Dupuis and others");
 MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(autodetect, "1-" __MODULE_STRING(1) "i");
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+module_param(autodetect, int, 0);
 MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)");
 MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
 MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
 MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
 
-int
-init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev;
        int i;
-       if (io[0] == 0 && autodetect == 0) {
+       if (io[0] == -1 && autodetect == 0) {
                printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
                printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");
-               return 1;
+               return -ENODEV;
        }
        else if (autodetect) {
                /* if autodetect is set then we must force detection */
-               io[0] = 0;
+               for (i = 0; i < MAX_EEPRO; i++) {
+                       io[i] = 0;
+               }
 
                printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
        }
 
-       for (i = 0; i < MAX_EEPRO; i++) {
+       for (i = 0; io[i] != -1 && i < MAX_EEPRO; i++) {
                dev = alloc_etherdev(sizeof(struct eepro_local));
                if (!dev)
                        break;
@@ -1756,11 +1814,8 @@ init_module(void)
                dev->irq = irq[i];
 
                if (do_eepro_probe(dev) == 0) {
-                       if (register_netdev(dev) == 0) {
-                               dev_eepro[n_eepro++] = dev;
-                               continue;
-                       }
-                       release_region(dev->base_addr, EEPRO_IO_EXTENT);
+                       dev_eepro[n_eepro++] = dev;
+                       continue;
                }
                free_netdev(dev);
                break;
@@ -1772,7 +1827,7 @@ init_module(void)
        return n_eepro ? 0 : -ENODEV;
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        int i;