[1643] in linux-net channel archive
PCI support for ne2k cards available
daemon@ATHENA.MIT.EDU (Paul Gortmaker)
Thu Jan 18 22:10:40 1996
From: Paul Gortmaker <gpg109@rsphy1.anu.edu.au>
To: linux-net@vger.rutgers.edu
Date: Wed, 17 Jan 1996 16:49:50 +1100 (EST)
Cc: torvalds@cs.helsinki.fi (Linus Torvalds)
Who would have thought somebody would pattern a modern PCI card on the
venerable ne2k design? Well it has been done, and now Linux supports it.
I'd never even heard of such a card until I saw Chris' post asking for
help with a "PCI ne2000 clone". Didn't believe it at first...
Chris Ho has since tested the ne2k driver with my added PCI support, and
verified that these cards are indeed ne2k compatible (see below)
ne.c: PCI BIOS reports ne2000 clone at i/o 0xff80, irq 12.
ne.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)
NE*000 ethercard probe at 0xff80: 00 40 95 41 06 2b
eth0: NE2000 found at 0xff80, using IRQ 12.
For those that are interested, Chris (cyh4@cornell.edu) reports that
the cards have one big chip, marked RTL8029 chip and the vendor is
RPTI International. The output from /proc/pci is as follows:
Bus 0, device 12, function 0:
Ethernet controller: Realtek 8029 (rev 0).
Medium devsel. IRQ 12.
I/O at 0xff80.
I suppose the performance might be similar to that of a 3c59x card,
given that they both use a PIO based driver. (Guessing only...)
[[ Alan, another target for eth_insw_and_sum() !!! ]]
Anyway, here is the patch.
Paul.
--
Proud supporter of the
campaign to bring back: printk("lp%d on fire\n", minor);
--- /home/linux/drivers/net/ne.c Tue Nov 14 16:48:52 1995
+++ linux/drivers/net/ne.c Wed Jan 17 15:34:40 1996
@@ -22,6 +22,7 @@
sanity checks and bad clone support optional.
Paul Gortmaker : new reset code, reset card after probe at boot.
Paul Gortmaker : multiple card support for module users.
+ Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c
*/
@@ -32,10 +33,12 @@
#include <linux/module.h>
-
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -90,6 +93,9 @@
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
+/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
+static unsigned char pci_irq_line = 0;
+
int ne_probe(struct device *dev);
static int ne_probe1(struct device *dev, int ioaddr);
@@ -131,16 +137,56 @@
{"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. */
+
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> */
if (base_addr > 0x1ff) /* Check a single specified location. */
return ne_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
+ /* 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) */
+
+ /* Last resort. The semi-risky ISA auto-probe. */
for (i = 0; netcard_portlist[i]; i++) {
int ioaddr = netcard_portlist[i];
if (check_region(ioaddr, NE_IO_EXTENT))
@@ -289,6 +335,10 @@
if (dev == NULL) {
printk("ne.c: Passed a NULL device.\n");
dev = init_etherdev(0, 0);
+ }
+
+ if (pci_irq_line) {
+ dev->irq = pci_irq_line;
}
if (dev->irq < 2) {