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;