[1241] in linux-net channel archive
3c503 driver update
daemon@ATHENA.MIT.EDU (Paul Gortmaker)
Wed Oct 25 00:21:22 1995
From: Paul Gortmaker <gpg109@rsphy1.anu.edu.au>
To: torvalds@cs.helsinki.fi (Linus Torvalds)
Date: Tue, 24 Oct 1995 20:35:31 +1000 (EST)
Cc: linux-net@vger.rutgers.edu
Hi,
This is a patch that I have been sitting on for a while. It updates the
3c503 driver to detect the 16 bit version of the card and make use of
the extra 8kB of packet space on the 16bit card. I finally got my hands
on a 3c503/16 to properly test it. (I also tested to make sure it still
works properly on the 8 bit cards as well.) It is against 1.1.35 but
3c503.[ch] is the same in 1.3.36.
[ linux-net people: I also tested the PIO portion of the driver, and
it still works, but you are still dain-bramaged if you aren't using
these cards in shared memory mode.]
Paul.
-----------------------
diff -ur /foo/linux-1335-oem/drivers/net/3c503.c linux/drivers/net/3c503.c
--- /foo/linux-1335-oem/drivers/net/3c503.c Tue Oct 10 22:03:45 1995
+++ linux/drivers/net/3c503.c Mon Oct 23 22:06:11 1995
@@ -16,10 +16,16 @@
in programmed-I/O mode.
Sources:
- EtherLink II Technical Reference Guide,
+ EtherLink II Technical Reference Manual,
+ EtherLink II/16 Technical Reference Manual Supplement,
3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
The Crynwr 3c503 packet driver.
+
+ Changelog:
+
+ Paul Gortmaker : add support for the 2nd 8kB of RAM on 16 bit cards.
+
*/
static const char *version =
@@ -148,7 +154,7 @@
int
el2_probe1(struct device *dev, int ioaddr)
{
- int i, iobase_reg, membase_reg, saved_406;
+ int i, iobase_reg, membase_reg, saved_406, wordlength;
static unsigned version_printed = 0;
unsigned long vendor_id;
@@ -180,8 +186,6 @@
return ENODEV;
}
- request_region(ioaddr, EL2_IO_EXTENT,"3c503");
-
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device));
@@ -191,7 +195,7 @@
dev->base_addr = ioaddr;
ethdev_init(dev);
- printk("%s: 3c503 at %#3x,", dev->name, ioaddr);
+ printk("%s: 3c503 at i/o base %#3x, node address", dev->name, ioaddr);
/* Retrieve and print the ethernet address. */
for (i = 0; i < 6; i++)
@@ -200,6 +204,13 @@
/* Map the 8390 back into the window. */
outb(ECNTRL_THIN, ioaddr + 0x406);
+ /* Check for EL2/16 as described in tech. man. */
+ outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
+ outb_p(0, ioaddr + EN0_DCFG);
+ outb_p(E8390_PAGE2, ioaddr + E8390_CMD);
+ wordlength = inb_p(ioaddr + EN0_DCFG) & ENDCFG_WTS;
+ outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
+
/* 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 */
@@ -216,13 +227,16 @@
if ((membase_reg & 0xf0) == 0) {
dev->mem_start = 0;
+ ei_status.name = "3c503-PIO";
} else {
dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
((membase_reg & 0xA0) ? 0x4000 : 0);
-#define EL2_MEMSIZE (EL2SM_STOP_PG - EL2SM_START_PG)*256
+#define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256
#ifdef EL2MEMTEST
- /* This has never found an error, but someone might care. */
+ /* This has never found an error, but someone might care.
+ Note that it only tests the 2nd 8kB on 16kB 3c503/16
+ cards between card addr. 0x2000 and 0x3fff. */
{ /* Check the card's memory. */
unsigned long mem_base = dev->mem_start;
unsigned int test_val = 0xbbadf00d;
@@ -233,6 +247,7 @@
|| readl(mem_base + i) != test_val) {
printk(" memory failure or memory address conflict.\n");
dev->mem_start = 0;
+ ei_status.name = "3c503-PIO";
break;
}
test_val += 0x55555555;
@@ -240,27 +255,48 @@
}
}
#endif /* EL2MEMTEST */
- /* 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. */
+
dev->mem_end = dev->rmem_end = dev->mem_start + EL2_MEMSIZE;
- dev->rmem_start = TX_PAGES*256 + dev->mem_start;
+
+ if (wordlength) { /* No Tx pages to skip over to get to Rx */
+ dev->rmem_start = dev->mem_start;
+ ei_status.name = "3c503/16";
+ } else {
+ dev->rmem_start = TX_PAGES*256 + dev->mem_start;
+ ei_status.name = "3c503";
+ }
}
+ /*
+ Divide up the memory on the card. This is the same regardless of
+ whether shared-mem or PIO is used. For 16 bit cards (16kB RAM),
+ we use the entire 8k of bank1 for an Rx ring. We only use 3k
+ of the bank0 for 2 full size Tx packet slots. For 8 bit cards,
+ (8kB RAM) we use 3kB of bank1 for two Tx slots, and the remaining
+ 5kB for an Rx ring. */
+
+ if (wordlength) {
+ ei_status.tx_start_page = EL2_MB0_START_PG;
+ ei_status.rx_start_page = EL2_MB1_START_PG;
+ } else {
+ ei_status.tx_start_page = EL2_MB1_START_PG;
+ ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
+ }
+
/* Finish setting the board's parameters. */
- ei_status.name = "3C503";
- ei_status.tx_start_page = EL2SM_START_PG;
- ei_status.rx_start_page = EL2SM_START_PG + TX_PAGES;
- ei_status.stop_page = EL2SM_STOP_PG;
+ ei_status.stop_page = EL2_MB1_STOP_PG;
+ ei_status.word16 = wordlength;
ei_status.reset_8390 = &el2_reset_8390;
ei_status.get_8390_hdr = &el2_get_8390_hdr;
ei_status.block_input = &el2_block_input;
ei_status.block_output = &el2_block_output;
+ request_region(ioaddr, EL2_IO_EXTENT, ei_status.name);
+
if (dev->irq == 2)
dev->irq = 9;
else if (dev->irq > 5 && dev->irq != 9) {
- printk("\n3c503: configured interrupt %d invalid, using autoIRQ.\n",
+ printk("\n3c503: configured interrupt %d invalid, will use autoIRQ.\n",
dev->irq);
dev->irq = 0;
}
@@ -272,14 +308,13 @@
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
- printk("\n%s: %s using programmed I/O (REJUMPER for SHARED MEMORY).\n",
- dev->name, ei_status.name);
+ printk("\n%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
+ dev->name, ei_status.name, (wordlength+1)<<3,
+ dev->mem_start, dev->mem_end-1);
- if (ei_debug > 1)
- printk(version);
+ else
+ printk("\n%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
+ dev->name, ei_status.name, (wordlength+1)<<3);
return 0;
}
@@ -300,7 +335,7 @@
outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
outb_p(0x00, E33G_IDCFR);
if (*irqp == autoirq_report(0) /* It's a good IRQ line! */
- && request_irq (dev->irq = *irqp, &ei_interrupt, 0, "3c503") == 0)
+ && request_irq (dev->irq = *irqp, &ei_interrupt, 0, ei_status.name) == 0)
break;
}
} while (*++irqp);
@@ -309,7 +344,7 @@
return -EAGAIN;
}
} else {
- if (request_irq(dev->irq, &ei_interrupt, 0, "3c503")) {
+ if (request_irq(dev->irq, &ei_interrupt, 0, ei_status.name)) {
return -EAGAIN;
}
}
@@ -388,13 +423,16 @@
int i; /* Buffer index */
int boguscount = 0; /* timeout counter */
- /* This should really be set with during an open(). */
- outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM and interrupts. */
+ if (ei_status.word16) /* Tx packets go into bank 0 on EL2/16 card */
+ outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
+ else
+ outb(EGACFR_NORM, E33G_GACFR);
if (dev->mem_start) { /* Shared memory transfer */
unsigned long dest_addr = dev->mem_start +
((start_page - ei_status.tx_start_page) << 8);
memcpy_toio(dest_addr, buf, count);
+ outb(EGACFR_NORM, E33G_GACFR); /* Back to bank1 in case on bank0 */
return;
}
/* No shared memory, put the packet out the slow way. */
@@ -413,11 +451,13 @@
if (++boguscount > (i<<3) + 32) {
printk("%s: FIFO blocked in el2_block_output (at %d of %d, bc=%d).\n",
dev->name, i, count, boguscount);
+ outb(EGACFR_NORM, E33G_GACFR); /* To MB1 for EL2/16 */
return;
}
outb(buf[i], E33G_FIFOH);
}
outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+ outb(EGACFR_NORM, E33G_GACFR); /* Back to bank1 in case on bank0 */
return;
}
@@ -426,7 +466,7 @@
el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
unsigned int i;
- unsigned long hdr_start = dev->mem_start + ((ring_page - EL2SM_START_PG)<<8);
+ unsigned long hdr_start = dev->mem_start + ((ring_page - EL2_MB1_START_PG)<<8);
if (dev->mem_start) { /* Use the shared memory. */
memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
@@ -456,7 +496,7 @@
/* Maybe enable shared memory just be to be safe... nahh.*/
if (dev->mem_start) { /* Use the shared memory. */
- ring_offset -= (EL2SM_START_PG<<8);
+ ring_offset -= (EL2_MB1_START_PG<<8);
if (dev->mem_start + ring_offset + count > end_of_ring) {
/* We must wrap the input move. */
int semi_count = end_of_ring - (dev->mem_start + ring_offset);
diff -ur /foo/linux-1335-oem/drivers/net/3c503.h linux/drivers/net/3c503.h
--- /foo/linux-1335-oem/drivers/net/3c503.h Mon Oct 2 03:18:58 1995
+++ linux/drivers/net/3c503.h Mon Oct 23 20:59:00 1995
@@ -12,11 +12,15 @@
#define OLD_3COM_ID 0x02608c
#define NEW_3COM_ID 0x0020af
-/* Shared memory management parameters */
+/* Shared memory management parameters. NB: The 8 bit cards have only
+ one bank (MB1) which serves both Tx and Rx packet space. The 16bit
+ cards have 2 banks, MB0 for Tx packets, and MB1 for Rx packets.
+ You choose which bank appears in the sh. mem window with EGACFR_MBSn */
+
+#define EL2_MB0_START_PG (0x00) /* EL2/16 Tx packets go in bank 0 */
+#define EL2_MB1_START_PG (0x20) /* First page of bank 1 */
+#define EL2_MB1_STOP_PG (0x40) /* Last page +1 of bank 1 */
-#define EL2SM_START_PG (0x20) /* First page of TX buffer */
-#define EL2SM_STOP_PG (0x40) /* Last page +1 of RX ring */
-
/* 3Com 3c503 ASIC registers */
#define E33G_STARTPG (EL2H+0) /* Start page, matching EN0_STARTPG */
#define E33G_STOPPG (EL2H+1) /* Stop page, must match EN0_STOPPG */
@@ -60,7 +64,28 @@
/* Bits in E33G_GACFR register: */
-#define EGACFR_NORM (0x49) /* Enable 8K shared mem, no DMA TC int */
-#define EGACFR_IRQOFF (0xc9) /* Above, and disable 8390 IRQ line */
+#define EGACFR_NIM (0x80) /* NIC interrupt mask */
+#define EGACFR_TCM (0x40) /* DMA term. count interrupt mask */
+#define EGACFR_RSEL (0x08) /* Map a bank of card mem into system mem */
+#define EGACFR_MBS2 (0x04) /* Memory bank select, bit 2. */
+#define EGACFR_MBS1 (0x02) /* Memory bank select, bit 1. */
+#define EGACFR_MBS0 (0x01) /* Memory bank select, bit 0. */
+
+#define EGACFR_NORM (0x49) /* TCM | RSEL | MBS0 */
+#define EGACFR_IRQOFF (0xc9) /* TCM | RSEL | MBS0 | NIM */
+
+/*
+ MBS2 MBS1 MBS0 Sh. mem windows card mem at:
+ ---- ---- ---- -----------------------------
+ 0 0 0 0x0000 -- bank 0
+ 0 0 1 0x2000 -- bank 1 (only choice for 8bit card)
+ 0 1 0 0x4000 -- bank 2, not used
+ 0 1 1 0x6000 -- bank 3, not used
+
+There was going to be a 32k card that used bank 2 and 3, but it
+never got produced.
+
+*/
+
/* End of 3C503 parameter definitions */