NE2000 PCI clone autodetect code for 2.0.29 !!!

Bas Mevissen (sgm@stack.nl)
Fri, 14 Feb 1997 13:54:38 +0100 (MET)


Hello all,

As you have read, I use a RealTek PCI NE2000 clone.
Now there is proper detection & initialisation code in the development
kernel, but I would like to use the stable releases for the next few months.

That's because my WDC 1.6Gb IDE disk (1 1/2 years old) crashed and now I
only have Linux to do my homework on :-)) (So my Linux system must work OK)

Therefore I put the new code in the 2.0.29 source tree. And voil\'a, it
worked like hell (Thank you Paul Gortmaker).

Enough talked about it, here is the patch.

--- drivers/net/ne.c.orig Mon Oct 7 19:27:46 1996
+++ drivers/net/ne.c Thu Feb 13 13:08:01 1997
@@ -24,6 +24,10 @@
Paul Gortmaker : multiple card support for module users.
Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c
Paul Gortmaker : Allow users with bad cards to avoid full probe.
+ Paul Gortmaker : PCI probe changes, more PCI cards supported.
+
+ ne2k driver from Linux kernel 2.1.xx ported to Linux 2.0.xx
+ by Bas Mevissen <sgm@stack.nl>, Februari 1997

*/

@@ -61,11 +65,22 @@
/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
/* #define PACKETBUF_MEMSIZE 0x40 */

-/* ---- No user-serviceable parts below ---- */
-
-/* A zero-terminated list of I/O addresses to be probed. */
+/* A zero-terminated list of I/O addresses to be probed at boot. */
+#ifndef MODULE
static unsigned int netcard_portlist[] =
{ 0x300, 0x280, 0x320, 0x340, 0x360, 0};
+#endif
+
+#ifdef CONFIG_PCI
+/* Ack! People are making PCI ne2000 clones! Oh the horror, the horror... */
+static struct { unsigned short vendor, dev_id;}
+pci_clone_list[] = {
+ {PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029},
+ {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940},
+ {PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000},
+ {0,}
+};
+#endif

#ifdef SUPPORT_NE_BAD_CLONES
/* A list of bad clones that we none-the-less recognize. */
@@ -80,10 +95,14 @@
{"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}}, /* Outlaw 4-Dimension cards. */
{"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
{"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
+ {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
+ {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
{0,}
};
#endif

+/* ---- No user-serviceable parts below ---- */
+
#define NE_BASE (dev->base_addr)
#define NE_CMD 0x00
#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
@@ -100,6 +119,9 @@

int ne_probe(struct device *dev);
static int ne_probe1(struct device *dev, int ioaddr);
+#ifdef CONFIG_PCI
+static int ne_probe_pci(struct device *dev);
+#endif

static int ne_open(struct device *dev);
static int ne_close(struct device *dev);
@@ -139,13 +161,15 @@
{"ne", ne_probe1, NE_IO_EXTENT, netcard_portlist};
#else

-/* Note that this probe only picks up one card at a time, even for multiple
- PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI ne2k card.
- This keeps things consistent regardless of the bus type of the card. */
+/*
+ * Note that at boot, this probe only picks up one card at a time, even for
+ * multiple PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI
+ * ne2k card. This keeps things consistent regardless of the bus type of
+ * the card.
+ */

int ne_probe(struct device *dev)
{
- int i;
int base_addr = dev ? dev->base_addr : 0;

/* First check any supplied i/o locations. User knows best. <cough> */
@@ -154,53 +178,70 @@
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;

+#ifdef CONFIG_PCI
/* Then look for any installed PCI clones */
-#if defined(CONFIG_PCI)
- if (pcibios_present()) {
- int pci_index;
- for (pci_index = 0; pci_index < 8; pci_index++) {
- unsigned char pci_bus, pci_device_fn;
- unsigned int pci_ioaddr;
-
- /* Currently only Realtek are making PCI ne2k clones. */
- if (pcibios_find_device (PCI_VENDOR_ID_REALTEK,
- PCI_DEVICE_ID_REALTEK_8029, pci_index,
- &pci_bus, &pci_device_fn) != 0)
- break; /* OK, now try to probe for std. ISA card */
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- /* Strip the I/O address out of the returned value */
- pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
- /* Avoid already found cards from previous ne_probe() calls */
- if (check_region(pci_ioaddr, NE_IO_EXTENT))
- continue;
- printk("ne.c: PCI BIOS reports ne2000 clone at i/o %#x, irq %d.\n",
- pci_ioaddr, pci_irq_line);
- if (ne_probe1(dev, pci_ioaddr) != 0) { /* Shouldn't happen. */
- printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr);
- break; /* Hrmm, try to probe for ISA card... */
- }
- pci_irq_line = 0;
- return 0;
- }
- }
-#endif /* defined(CONFIG_PCI) */
+ if (pcibios_present() && (ne_probe_pci(dev) == 0))
+ return 0;
+#endif

+#ifndef MODULE
/* Last resort. The semi-risky ISA auto-probe. */
- for (i = 0; netcard_portlist[i]; i++) {
- int ioaddr = netcard_portlist[i];
+ for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
+ int ioaddr = netcard_portlist[base_addr];
if (check_region(ioaddr, NE_IO_EXTENT))
continue;
if (ne_probe1(dev, ioaddr) == 0)
return 0;
}
+#endif

return ENODEV;
}
#endif

+#ifdef CONFIG_PCI
+static int ne_probe_pci(struct device *dev)
+{
+ int i;
+
+ for (i = 0; pci_clone_list[i].vendor != 0; i++) {
+ unsigned char pci_bus, pci_device_fn;
+ unsigned int pci_ioaddr;
+ int pci_index;
+
+ for (pci_index = 0; pci_index < 8; pci_index++) {
+ if (pcibios_find_device (pci_clone_list[i].vendor,
+ pci_clone_list[i].dev_id, pci_index,
+ &pci_bus, &pci_device_fn) != 0)
+ break; /* No more of these type of cards */
+ pcibios_read_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ /* Strip the I/O address out of the returned value */
+ pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+ /* Avoid already found cards from previous calls */
+ if (check_region(pci_ioaddr, NE_IO_EXTENT))
+ continue;
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, &pci_irq_line);
+ break; /* Beauty -- got a valid card. */
+ }
+ if (pci_irq_line == 0) continue; /* Try next PCI ID */
+ printk("ne.c: PCI BIOS reports %s %s at i/o %#x, irq %d.\n",
+ pci_strvendor(pci_clone_list[i].vendor),
+ pci_strdev(pci_clone_list[i].vendor, pci_clone_list[i].dev_id),
+ pci_ioaddr, pci_irq_line);
+ if (ne_probe1(dev, pci_ioaddr) != 0) { /* Shouldn't happen. */
+ printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr);
+ pci_irq_line = 0;
+ return -ENXIO;
+ }
+ pci_irq_line = 0;
+ return 0;
+ }
+ return -ENODEV;
+}
+#endif /* CONFIG_PCI */
+
static int ne_probe1(struct device *dev, int ioaddr)
{
int i;
@@ -243,7 +284,7 @@
/* A user with a poor card that fails to ack the reset, or that
does not have a valid 0x57,0x57 signature can still use this
without having to recompile. Specifying an i/o address along
- with an otherwise unused dev->mem_end value of "0xBAD" will
+ with an otherwise unused dev->mem_end value of "0xBAD" will
cause the driver to skip these parts of the probe. */

bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
@@ -301,15 +342,15 @@

/* At this point, wordlength *only* tells us if the SA_prom is doubled
up or not because some broken PCI cards don't respect the byte-wide
- request in program_seq above, and hence don't have doubled up values.
+ request in program_seq above, and hence don't have doubled up values.
These broken cards would otherwise be detected as an ne1000. */

if (wordlength == 2)
for (i = 0; i < 16; i++)
SA_prom[i] = SA_prom[i+i];
-
- if (pci_irq_line)
- wordlength = 2; /* Catch broken cards mentioned above. */
+
+ if (pci_irq_line || ioaddr >= 0x400)
+ wordlength = 2; /* Catch broken PCI cards mentioned above. */

if (wordlength == 2) {
/* We must set the 8390 for word mode. */
@@ -359,9 +400,8 @@

}

- if (pci_irq_line) {
+ if (pci_irq_line)
dev->irq = pci_irq_line;
- }

if (dev->irq < 2) {
autoirq_setup(0);
@@ -382,7 +422,7 @@
printk(" failed to detect IRQ line.\n");
return EAGAIN;
}
-
+
/* Snarf the interrupt now. There's no point in waiting since we cannot
share and the board will usually be enabled. */
{
@@ -401,7 +441,7 @@
free_irq(dev->irq, NULL);
return -ENOMEM;
}
-
+
request_region(ioaddr, NE_IO_EXTENT, name);

for(i = 0; i < ETHER_ADDR_LEN; i++) {
@@ -694,8 +734,9 @@

static int io[MAX_NE_CARDS] = { 0, };
static int irq[MAX_NE_CARDS] = { 0, };
+static int bad[MAX_NE_CARDS] = { 0, }; /* 0xbad = bad sig or no reset ack */

-/* This is set up so that no autoprobe takes place. We can't guarantee
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
that the ne2k probe is the last 8390 based probe to take place (as it
is at boot) and so the probe will get confused by any other 8390 cards.
ISA device autoprobes on a running machine are not recommended anyway. */
@@ -709,19 +750,20 @@
struct device *dev = &dev_ne[this_dev];
dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
+ dev->mem_end = bad[this_dev];
dev->base_addr = io[this_dev];
dev->init = ne_probe;
- if (io[this_dev] == 0) {
- if (this_dev != 0) break; /* only complain once */
- printk(KERN_NOTICE "ne.c: Module autoprobing not allowed. Append \"io=0xNNN\" value(s).\n");
- return -EPERM;
- }
- if (register_netdev(dev) != 0) {
- printk(KERN_WARNING "ne.c: No NE*000 card found (i/o = 0x%x).\n", io[this_dev]);
- if (found != 0) return 0; /* Got at least one. */
- return -ENXIO;
+ if (register_netdev(dev) == 0) {
+ found++;
+ continue;
}
- found++;
+ if (found != 0) /* Got at least one. */
+ return 0;
+ if (io[this_dev] != 0)
+ printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
+ else
+ printk(KERN_NOTICE "ne.c: No PCI cards found. Use \"io=0xNNN\" value(s) for ISA cards.\n");
+ return -ENXIO;
}

return 0;
--- drivers/pci/pci.c.orig Fri Feb 7 22:29:55 1997
+++ drivers/pci/pci.c Thu Feb 13 13:09:51 1997
@@ -5,6 +5,9 @@
*
* Copyright 1993, 1994, 1995 Drew Eckhardt, Frederic Potter,
* David Mosberger-Tang
+ *
+ * Some extra IDs added for ne2k by Bas Mevissen <sgm@stack.nl>, Februari 1997
+ *
*/
#include <linux/config.h>
#include <linux/ptrace.h>
@@ -41,6 +44,12 @@
* it is sequential by both vendor and device id.
*/
struct pci_dev_info dev_info[] = {
+
+/* Grabbed from Linux-2.1.26 */
+ DEVICE( WINBOND2, WINBOND2_89C940,"NE2000-PCI"),
+ DEVICE( COMPEX, COMPEX_RL2000, "ReadyLink 2000"),
+/* Bas Mevissen <sgm@stack.nl>, Februari 1997 */
+
DEVICE( COMPAQ, COMPAQ_1280, "QVision 1280/p"),
DEVICE( COMPAQ, COMPAQ_THUNDER, "ThunderLAN"),
DEVICE( NCR, NCR_53C810, "53c810"),
--- include/linux/pci.h.orig Fri Feb 7 22:29:55 1997
+++ include/linux/pci.h Thu Feb 13 13:11:00 1997
@@ -17,6 +17,10 @@
*
* Manuals are $25 each or $50 for all three, plus $7 shipping
* within the United States, $35 abroad.
+ *
+ * Some extra DEFINEs added for ne2k
+ * by Bas Mevissen <sgm@stack.nl>, Februari 1997
+ *
*/


@@ -219,6 +223,14 @@
* Vendor and card ID's: sort these numerically according to vendor
* (and according to card ID within vendor)
*/
+
+/* Grabbed from Linux-2.1.26 */
+#define PCI_VENDOR_ID_WINBOND2 0x1050
+#define PCI_DEVICE_ID_WINBOND2_89C940 0x0940
+#define PCI_VENDOR_ID_COMPEX 0x11f6
+#define PCI_DEVICE_ID_COMPEX_RL2000 0x1401
+/* Bas Mevissen <sgm@stack.nl>, Februari 1997 */
+
#define PCI_VENDOR_ID_COMPAQ 0x0e11
#define PCI_DEVICE_ID_COMPAQ_1280 0x3033
#define PCI_DEVICE_ID_COMPAQ_THUNDER 0xf130
--- kernel/ksyms.c.orig Wed Nov 13 21:41:13 1996
+++ kernel/ksyms.c Thu Feb 13 13:05:33 1997
@@ -7,6 +7,9 @@
* - External symbol table support added (December 1994)
* - Versions on symbols added (December 1994)
* by Bjorn Ekwall <bj0rn@blox.se>
+ *
+ * - Some extra ksyms added for ne2k
+ * by Bas Mevissen <sgm@stack.nl>, Februari 1997
*/

#include <linux/module.h>
@@ -115,6 +118,11 @@
X(pcibios_write_config_byte),
X(pcibios_write_config_word),
X(pcibios_write_config_dword),
+/* Grabbed from Linux-2.1.26 */
+ /* PCI support */
+ X(pci_strdev),
+ X(pci_strvendor),
+/* Bas Mevissen <sgm@stack.nl>, Februari 1997 */
#endif

/* process memory management */

It works for me, so I hope it does for you. (In fact, I'm pretty sure it
does, otherwise I wouldn't put my name in it everywhere :-)) ).

Enjoy,

Bas.

-- 
E-mail: sgm@stack.nl, S.G.A.H.Mevissen@stud.tue.nl
PGP: Finger sgm@toad.stack.nl for PGP public key, KeyID 3B896721 
WWW: www.stack.nl/~sgm (Also PGP public key)