[259] in linux-net channel archive

home help back first fref pref prev next nref lref last post

3c503 --- memory saver

daemon@ATHENA.MIT.EDU (Paul Gortmaker)
Sun Apr 30 06:51:34 1995

From: Paul Gortmaker <gpg109@rsphy1.anu.edu.au>
To: linux-net@vger.rutgers.edu
Date: Sun, 30 Apr 1995 19:57:17 +1000 (EST)

	Here is a patch I have had kicking around for a while. As you may
or may not know, the 3c503 has the ability to support PIO transfers
to the card (akin to a ne2000) instead of the standard (read faster/better)
shared memory implementation.

	However, since it is slower, and the 8390 is buggy for PIO usage,
you shouldn't use a 3c503 in PIO mode. If you do, the linux driver will
print a message like "REJUMPER FOR SHARED MEMORY" at boot, and then still
try and use it in the crippled PIO mode.

This patch just #ifdef's out all the PIO code based on whether you have
defined CONFIG_EL2_PIO, for a 20% reduction in the driver size, as
seen below. This may be useful for 2 and 4MB machines.

=========================================
with PIO support
text    data    bss     dec     hex
3576    44      0       3620    e24
-rw-------   1 root     root         4964 Apr 13 19:50 3c503.o

without PIO support
text    data    bss     dec     hex
2700    44      0       2744    ab8
-rw-------   1 root     root         4005 Apr 15 15:33 3c503.o
=========================================

This doesn't change the driver behaviour in any other way, so I
wouldn't expect it to fix any problems you might already have.
However, it means two less "if (dev->mem_start)" per Rx packet,
and one less per Tx, so you may see a 0.0001% performance increase. ;-)

Have fun with it.
Paul.

--- 3c503.c.old	Sun Apr 30 17:06:31 1995
+++ 3c503.c	Sun Apr 30 17:07:24 1995
@@ -12,8 +12,8 @@
        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.
+    in shared memory mode for best performance, although it can be
+    configured to work in programmed-I/O mode.
 
     Sources:
     EtherLink II Technical Reference Guide,
@@ -25,6 +25,12 @@
 static char *version =
     "3c503.c:v1.10 9/23/93  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
+/* Do we support the slower, bug-ridden PIO mode of the 8390? */
+/* #define CONFIG_EL2_PIO */
+
+/* Do we do a quick test on the card's memory at boot? */
+/* #define CONFIG_EL2_MEMTEST */
+
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
@@ -56,9 +62,11 @@
    the other for the typical I/O probe. */
 struct netdev_entry el2_drv =
 {"3c503", el2_probe, EL1_IO_EXTENT, 0};
+#ifdef CONFIG_EL2_PIO
 struct netdev_entry el2pio_drv =
 {"3c503pio", el2_pioprobe1, EL1_IO_EXTENT, netcard_portlist};
 #endif
+#endif
 
 static int el2_open(struct device *dev);
 static int el2_close(struct device *dev);
@@ -102,14 +110,14 @@
 	if (el2_probe1(dev, netcard_portlist[i]) == 0)
 	    return 0;
     }
-#if ! defined(no_probe_nonshared_memory) && ! defined (HAVE_DEVLIST)
+#if defined(CONFIG_EL2_PIO) && ! defined (HAVE_DEVLIST)
     return el2_pio_probe(dev);
 #else
     return ENODEV;
 #endif
 }
 
-#ifndef HAVE_DEVLIST
+#if defined(CONFIG_EL2_PIO) && ! defined (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
@@ -172,6 +180,13 @@
 	return ENODEV;
     }
 
+#ifndef CONFIG_EL2_PIO
+    if ((membase_reg & 0xf0) == 0) {
+	printk("3c503 in PIO mode ignored - rejumper for shared memory.\n");
+	return ENODEV;
+    }
+#endif
+
     request_region(ioaddr, EL2_IO_EXTENT,"3c503");
 
     if (dev == NULL)
@@ -206,14 +221,18 @@
     ei_status.interface_num = dev->mem_end & 0xf;
 #endif
 
+#ifdef CONFIG_EL2_PIO
     if ((membase_reg & 0xf0) == 0) {
 	dev->mem_start = 0;
     } else {
+#else
+    {
+#endif
 	dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
 	    ((membase_reg & 0xA0) ? 0x4000 : 0);
 
 #define EL2_MEMSIZE (EL2SM_STOP_PG - EL2SM_START_PG)*256
-#ifdef EL2MEMTEST
+#ifdef CONFIG_EL2_MEMTEST
 	/* This has never found an error, but someone might care. */
 	{			/* Check the card's memory. */
 	    int *mem_base = (int *)dev->mem_start;
@@ -224,14 +243,16 @@
 		if (mem_base[0] != 0xba5eba5e
 		    || mem_base[i] != memtest_value) {
 		    printk(" memory failure or memory address conflict.\n");
+#ifdef CONFIG_EL2_PIO
 		    dev->mem_start = 0;
+#endif
 		    break;
 		}
 		memtest_value += 0x55555555;
 		mem_base[i] = 0;
 	    }
 	}
-#endif  /* EL2MEMTEST */
+#endif  /* EL2_MEMTEST */
 	/* Divide the on-board memory into a single maximum-sized transmit
 	   (double-sized for ping-pong transmit) buffer at the base, and
 	   use the rest as a receive ring. */
@@ -262,12 +283,14 @@
     dev->open = &el2_open;
     dev->stop = &el2_close;
 
-    if (dev->mem_start)
-	printk("\n%s: %s with shared memory at %#6lx-%#6lx,\n",
-	       dev->name, ei_status.name, dev->mem_start, dev->mem_end-1);
-    else
+#ifdef CONFIG_EL2_PIO
+    if (dev->mem_start == 0)
 	printk("\n%s: %s using programmed I/O (REJUMPER for SHARED MEMORY).\n",
 	       dev->name, ei_status.name);
+    else
+#endif
+	printk("\n%s: %s with shared memory at %#6lx-%#6lx,\n",
+	       dev->name, ei_status.name, dev->mem_start, dev->mem_end-1);
 
     if (ei_debug > 1)
 	printk(version);
@@ -376,20 +399,26 @@
 el2_block_output(struct device *dev, int count,
 		 const unsigned char *buf, const start_page)
 {
-    int i;				/* Buffer index */
+#ifdef CONFIG_EL2_PIO
+    int i;			/* Buffer index */
     int boguscount = 0;		/* timeout counter */
+#endif
+    void *dest_addr;
 
     /* This should really be set with during an open(). */
     outb(EGACFR_NORM, E33G_GACFR);	/* Enable RAM and interrupts. */
 
+#ifdef CONFIG_EL2_PIO
     if (dev->mem_start) {	/* Shared memory transfer */
-	void *dest_addr = (void *)(dev->mem_start +
+#endif
+	dest_addr = (void *)(dev->mem_start +
 	    ((start_page - ei_status.tx_start_page) << 8));
 	memcpy(dest_addr, buf, count);
 	if (ei_debug > 2  &&  memcmp(dest_addr, buf, count))
 	    printk("%s: 3c503 send_packet() bad memory copy @ %#5x.\n",
 		   dev->name, (int) dest_addr);
 	return;
+#ifdef CONFIG_EL2_PIO
     }
     /* No shared memory, put the packet out the slow way. */
     /* Set up then start the internal memory transfer to Tx Start Page */
@@ -413,18 +442,23 @@
     }
     outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
     return;
+#endif
 }
 
 /* Returns the new ring pointer. */
 static int
 el2_block_input(struct device *dev, int count, char *buf, int ring_offset)
 {
+#ifdef CONFIG_EL2_PIO
     int boguscount = 0;
-    int end_of_ring = dev->rmem_end;
     unsigned int i;
+#endif
+    int end_of_ring = dev->rmem_end;
 
     /* Maybe enable shared memory just be to be safe... nahh.*/
+#ifdef CONFIG_EL2_PIO
     if (dev->mem_start) {	/* Use the shared memory. */
+#endif
 	ring_offset -= (EL2SM_START_PG<<8);
 	if (dev->mem_start + ring_offset + count > end_of_ring) {
 	    /* We must wrap the input move. */
@@ -436,6 +470,7 @@
 	}
 	memcpy(buf, (char *)dev->mem_start + ring_offset, count);
 	return ring_offset + count;
+#ifdef CONFIG_EL2_PIO
     }
     /* No shared memory, use programmed I/O. */
     outb(ring_offset & 0xff, E33G_DMAAL);
@@ -458,6 +493,7 @@
     }
     outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
     return 0;
+#endif
 }
 
 /*

home help back first fref pref prev next nref lref last post