hello,
        this is the patch for eepro that makes possible the use of
etherexpress 10 (82595FX based cards) with eepro driver. please, who has
cards that is supported by eepro (i only have ee10) please test this
patch. all feedback is welcome. Thanks,

                                                                Aris

---------------------------------------------------------------------------
Aristeu Sergio Rozanski Filho                         [EMAIL PROTECTED]
---------------------------------------------------------------------------

--- linux/drivers/net/eepro.c.old       Wed Apr 26 14:54:45 2000
+++ linux/drivers/net/eepro.c   Wed Apr 26 14:54:59 2000
@@ -23,6 +23,8 @@
        This is a compatibility hardware problem.
 
        Versions:
+       0.12    added support to 82595FX etherexpress 10 based cards
+                (aris <[EMAIL PROTECTED]>), 04/26/2000)
        0.11e   some tweaks about multiple cards support (PdP, jul/aug 1999)
        0.11d   added __initdata, __initfunc stuff; call spin_lock_init
                in eepro_probe1. Replaced "eepro" by dev->name. Augmented 
@@ -93,7 +95,7 @@
 */
 
 static const char *version =
-       "eepro.c: v0.11d 08/12/1998 [EMAIL PROTECTED]\n";
+       "eepro.c: v0.12 04/26/2000 [EMAIL PROTECTED]\n";
 
 #include <linux/module.h>
 
@@ -176,7 +178,12 @@
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int eepro_portlist[] compat_init_data =
-   { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
+#ifdef PnPWakeup
+   { 0x210, 0x300,
+#else
+   { 0x300, 0x210, 
+#endif
+   0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
 /* note: 0x300 is default, the 595FX supports ALL IO Ports 
   from 0x000 to 0x3F0, some of which are reserved in PCs */
 
@@ -199,6 +206,9 @@
 #define        LAN595TX        1
 #define        LAN595FX        2
 
+/* global to recall the read_eepro */
+static unsigned char etherexpress10 = 0;
+
 /* Information that need to be kept for each board. */
 struct eepro_local {
        struct enet_statistics stats;
@@ -215,6 +225,7 @@
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
        spinlock_t lock; /* Serializing lock  */ 
 #endif
+       int tx_count;
 };
 
 /* The station (ethernet) address prefix, used for IDing the board. */
@@ -350,18 +361,33 @@
 buffer (transmit-buffer = 32K - receive-buffer).
 
 */
+
+/* now this section could be used by both boards: the oldies and the ee10:
+ * ee10 uses tx buffer before of rx buffer and the oldies the inverse.
+ * (aris)
+ */
 #define        RAM_SIZE        0x8000
+
 #define        RCV_HEADER      8
-#define RCV_RAM        0x6000  /* 24KB default for RCV buffer */
-#define RCV_LOWER_LIMIT 0x00    /* 0x0000 */
-/* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */    /* 0x5ffe */
-#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)   
-/* #define XMT_RAM         (RAM_SIZE - RCV_RAM) */    /* 8KB for XMT buffer */
-#define XMT_RAM         (RAM_SIZE - (rcv_ram))    /* 8KB for XMT buffer */
-/* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */  /* 0x6000 */
-#define XMT_LOWER_LIMIT ((rcv_ram) >> 8) 
-#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8)   /* 0x7ffe */
-#define        XMT_HEADER      8
+#define RCV_DEFAULT_RAM        0x6000
+#define RCV_RAM        rcv_ram
+
+static unsigned rcv_ram = RCV_DEFAULT_RAM;
+
+#define XMT_HEADER     8
+#define XMT_RAM                (RAM_SIZE - RCV_RAM)
+
+#define XMT_START      ((rcv_start + RCV_RAM) % RAM_SIZE)
+
+#define RCV_LOWER_LIMIT        (rcv_start >> 8)
+#define RCV_UPPER_LIMIT        (((rcv_start + RCV_RAM) - 2) >> 8)
+#define XMT_LOWER_LIMIT        (XMT_START >> 8)
+#define XMT_UPPER_LIMIT        (((XMT_START + XMT_RAM) - 2) >> 8)
+
+#define RCV_START_PRO  0x00
+#define RCV_START_10   XMT_RAM
+                                       /* by default the old driver */
+static unsigned rcv_start = RCV_START_PRO;
 
 #define        RCV_DONE        0x0008
 #define        RX_OK           0x2000
@@ -407,7 +433,11 @@
 #define        IO_32_BIT       0x10
 #define        RCV_BAR         0x04    /* The following are word (16-bit) registers 
*/
 #define        RCV_STOP        0x06
-#define        XMT_BAR         0x0a
+
+#define        XMT_BAR_PRO     0x0a
+#define        XMT_BAR_10      0x0b
+static unsigned xmt_bar = XMT_BAR_PRO;
+
 #define        HOST_ADDRESS_REG        0x0c
 #define        IO_PORT         0x0e
 #define        IO_PORT_32_BIT  0x0c
@@ -419,8 +449,13 @@
 #define INT_NO_REG     0x02
 #define        RCV_LOWER_LIMIT_REG     0x08
 #define        RCV_UPPER_LIMIT_REG     0x09
-#define        XMT_LOWER_LIMIT_REG     0x0a
-#define        XMT_UPPER_LIMIT_REG     0x0b
+
+#define        XMT_LOWER_LIMIT_REG_PRO 0x0a
+#define        XMT_UPPER_LIMIT_REG_PRO 0x0b
+#define        XMT_LOWER_LIMIT_REG_10  0x0b
+#define        XMT_UPPER_LIMIT_REG_10  0x0a
+static unsigned xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
+static unsigned xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
 
 /* Bank 2 registers */
 #define        XMT_Chain_Int   0x20    /* Interrupt at the end of the transmit chain 
*/
@@ -443,7 +478,10 @@
 #define        I_ADD_REG4      0x08
 #define        I_ADD_REG5      0x09
 
-#define EEPROM_REG 0x0a
+#define EEPROM_REG_PRO 0x0a
+#define EEPROM_REG_10  0x0b
+static unsigned eeprom_reg = EEPROM_REG_PRO;
+
 #define EESK 0x01
 #define EECS 0x02
 #define EEDI 0x04
@@ -457,17 +495,15 @@
    (detachable devices only).
    */
 #ifdef HAVE_DEVLIST
-/* Support for an alternate probe manager, which will eliminate the
-   boilerplate below. */
+       /* Support for an alternate probe manager, which will eliminate the
+                                                       boilerplate below. */
 struct netdev_entry netcard_drv =
-{"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
+               {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
 #else
 compat_init_func(int eepro_probe(struct device *dev))
 {
        int i;
        int base_addr = dev ? dev->base_addr : 0;
-
-
 #ifdef PnPWakeup
        /* XXXX for multiple cards should this only be run once? */
        
@@ -480,9 +516,7 @@
 
        {
                unsigned short int WS[32]=WakeupSeq;
-
                if (check_region(WakeupPort, 2)==0) {
-
                        if (net_debug>5)
                                printk(KERN_DEBUG "Waking UP\n");
 
@@ -503,7 +537,6 @@
        else if (base_addr != 0)        /* Don't probe at all. */
                return ENXIO;
 
-
        for (i = 0; eepro_portlist[i]; i++) {
                int ioaddr = eepro_portlist[i];
 
@@ -512,12 +545,12 @@
                if (eepro_probe1(dev, ioaddr) == 0)
                        return 0;
        }
-
+       
        return ENODEV;
 }
 #endif
 
-void printEEPROMInfo(short ioaddr)
+static void printEEPROMInfo(short ioaddr)
 {
        unsigned short Word;
        int i,j;
@@ -597,7 +630,6 @@
                /* We seem to have the 82595 signature, let's
                   play with its counter (last 2 bits of
                   register 2 of bank 0) to be sure. */
-       
                counter = (id & R_ROBIN_BITS);  
                if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) == 
                        (counter + 0x40)) {
@@ -608,21 +640,41 @@
                           the EEPROM */
 
                        station_addr[0] = read_eeprom(ioaddr, 2);
+
+                       /* FIXME - find another way to know that we've found
+                        * a Etherexpress 10
+                        */
+                       if (station_addr[0] == 0x0000 ||
+                           station_addr[0] == 0xffff) {
+                               etherexpress10 = 1;
+                               eeprom_reg = EEPROM_REG_10;
+                               rcv_start = RCV_START_10;
+                               xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
+                               xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
+                               xmt_bar = XMT_BAR_10;
+                               station_addr[0] = read_eeprom(ioaddr, 2);
+                       }
+                       
                        station_addr[1] = read_eeprom(ioaddr, 3);
                        station_addr[2] = read_eeprom(ioaddr, 4);
 
                        /* Check the station address for the manufacturer's code */
                        if (net_debug>3)
                                printEEPROMInfo(ioaddr);
-                               
-                       if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ 
Mask */
+
+                       if (etherexpress10) {
+                               eepro = 2;
+                               printk("%s: Intel EtherExpress 10 ISA\n at %#x,",
+                                       dev->name, ioaddr);
+                       } else if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) {
+                                                /* int to IRQ Mask */
                                eepro = 2;
                                printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 

                                        dev->name, ioaddr);
                        } else
                        if (station_addr[2] == 0x00aa)  {
                                eepro = 1;
-                               printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", 
+                               printk("%s: Intel EtherExpress Pro/10 ISA at %#x,",
                                        dev->name, ioaddr);
                        }
                        else {
@@ -638,18 +690,26 @@
                                dev->dev_addr[i] = ((unsigned char *) 
station_addr)[5-i];
                                printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
                        }
-                       
+
+                       dev->mem_start = (RCV_LOWER_LIMIT << 8);
+
                        if ((dev->mem_end & 0x3f) < 3 ||        /* RX buffer must be 
more than 3K */
                                (dev->mem_end & 0x3f) > 29)     /* and less than 29K 
*/
-                               dev->mem_end = RCV_RAM;         /* or it will be set 
to 24K */
-                       else dev->mem_end = 1024*dev->mem_end;  /* Maybe I should 
shift << 10 */
+                               dev->mem_end = (RCV_UPPER_LIMIT << 8);
+                       else {
+                               dev->mem_end = (dev->mem_end * 1024) +
+                                                       (RCV_LOWER_LIMIT << 8);
+                               rcv_ram = dev->mem_end - (RCV_LOWER_LIMIT << 8);
+                       }
 
-                       /* From now on, dev->mem_end contains the actual size of rx 
buffer */
+                       /* From now on, dev->mem_end - dev->mem_start contains 
+                        * the actual size of rx buffer 
+                        */
                        
                        if (net_debug > 3)
-                               printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
-                               
-                               
+                               printk(", %dK RCV buffer",
+                                               (int)(dev->mem_end - 
+dev->mem_start)/1024);
+                                                               
                        /* ............... */
 
                        if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE))
@@ -678,10 +738,8 @@
                                                return ENODEV;
                                } else 
                                
-                               if (dev->irq==2) dev->irq = 9;
-
-                               else if (dev->irq == 2)
-                               dev->irq = 9;
+                               if (dev->irq==2)
+                                       dev->irq = 9;
                        }
                        
                        if (dev->irq > 2) {
@@ -690,9 +748,6 @@
                        }
                        else printk(", %s.\n", ifmap[dev->if_port]);
                        
-                       if ((dev->mem_start & 0xf) > 0) /* I don't know if this is */
-                               net_debug = dev->mem_start & 7; /* still useful or not 
*/
-
                        if (net_debug > 3) {
                                i = read_eeprom(ioaddr, 5);
                                if (i & 0x2000) /* bit 13 of EEPROM word 5 */
@@ -809,7 +864,8 @@
 {
        unsigned short temp_reg, old8, old9;
        int irqMask;
-       int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
+       int i, ioaddr = dev->base_addr;
+
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
 
        if (net_debug > 3)
@@ -854,7 +910,7 @@
        /* Initialize the 82595. */
 
        outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
-       temp_reg = inb(ioaddr + EEPROM_REG);
+       temp_reg = inb(ioaddr + eeprom_reg);
 
        lp->stepping = temp_reg >> 5;   /* Get the stepping number of the 595 */
        
@@ -862,8 +918,8 @@
                printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping);
 
        if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
-               outb(temp_reg & 0xef, ioaddr + EEPROM_REG);
-       for (i=0; i < 6; i++) 
+               outb(temp_reg & 0xef, ioaddr + eeprom_reg);
+       for (i=0; i < 6; i++)
                outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); 
                        
        temp_reg = inb(ioaddr + REG1);    /* Setup Transmit Chaining */
@@ -885,7 +941,6 @@
                outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG);
        else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); 
 
-
        temp_reg = inb(ioaddr + INT_NO_REG);
        if (lp->eepro == 2)
                outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
@@ -898,8 +953,8 @@
        /* Initialize the RCV and XMT upper and lower limits */
        outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); 
        outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); 
-       outb(XMT_LOWER_LIMIT, ioaddr + XMT_LOWER_LIMIT_REG); 
-       outb(XMT_UPPER_LIMIT, ioaddr + XMT_UPPER_LIMIT_REG); 
+       outb(XMT_LOWER_LIMIT, ioaddr + xmt_lower_limit_reg); 
+       outb(XMT_UPPER_LIMIT, ioaddr + xmt_upper_limit_reg); 
 
        /* Enable the interrupt line. */
        temp_reg = inb(ioaddr + REG1);
@@ -914,12 +969,12 @@
        outb(ALL_MASK, ioaddr + STATUS_REG); 
 
        /* Initialize RCV */
-       outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR); 
-       lp->rx_start = (RCV_LOWER_LIMIT << 8) ;
-       outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP); 
+       outw((RCV_LOWER_LIMIT << 8), ioaddr + RCV_BAR); 
+       lp->rx_start = (RCV_LOWER_LIMIT << 8);
+       outw(((RCV_UPPER_LIMIT << 8) | 0xfe), ioaddr + RCV_STOP); 
 
        /* Initialize XMT */
-       outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR); 
+       outw((XMT_LOWER_LIMIT << 8), ioaddr + xmt_bar); 
 
        /* Check for the i82595TX and i82595FX */
        old8 = inb(ioaddr + 8);
@@ -969,8 +1024,9 @@
        SLOW_DOWN;
        SLOW_DOWN;
 
-       lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
+       lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8);
        lp->tx_last = 0;
+       lp->tx_count = 0;
        
        dev->tbusy = 0;
        dev->interrupt = 0;
@@ -989,22 +1045,22 @@
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        int ioaddr = dev->base_addr;
-       int rcv_ram = dev->mem_end;
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
        unsigned long flags;
 #endif
-       
+
        if (net_debug > 5)
                printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", 
dev->name);
-       
+
        if (dev->tbusy) {
                /* If we get here, some higher level has decided we are broken.
                   There should really be a "kick me" function call instead. */
                int tickssofar = jiffies - dev->trans_start;
+
                if (tickssofar < 40)
                        return 1;
-       
+                       
                /* if (net_debug > 1) */
                printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name, 
                        "network cable problem");
@@ -1021,8 +1077,9 @@
                SLOW_DOWN;
 
                /* Do I also need to flush the transmit buffers here? YES? */
-               lp->tx_start = lp->tx_end = rcv_ram; 
+               lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8); 
                lp->tx_last = 0;
+               lp->tx_count = 0;
        
                dev->tbusy=0;
                dev->trans_start = jiffies;
@@ -1056,12 +1113,16 @@
        } else {
                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
                unsigned char *buf = skb->data;
+               int discard = lp->stats.tx_dropped;
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
                lp->stats.tx_bytes+=skb->len;
 #endif
-
                hardware_send_packet(dev, buf, length);
+
+               if (lp->stats.tx_dropped != discard)
+                       return 1;
+               
                dev->trans_start = jiffies;
 
        }
@@ -1112,6 +1173,7 @@
 
                return;
        }
+
        dev->interrupt = 1;
 
        if (net_debug > 5)
@@ -1119,33 +1181,36 @@
        
        ioaddr = dev->base_addr;
 
-       do { 
-               status = inb(ioaddr + STATUS_REG);
-               
+       while (((status = inb(ioaddr + STATUS_REG)) & 0x06) && (boguscount--)) 
+       {
+               switch (status & (RX_INT | TX_INT)) {
+                       case (RX_INT | TX_INT):
+                               outb (RX_INT | TX_INT, ioaddr + STATUS_REG);
+                               break;
+                       case RX_INT:
+                               outb (RX_INT, ioaddr + STATUS_REG);
+                               break;
+                       case TX_INT:
+                               outb (TX_INT, ioaddr + STATUS_REG);
+                               break;
+               }
                if (status & RX_INT) {
                        if (net_debug > 4)
-                       printk(KERN_DEBUG "%s: packet received interrupt.\n", 
dev->name);
+                               printk(KERN_DEBUG "%s: packet received interrupt.\n", 
+dev->name);
 
-                       /* Acknowledge the RX_INT */
-                       outb(RX_INT, ioaddr + STATUS_REG);
                        /* Get the received packets */
                        eepro_rx(dev);
                }
-
-               else if (status & TX_INT) {
+               if (status & TX_INT) {
                        if (net_debug > 4)
-                       printk(KERN_DEBUG "%s: packet transmit interrupt.\n", 
dev->name);
-
-                       /* Acknowledge the TX_INT */
-                       outb(TX_INT, ioaddr + STATUS_REG); 
+                               printk(KERN_DEBUG "%s: packet transmit interrupt.\n", 
+dev->name);
 
                        /* Process the status of transmitted packets */
                        eepro_transmit_interrupt(dev);
                }
+       }
        
-       } while ((boguscount-- > 0) && (status & 0x06));
-
-       dev->interrupt = 0; 
+       dev->interrupt = 0;
 
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", 
dev->name);
@@ -1153,6 +1218,7 @@
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
        spin_unlock(&lp->lock);
 #endif
+
        return;
 }
 
@@ -1160,7 +1226,6 @@
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        int ioaddr = dev->base_addr;
-       int rcv_ram = dev->mem_end;
        short temp_reg;
 
        dev->tbusy = 1;
@@ -1176,8 +1241,9 @@
 
        /* Flush the Tx and disable Rx. */
        outb(STOP_RCV_CMD, ioaddr); 
-       lp->tx_start = lp->tx_end = rcv_ram ;
+       lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8);
        lp->tx_last = 0;
+       lp->tx_count = 0;
 
        /* Mask all the interrupts. */
        outb(ALL_MASK, ioaddr + INT_MASK_REG); 
@@ -1289,7 +1355,7 @@
                outw(eaddrs[0], ioaddr + IO_PORT);
                outw(eaddrs[1], ioaddr + IO_PORT);
                outw(eaddrs[2], ioaddr + IO_PORT);
-               outw(lp->tx_end, ioaddr + XMT_BAR);
+               outw(lp->tx_end, ioaddr + xmt_bar);
                outb(MC_SETUP, ioaddr);
 
                /* Update the transmit queue */
@@ -1351,10 +1417,19 @@
 {
        int i;
        unsigned short retval = 0;
-       short ee_addr = ioaddr + EEPROM_REG;
+       short ee_addr = ioaddr + eeprom_reg;
        int read_cmd = location | EE_READ_CMD;
        short ctrl_val = EECS ;
        
+       /* XXXX - this is not the final version. We must test this on other
+        *        boards other than eepro10. I think that it won't let other
+        *        boards to fail. (aris)
+        */
+       if (etherexpress10) {
+               outb(BANK1_SELECT, ioaddr);
+               outb(0x00, ioaddr + STATUS_REG);
+       }
+               
        outb(BANK2_SELECT, ioaddr);
        outb(ctrl_val, ee_addr);
        
@@ -1391,14 +1466,21 @@
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        short ioaddr = dev->base_addr;
-       int rcv_ram = dev->mem_end;
+
        unsigned status, tx_available, last, end, boguscount = 100;
 
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", 
dev->name);
 
-       while (boguscount-- > 0) {
+       if (etherexpress10 && lp->tx_count) {
+               eepro_transmit_interrupt(dev);
+               if (lp->tx_count) {
+                       lp->stats.tx_dropped++;
+                       return;
+               }
+       }               
 
+       while (boguscount-- > 0) {
                /* Disable RX and TX interrupts.  Necessary to avoid
                corruption of the HOST_ADDRESS_REG by interrupt
                service routines. */
@@ -1406,7 +1488,7 @@
 
                if (dev->interrupt == 1) {
                        /* Enable RX and TX interrupts */
-                       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+                       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
                        continue;
                }
 
@@ -1430,21 +1512,21 @@
                last = lp->tx_end;
                end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
 
-               if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */
-               
-                       if ((RAM_SIZE - last) <= XMT_HEADER) {  
+               if (end >= (XMT_UPPER_LIMIT << 8)) { /* the transmit buffer is wrapped 
+around */
+                       if (((XMT_UPPER_LIMIT << 8) - last) <= XMT_HEADER) {
                                /* Arrrr!!!, must keep the xmt header together,
                                several days were lost to chase this one down. */
                                
-                               last = rcv_ram;
+                               last = (XMT_LOWER_LIMIT << 8);
                                end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
                        }
-                       
-                       else end = rcv_ram + (end - RAM_SIZE);
+                       else end = (XMT_LOWER_LIMIT << 8) + (end - XMT_RAM);
                }
 
+               lp->tx_count++;
+
                outw(last, ioaddr + HOST_ADDRESS_REG);
-               outw(XMT_CMD, ioaddr + IO_PORT); 
+               outw(XMT_CMD, ioaddr + IO_PORT);
                outw(0, ioaddr + IO_PORT);
                outw(end, ioaddr + IO_PORT);
                outw(length, ioaddr + IO_PORT);
@@ -1461,15 +1543,14 @@
                /* A dummy read to flush the DRAM write pipeline */
                status = inw(ioaddr + IO_PORT); 
 
-               if (lp->tx_start == lp->tx_end) {       
-                       outw(last, ioaddr + XMT_BAR);
-                       outb(XMT_CMD, ioaddr);
+               if (lp->tx_start == lp->tx_end) {
+                       outw(last, ioaddr + xmt_bar);
+                       outb(XMT_CMD, ioaddr);                  
                        lp->tx_start = last;   /* I don't like to change tx_start here 
*/
                }
                else {
                        /* update the next address and the chain bit in the 
                        last packet */
-                       
                        if (lp->tx_end != last) {
                                outw(lp->tx_last + XMT_CHAIN, ioaddr + 
HOST_ADDRESS_REG);
                                outw(last, ioaddr + IO_PORT); 
@@ -1478,7 +1559,6 @@
                        outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
                        status = inw(ioaddr + IO_PORT); 
                        outw(status | CHAIN_BIT, ioaddr + IO_PORT);
-
                        /* Continue the transmit command */
                        outb(RESUME_XMT_CMD, ioaddr);
                }
@@ -1498,7 +1578,9 @@
                return;
        }
 
+       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
        dev->tbusy = 1;
+
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", 
dev->name);
 }
@@ -1507,14 +1589,17 @@
 eepro_rx(struct device *dev)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
-       short ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
+       short ioaddr = dev->base_addr;
+               
        short boguscount = 20;
-       short rcv_car = lp->rx_start;
+       unsigned rcv_car = lp->rx_start;
        unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
 
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);
        
+       outb(ALL_MASK, ioaddr + STATUS_REG);
+       
        /* Set the read pointer to the start of the RCV */
        outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
        
@@ -1589,12 +1674,14 @@
 
        } 
        if (rcv_car == 0)
-               rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+               rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff);
                
        outw(rcv_car - 1, ioaddr + RCV_STOP);
 
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);
+
+       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
 }
 
 static void
@@ -1603,8 +1690,8 @@
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        short ioaddr = dev->base_addr;
        short boguscount = 20; 
-       short xmt_status;
-       
+       unsigned xmt_status;
+
        /*
        if (dev->tbusy == 0) {
                printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
@@ -1613,30 +1700,72 @@
                        dev->name);
        }
        */
+       while (lp->tx_start != lp->tx_end && boguscount) {
 
-       while (lp->tx_start != lp->tx_end) { 
-       
-               outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); 
+               outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
                xmt_status = inw(ioaddr+IO_PORT);
-               
-               if ((xmt_status & TX_DONE_BIT) == 0) break;
+
+               if ((xmt_status & TX_DONE_BIT) == 0) {
+                       udelay(40);
+                       boguscount--;
+                       continue;
+               }
+
+               lp->tx_count--;
 
                xmt_status = inw(ioaddr+IO_PORT); 
                lp->tx_start = inw(ioaddr+IO_PORT);
 
+               if (etherexpress10) {
+                       lp->tx_start = (XMT_LOWER_LIMIT << 8);
+                       lp->tx_end = lp->tx_start;
+       
+                       /* yeah, black magic :( */
+                       outb(BANK0_SELECT, ioaddr);
+                       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+               
+                       outb(RCV_DISABLE_CMD, ioaddr);
+                       outb(RCV_ENABLE_CMD, ioaddr);
+               }
+
                dev->tbusy = 0;
+               
                mark_bh(NET_BH);
-
-               if (xmt_status & 0x2000)
+               
+               if (xmt_status & 0x2000) {
                        lp->stats.tx_packets++; 
+               }
                else {
                        lp->stats.tx_errors++;
-                       if (xmt_status & 0x0400)
+                       if (xmt_status & 0x0400) {
                                lp->stats.tx_carrier_errors++;
-                       printk("%s: XMT status = %#x\n",
-                               dev->name, xmt_status);
-                       printk(KERN_DEBUG "%s: XMT status = %#x\n",
-                               dev->name, xmt_status);
+                               printk(KERN_DEBUG "%s: carrier error\n",
+                                       dev->name);
+                               printk(KERN_DEBUG "%s: XMT status = %#x\n",
+                                       dev->name, xmt_status);
+                       }
+                       else {
+                               printk(KERN_DEBUG "%s: XMT status = %#x\n",
+                                       dev->name, xmt_status);
+                               printk(KERN_DEBUG "%s: XMT status = %#x\n",
+                                       dev->name, xmt_status);
+                       }
+                       
+                       if (etherexpress10) {
+                               /* Try to restart the adaptor. */
+                               outb(SEL_RESET_CMD, ioaddr); 
+                               lp->tx_count = 0;
+                       
+                               /* We are supposed to wait for 2 us after a SEL_RESET 
+*/
+                               SLOW_DOWN;
+                               SLOW_DOWN;
+
+                               /* first enable interrupts */
+                               outb(BANK0_SELECT, ioaddr);
+                               outb(ALL_MASK & ~(RX_INT | TX_INT), ioaddr + 
+STATUS_REG);
+                       
+                               outb(RCV_ENABLE_CMD, ioaddr);
+                       }
                }
                
                if (xmt_status & 0x000f) {
@@ -1646,9 +1775,7 @@
                if ((xmt_status & 0x0040) == 0x0) {
                        lp->stats.tx_heartbeat_errors++;
                }
-
-               if (--boguscount == 0)
-                       break;
+               boguscount--;
        }
 }
 
@@ -1658,17 +1785,12 @@
 static char devicename[MAX_EEPRO][9];
 static struct device dev_eepro[MAX_EEPRO];
 
-static int io[MAX_EEPRO] = {
-#ifdef PnPWakeup
-  0x210,  /*: default for PnP enabled FX chips */
-#else
-  0x200,  /* Why? */
-#endif
-  [1 ... MAX_EEPRO - 1] = -1 };
+static int io[MAX_EEPRO];
 static int irq[MAX_EEPRO] = { [0 ... MAX_EEPRO-1] = 0 };
 static int mem[MAX_EEPRO] = {  /* Size of the rx buffer in KB */
-  [0 ... MAX_EEPRO-1] = RCV_RAM/1024
+  [0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024
 };
+static int autodetect;
 
 static int n_eepro = 0;
 /* For linux 2.1.xx */
@@ -1678,19 +1800,30 @@
 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");
 #endif 
 
 int 
 init_module(void)
 {
-       if (io[0] == 0)
-               printk("eepro_init_module: You should not use auto-probing with 
insmod!\n");
-
-       while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) {
+       int i;
+       if (io[0] == 0 && autodetect == 0) {
+               printk("eepro_init_module: Probe is very dangerous in ISA boards!\n");
+               printk("eepro_init_module: Please add \"autodetect=1\" to force 
+probe\n");
+               return 1;
+       }
+       else if (autodetect) {
+               /* if autodetect is set then we must force detection */
+               io[0] = 0;
+               
+               printk("eepro_init_module: Auto-detecting boards (May God protect 
+us...)\n");
+       }       
+       
+       for (i = 0; i < MAX_EEPRO; i++) {
                struct device *d = &dev_eepro[n_eepro];
                d->name         = devicename[n_eepro]; /* inserted by 
drivers/net/net_init.c */
-               d->mem_end      = mem[n_eepro];
-               d->base_addr    = io[n_eepro];
+               d->mem_end      = mem[n_eepro];         
+               d->base_addr    = io[0];
                d->irq          = irq[n_eepro];
                d->init         = eepro_probe;
 

Reply via email to