[3682] in linux-net channel archive
new lance patch - round 2
daemon@ATHENA.MIT.EDU (Tekno Soft Snc)
Sun Jul 14 07:07:31 1996
To: linux-net@vger.rutgers.edu
Date: Sat, 13 Jul 96 13:20:38 CEST
From: Tekno Soft Snc <MC3641@mclink.it>
Hi All,
This new other lance patch divide lance.c and lance32.c, and make possible
to link in the kernel only ISA cards or only PCI/VLB cards or both.
I think that next work must be to make a library where put the same lance
and
lance32 code (am7990.c ?) as 8390.c, so we can reduce the kernel size when
both
lance drivers are used.
This is the patch:
--- cut here --- cut here --- cut here --- cut here --- cut here --- cut
here
--- linux/drivers/net/lance.c.old Fri Jul 12 19:47:06 1996
+++ linux/drivers/net/lance.c Sat Jul 13 13:05:12 1996
@@ -169,6 +169,9 @@
*
* Paul Gortmaker (gpg109@rsphy1.anu.edu.au):
* - hopefully fix above so Linux/Alpha can use ISA cards too.
+ *
+ * Roberto Fichera (MC3641@mclink.it):
+ * - removed the lance32 probing call
*/
/* Set the number of Tx and Rx buffers, using Log_2(# buffers).
@@ -261,23 +264,17 @@
{0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+,
Plug-n-Play. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
- {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974
PCnet-SCSI, PCI. */
- LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
- LANCE_HAS_MISSED_FRAME},
/* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so
just call
it the PCnet32. */
{0x2430, "PCnet32", /* 79C965
PCnet for VL bus. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
- {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II.
*/
- LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
- LANCE_HAS_MISSED_FRAME},
{0x0, "PCnet (unknown)",
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
};
-enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4,
PCNET_PCI_II=5, LANCE_UNKNOWN=6};
+enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_VLB=3,
LANCE_UNKNOWN=4};
/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
static unsigned char pci_irq_line = 0;
@@ -311,45 +308,6 @@
if (high_memory <= 16*1024*1024)
lance_need_isa_bounce_buffers = 0;
-#if defined(CONFIG_PCI)
- if (pcibios_present()) {
- int pci_index;
- printk("lance.c: PCI bios is present, checking for
devices...\n");
- for (pci_index = 0; pci_index < 8; pci_index++) {
- unsigned char pci_bus, pci_device_fn;
- unsigned int pci_ioaddr;
- unsigned short pci_command;
-
- if (pcibios_find_device (PCI_VENDOR_ID_AMD,
-
PCI_DEVICE_ID_AMD_LANCE, pci_index,
-
&pci_bus, &pci_device_fn) != 0)
- break;
- 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);
- /* Remove I/O space marker in bit 0. */
- pci_ioaddr &= ~3;
- /* PCI Spec 2.1 states that it is either the
driver or PCI card's
- * responsibility to set the PCI Master Enable Bit
if needed.
- * (From Mark Stockton
<marks@schooner.sys.hou.compaq.com>)
- */
- pcibios_read_config_word(pci_bus, pci_device_fn,
-
PCI_COMMAND, &pci_command);
- if ( ! (pci_command & PCI_COMMAND_MASTER)) {
- printk("PCI Master Bit has not been set.
Setting...\n");
- pci_command |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(pci_bus,
pci_device_fn,
-
PCI_COMMAND, pci_command);
- }
- printk("Found PCnet/PCI at %#x, irq %d.\n",
- pci_ioaddr, pci_irq_line);
- lance_probe1(pci_ioaddr);
- pci_irq_line = 0;
- }
- }
-#endif /* defined(CONFIG_PCI) */
-
for (port = lance_portlist; *port; port++) {
int ioaddr = *port;
@@ -424,6 +382,10 @@
if (chip_table[lance_version].id_number ==
chip_version)
break;
}
+
+ /* only ISA card on chip_table are probed */
+ if (lance_version == PCNET_VLB || lance_version ==
LANCE_UNKNOWN)
+ return;
}
dev = init_etherdev(0, 0);
@@ -439,15 +401,6 @@
dev->base_addr = ioaddr;
request_region(ioaddr, LANCE_TOTAL_SIZE,
chip_table[lance_version].name);
-#ifdef CONFIG_LANCE32
- /* look if it's a PCI or VLB chip */
- if (lance_version == PCNET_PCI || lance_version == PCNET_VLB ||
lance_version == PCNET_PCI_II) {
- extern void lance32_probe1 (struct device *dev, const char
*chipname, int pci_irq_line);
-
- lance32_probe1 (dev, chipname, pci_irq_line);
- return;
- }
-#endif
/* Make certain the data structures used by the LANCE are aligned
and DMAble. */
lp = (struct lance_private *) LANCE_KMALLOC(sizeof(*lp));
if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
--- linux/drivers/net/lance32.c.old Fri Jul 12 19:47:13 1996
+++ linux/drivers/net/lance32.c Sat Jul 13 13:13:35 1996
@@ -13,7 +13,7 @@
* This driver is for PCnet32 and PCnetPCI based ethercards
*/
-static const char *version = "lance32.c:v0.10 28.4.96
tsbogend@bigbug.franken.de\n";
+static const char *version = "lance32.c:v0.20 28.4.96
tsbogend@bigbug.franken.de\n";
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -33,6 +33,14 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+static unsigned int lance32_portlist[] = {0x300, 0x320, 0x340, 0x360, 0};
+void lance32_probe1(int ioaddr);
+
+#ifdef HAVE_DEVLIST
+struct netdev_entry lance32_drv =
+{"lance32", lance32_probe1, LANCE_TOTAL_SIZE, lance32_portlist};
+#endif
+
#ifdef LANCE32_DEBUG
int lance32_debug = LANCE32_DEBUG;
#else
@@ -60,6 +68,9 @@
* short period of time; now we do a reinit of the lance; the
* bug was triggered by doing ifconfig eth0 <ip> broadcast <addr>
* and hangs the machine (thanks to Klaus Liedl for debugging)
+ *
+ * v0.20: Roberto Fichera MC3641@mclink.it
+ * divided from lance.c
*/
@@ -137,7 +148,43 @@
unsigned long lock;
};
+#define LANCE_MUST_PAD 0x00000001
+#define LANCE_ENABLE_AUTOSELECT 0x00000002
+#define LANCE_MUST_REINIT_RING 0x00000004
+#define LANCE_MUST_UNRESET 0x00000008
+#define LANCE_HAS_MISSED_FRAME 0x00000010
+
+/* A mapping from the chip ID number to the part number and features.
+ These are from the datasheets -- in real life the '970 version
+ reportedly has the same ID as the '965. */
+static struct lance_chip_type {
+ int id_number;
+ const char *name;
+ int flags;
+} chip_table[] = {
+ {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974
PCnet-SCSI, PCI. */
+ LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+ LANCE_HAS_MISSED_FRAME},
+ /* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so
just call
+ it the PCnet32. */
+ {0x2430, "PCnet32", /* 79C965
PCnet for VL bus. */
+ LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+ LANCE_HAS_MISSED_FRAME},
+ {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II.
*/
+ LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+ LANCE_HAS_MISSED_FRAME},
+ {0x0, "PCnet (unknown)",
+ LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+ LANCE_HAS_MISSED_FRAME},
+};
+
+enum {PCNET_PCI=0, PCNET_VLB=1, PCNET_PCI_II=2, LANCE_UNKNOWN=3};
+
+/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
+static unsigned char pci_irq_line = 0;
+
static int lance32_open(struct device *dev);
+static int lance32_open_fail(struct device *dev);
static void lance32_init_ring(struct device *dev);
static int lance32_start_xmit(struct sk_buff *skb, struct device *dev);
static int lance32_rx(struct device *dev);
@@ -147,15 +194,118 @@
static void lance32_set_multicast_list(struct device *dev);
+int lance32_init(void)
+{
+ int *port;
+
+#if defined(CONFIG_PCI)
+ if (pcibios_present()) {
+ int pci_index;
+ printk("lance32.c: PCI bios is present, checking for
devices...\n");
+ for (pci_index = 0; pci_index < 8; pci_index++) {
+ unsigned char pci_bus, pci_device_fn;
+ unsigned int pci_ioaddr;
+ unsigned short pci_command;
+
+ if (pcibios_find_device (PCI_VENDOR_ID_AMD,
+
PCI_DEVICE_ID_AMD_LANCE, pci_index,
+
&pci_bus, &pci_device_fn) != 0)
+ break;
+ 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);
+ /* Remove I/O space marker in bit 0. */
+ pci_ioaddr &= ~3;
+ /* PCI Spec 2.1 states that it is either the
driver or PCI card's
+ * responsibility to set the PCI Master Enable Bit
if needed.
+ * (From Mark Stockton
<marks@schooner.sys.hou.compaq.com>)
+ */
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+
PCI_COMMAND, &pci_command);
+ if ( ! (pci_command & PCI_COMMAND_MASTER)) {
+ printk("PCI Master Bit has not been set.
Setting...\n");
+ pci_command |= PCI_COMMAND_MASTER;
+ pcibios_write_config_word(pci_bus,
pci_device_fn,
+
PCI_COMMAND, pci_command);
+ }
+ printk("Found PCnet/PCI at %#x, irq %d.\n",
+ pci_ioaddr, pci_irq_line);
+ lance32_probe1(pci_ioaddr);
+ pci_irq_line = 0;
+ }
+ }
+#endif /* defined(CONFIG_PCI) */
+
+ for (port = lance32_portlist; *port; port++) {
+ int ioaddr = *port;
+
+ if ( check_region(ioaddr, LANCE_TOTAL_SIZE) == 0) {
+ /* Detect "normal" 0x57 0x57 and the NI6510EB 0x52
0x44
+ signatures w/ minimal I/O reads */
+ char offset15, offset14 = inb(ioaddr + 14);
+
+ if ((offset14 == 0x52 || offset14 == 0x57) &&
+ ((offset15 = inb(ioaddr + 15)) == 0x57 ||
offset15 == 0x44))
+ lance32_probe1(ioaddr);
+ }
+ }
+ return 0;
+}
/* lance32_probe1 */
-void lance32_probe1(struct device *dev, char *chipname, int pci_irq_line)
+void lance32_probe1(int ioaddr)
{
+ struct device *dev;
struct lance32_private *lp;
- int ioaddr = dev->base_addr;
short dma_channels; /* Mark
spuriously-busy DMA channels */
- int i;
-
+ int i, reset_val, lance_version;
+ const char *chipname;
+
+ /* Reset the LANCE. */
+ reset_val = inw(ioaddr+LANCE_RESET); /* Reset the LANCE */
+ outw(reset_val, ioaddr+LANCE_RESET);
+
+ outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */
+ if (inw(ioaddr+LANCE_DATA) != 0x0004)
+ return;
+
+ /* Get the version of the chip. */
+ outw(88, ioaddr+LANCE_ADDR);
+ if (inw(ioaddr+LANCE_ADDR) != 88) {
+ return;
+ } else { /*
Good, it's a newer chip. */
+ int chip_version = inw(ioaddr+LANCE_DATA);
+ outw(89, ioaddr+LANCE_ADDR);
+ chip_version |= inw(ioaddr+LANCE_DATA) << 16;
+ if (lance32_debug > 2)
+ printk(" LANCE chip version is %#x.\n",
chip_version);
+ if ((chip_version & 0xfff) != 0x003)
+ return;
+ chip_version = (chip_version >> 12) & 0xffff;
+ for (lance_version = 0;
chip_table[lance_version].id_number; lance_version++) {
+ if (chip_table[lance_version].id_number ==
chip_version)
+ break;
+ }
+
+ /* only VLB/PCI card on chip_table are probed */
+ if (lance_version == LANCE_UNKNOWN)
+ return;
+ }
+
+ dev = init_etherdev(0, 0);
+ dev->open = lance32_open_fail;
+ chipname = chip_table[lance_version].name;
+ printk("%s: %s at %#3x,", dev->name, chipname, ioaddr);
+
+ /* There is a 16 byte station address PROM at the base address.
+ The first six bytes are the station address. */
+ for (i = 0; i < 6; i++)
+ printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
+
+ dev->base_addr = ioaddr;
+ request_region(ioaddr, LANCE_TOTAL_SIZE,
chip_table[lance_version].name);
+
/* Make certain the data structures used by the LANCE are 16byte
aligned and DMAble. */
lp = (struct lance32_private *) (((unsigned
long)kmalloc(sizeof(*lp)+15, GFP_DMA | GFP_KERNEL)+15) & ~15);
@@ -284,6 +434,12 @@
dev->set_multicast_list = &lance32_set_multicast_list;
return;
+}
+
+static int
+lance32_open_fail(struct device *dev)
+{
+ return -ENODEV;
}
--- linux/drivers/net/Config.in.old Fri Jul 12 19:55:24 1996
+++ linux/drivers/net/Config.in Fri Jul 12 19:58:21 1996
@@ -53,9 +53,7 @@
tristate '3c590 series (592/595/597) "Vortex" support' CONFIG_VORTEX
fi
bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE
- if [ "$CONFIG_LANCE" = "y" ]; then
- bool 'AMD PCInet32 (VLB and PCI) support' CONFIG_LANCE32
- fi
+ bool 'AMD LANCE PCnet/VLB and PCnet/PCI support' CONFIG_LANCE32
bool 'Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC
if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then
tristate 'WD80*3 support' CONFIG_WD80x3
--- linux/drivers/net/Makefile.old Fri Jul 12 19:59:09 1996
+++ linux/drivers/net/Makefile Fri Jul 12 19:59:27 1996
@@ -237,9 +237,10 @@
ifeq ($(CONFIG_LANCE),y)
L_OBJS += lance.o
- ifeq ($(CONFIG_LANCE32),y)
- L_OBJS += lance32.o
- endif
+endif
+
+ifeq ($(CONFIG_LANCE32),y)
+L_OBJS += lance32.o
endif
ifeq ($(CONFIG_SUNLANCE),y)
--- linux/net/core/dev.c.old Fri Jul 12 20:02:54 1996
+++ linux/net/core/dev.c Fri Jul 12 20:02:54 1996
@@ -1361,6 +1361,7 @@
*
*/
extern int lance_init(void);
+extern int lance32_init(void);
extern int ni65_init(void);
extern int pi_init(void);
extern void sdla_setup(void);
@@ -1391,6 +1392,9 @@
*/
#if defined(CONFIG_LANCE)
lance_init();
+#endif
+#if defined(CONFIG_LANCE32)
+ lance32_init();
#endif
#if defined(CONFIG_NI65)
ni65_init();
--- cut here --- cut here --- cut here --- cut here --- cut here --- cut
here
--
Roberto Fichera - email MC3641@mclink.it