patch-2.2.11 linux/drivers/net/ne2k-pci.c

Next file: linux/drivers/net/net_init.c
Previous file: linux/drivers/net/mace.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.10/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
@@ -24,11 +24,8 @@
 
 /* Our copyright info must remain in the binary. */
 static const char *version =
-"ne2k-pci.c:v0.99L 2/7/98 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n";
+"ne2k-pci.c:vpre-1.00e 5/27/99 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n";
 
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -44,6 +41,13 @@
 #include <linux/etherdevice.h>
 #include "8390.h"
 
+#if defined(__powerpc__)
+#define inl_le(addr)  le32_to_cpu(inl(addr))
+#define inw_le(addr)  le16_to_cpu(inw(addr))
+#define insl insl_ns
+#define outsl outsl_ns
+#endif
+
 /* Set statically or when loading the driver module. */
 static int debug = 1;
 
@@ -58,19 +62,34 @@
 /* Do we have a non std. amount of memory? (in units of 256 byte pages) */
 /* #define PACKETBUF_MEMSIZE	0x40 */
 
+#define ne2k_flags reg0			/* Rename an existing field to store flags! */
+
+/* Only the low 8 bits are usable for non-init-time flags! */
+enum {
+	HOLTEK_FDX=1, 		/* Full duplex -> set 0x80 at offset 0x20. */
+	ONLY_16BIT_IO=2, ONLY_32BIT_IO=4,	/* Chip can do only 16/32-bit xfers. */
+	STOP_PG_0x60=0x100,
+};
+
+/* This will eventually be converted to the standard PCI probe table. */
+
 static struct {
 	unsigned short vendor, dev_id;
 	char *name;
+	int flags;
 }
 pci_clone_list[] __initdata = {
-	{0x10ec, 0x8029, "RealTek RTL-8029"},
-	{0x1050, 0x0940, "Winbond 89C940"},
-	{0x11f6, 0x1401, "Compex RL2000"},
-	{0x8e2e, 0x3000, "KTI ET32P2"},
-	{0x4a14, 0x5000, "NetVin NV5000SC"},
-	{0x1106, 0x0926, "Via 82C926"},
-	{0x10bd, 0x0e34, "SureCom NE34"},
-	{0x1050, 0x5a5a, "Winbond"},
+	{0x10ec, 0x8029, "RealTek RTL-8029", 0},
+	{0x1050, 0x0940, "Winbond 89C940", 0},
+	{0x11f6, 0x1401, "Compex RL2000", 0},
+	{0x8e2e, 0x3000, "KTI ET32P2", 0},
+	{0x4a14, 0x5000, "NetVin NV5000SC", 0},
+	{0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO},
+	{0x10bd, 0x0e34, "SureCom NE34", 0},
+	{0x1050, 0x5a5a, "Winbond", 0},
+	{0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
+	{0x12c3, 0x5598, "Holtek HT80229",
+	 ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
 	{0,}
 };
 
@@ -86,7 +105,8 @@
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
 int ne2k_pci_probe(struct device *dev);
-static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq);
+static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq,
+									  int chip_idx);
 
 static int ne2k_pci_open(struct device *dev);
 static int ne2k_pci_close(struct device *dev);
@@ -115,17 +135,13 @@
 int
 init_module(void)
 {
-	int retval;
-
 	/* We must emit version information. */
 	if (debug)
 		printk(KERN_INFO "%s", version);
 
-	retval = ne2k_pci_probe(0);
-
-	if (retval) {
-		printk(KERN_NOTICE "ne2k-pci.c: no (useable) cards found, driver NOT installed.\n");
-		return retval;
+	if (ne2k_pci_probe(0)) {
+		printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n");
+		return -ENODEV;
 	}
 	lock_8390_module();
 	return 0;
@@ -225,7 +241,7 @@
 
 		printk("ne2k-pci.c: PCI NE2000 clone '%s' at I/O %#x, IRQ %d.\n",
 			   pci_clone_list[i].name, pci_ioaddr, pci_irq_line);
-		dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line);
+		dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line, i);
 		if (dev == 0) {
 			/* Should not happen. */
 			printk(KERN_ERR "ne2k-pci: Probe of PCI card at %#x failed.\n",
@@ -247,11 +263,11 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq))
+__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq,
+									  int chip_idx))
 {
 	int i;
 	unsigned char SA_prom[32];
-	const char *name = NULL;
 	int start_page, stop_page;
 	int reg0 = inb(ioaddr);
 
@@ -273,6 +289,8 @@
 		}
 	}
 
+	dev = init_etherdev(dev, 0);
+
 	/* Reset card. Who knows what dain-bramaged state it was left in. */
 	{
 		unsigned long reset_start_time = jiffies;
@@ -321,59 +339,47 @@
 
 	}
 
-#ifdef notdef
-	/* Some broken PCI cards don't respect the byte-wide
-	   request in program_seq above, and hence don't have doubled up values.
-	*/
-	for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
-		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
-		SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
-		if (SA_prom[i] != SA_prom[i+1])
-			sa_prom_doubled = 0;
-	}
-
-	if (sa_prom_doubled)
-		for (i = 0; i < 16; i++)
-			SA_prom[i] = SA_prom[i+i];
-#else
-	for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
-		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+	/* Note: all PCI cards have at least 16 bit access, so we don't have
+	   to check for 8 bit cards.  Most cards permit 32 bit access. */
 
-#endif
+	if (pci_clone_list[chip_idx].flags & ONLY_32BIT_IO) {
+		for (i = 0; i < 4 ; i++)
+			((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
+	} else
+		for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
+			SA_prom[i] = inb(ioaddr + NE_DATAPORT);
 
 	/* We always set the 8390 registers for word mode. */
 	outb(0x49, ioaddr + EN0_DCFG);
 	start_page = NESM_START_PG;
-	stop_page = NESM_STOP_PG;
 
-	/* Set up the rest of the parameters. */
-	name = "PCI NE2000";
-
-	dev = init_etherdev(dev, 0);
+	stop_page =
+		pci_clone_list[chip_idx].flags&STOP_PG_0x60 ? 0x60 : NESM_STOP_PG;
 
+	/* Set up the rest of the parameters. */
 	dev->irq = irq;
 	dev->base_addr = ioaddr;
 
 	/* Allocate dev->priv and fill in 8390 specific dev fields. */
 	if (ethdev_init(dev)) {
 		printk ("%s: unable to get memory for dev->priv.\n", dev->name);
-		kfree(dev);
 		return 0;
 	}
 
 	request_region(ioaddr, NE_IO_EXTENT, dev->name);
 
 	printk("%s: %s found at %#x, IRQ %d, ",
-		   dev->name, name, ioaddr, dev->irq);
+		   dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq);
 	for(i = 0; i < 6; i++) {
 		printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
 		dev->dev_addr[i] = SA_prom[i];
 	}
 
-	ei_status.name = name;
+	ei_status.name = pci_clone_list[chip_idx].name;
 	ei_status.tx_start_page = start_page;
 	ei_status.stop_page = stop_page;
 	ei_status.word16 = 1;
+	ei_status.ne2k_flags = pci_clone_list[chip_idx].flags;
 
 	ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
@@ -447,9 +453,9 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
-			   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   dev->interrupt);
+			   (int)dev->interrupt);
 		return;
 	}
 
@@ -461,11 +467,12 @@
 	outb(ring_page, nic_base + EN0_RSARHI);
 	outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
-#if defined(USE_LONGIO)
-	*(u32*)hdr = inl(NE_BASE + NE_DATAPORT);
-#else
-	insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-#endif
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	} else {
+		*(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT));
+		le16_to_cpus(&hdr->count);
+	}
 
 	outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
 	ei_status.dmaing &= ~0x01;
@@ -485,12 +492,14 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_block_input "
-			   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   dev->interrupt);
+			   (int)dev->interrupt);
 		return;
 	}
 	ei_status.dmaing |= 0x01;
+	if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+		count = (count + 3) & 0xFFFC;
 	outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
 	outb(count & 0xff, nic_base + EN0_RCNTLO);
 	outb(count >> 8, nic_base + EN0_RCNTHI);
@@ -498,21 +507,21 @@
 	outb(ring_offset >> 8, nic_base + EN0_RSARHI);
 	outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
-#if defined(USE_LONGIO)
-	insl(NE_BASE + NE_DATAPORT, buf, count>>2);
-	if (count & 3) {
-		buf += count & ~3;
-		if (count & 2)
-			*((u16*)buf)++ = inw(NE_BASE + NE_DATAPORT);
-		if (count & 1)
-			*buf = inb(NE_BASE + NE_DATAPORT);
-	}
-#else
-	insw(NE_BASE + NE_DATAPORT,buf,count>>1);
-	if (count & 0x01) {
-		buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+		if (count & 0x01) {
+			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+		}
+	} else {
+		insl(NE_BASE + NE_DATAPORT, buf, count>>2);
+		if (count & 3) {
+			buf += count & ~3;
+			if (count & 2)
+				*((u16*)buf)++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT));
+			if (count & 1)
+				*buf = inb(NE_BASE + NE_DATAPORT);
+		}
 	}
-#endif
 
 	outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
 	ei_status.dmaing &= ~0x01;
@@ -527,15 +536,18 @@
 
 	/* On little-endian it's always safe to round the count up for
 	   word writes. */
-	if (count & 0x01)
-		count++;
+	if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+		count = (count + 3) & 0xFFFC;
+	else
+		if (count & 0x01)
+			count++;
 
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_block_output."
-			   "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   dev->interrupt);
+			   (int)dev->interrupt);
 		return;
 	}
 	ei_status.dmaing |= 0x01;
@@ -561,16 +573,16 @@
 	outb(0x00, nic_base + EN0_RSARLO);
 	outb(start_page, nic_base + EN0_RSARHI);
 	outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-#if defined(USE_LONGIO)
-	outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
-	if (count & 3) {
-		buf += count & ~3;
-		if (count & 2)
-			outw(*((u16*)buf)++, NE_BASE + NE_DATAPORT);
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+	} else {
+		outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
+		if (count & 3) {
+			buf += count & ~3;
+			if (count & 2)
+				outw(cpu_to_le16(*((u16*)buf)++), NE_BASE + NE_DATAPORT);
+		}
 	}
-#else
-	outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
-#endif
 
 	dma_start = jiffies;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)