patch-2.3.41 linux/arch/sparc/kernel/ebus.c

Next file: linux/arch/sparc/kernel/ioport.c
Previous file: linux/arch/sparc/config.in
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.40/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.8 1999/11/27 22:40:38 zaitcev Exp $
+/* $Id: ebus.c,v 1.9 2000/01/22 07:35:25 zaitcev Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -22,14 +22,6 @@
 #include <asm/oplib.h>
 #include <asm/bpp.h>
 
-#undef PROM_DEBUG
-
-#if 0	/* separate from PROM_DEBUG for the sake of PROLL */
-#define dprintk prom_printf
-#else
-#define dprintk printk
-#endif
-
 struct linux_ebus *ebus_chain = 0;
 
 #ifdef CONFIG_SUN_OPENPROMIO
@@ -51,11 +43,62 @@
 /* We are together with pcic.c under CONFIG_PCI. */
 extern unsigned int pcic_pin_to_irq(unsigned int, char *name);
 
+/*
+ * IRQ Blacklist
+ * Here we list PROMs and systems that are known to supply crap as IRQ numbers.
+ */
+struct ebus_device_irq {
+	char *name;
+	unsigned int pin;
+};
+
+struct ebus_system_entry {
+	char *esname;
+	struct ebus_device_irq *ipt;
+};
+
+static struct ebus_device_irq je1_1[] = {
+	{ "8042",		 3 },
+	{ "SUNW,CS4231",	 0 },
+	{ "parallel",		 0 },
+	{ "se",			 2 },
+	{ 0, 0 }
+};
+
+/*
+ * Gleb's JE1 supplied reasonable pin numbers, but mine did not (OBP 2.32).
+ * Blacklist the sucker... Note that Gleb's system will work.
+ */
+static struct ebus_system_entry ebus_blacklist[] = {
+	{ "SUNW,JavaEngine1", je1_1 },
+	{ 0, 0 }
+};
+
+static struct ebus_device_irq *ebus_blackp = NULL;
+
+/*
+ */
 static inline unsigned long ebus_alloc(size_t size)
 {
 	return (unsigned long)kmalloc(size, GFP_ATOMIC);
 }
 
+/*
+ */
+int __init ebus_blacklist_irq(char *name)
+{
+	struct ebus_device_irq *dp;
+
+	if ((dp = ebus_blackp) != NULL) {
+		for (; dp->name != NULL; dp++) {
+			if (strcmp(name, dp->name) == 0) {
+				return pcic_pin_to_irq(dp->pin, name);
+			}
+		}
+	}
+	return 0;
+}
+
 void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
 				struct linux_ebus_child *dev)
 {
@@ -81,14 +124,10 @@
 		dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */
 	}
 
-	/*
-	 * Houston, we have a problem...
-	 * Sometimes PROM supplies absolutely meaningless properties.
-	 * Still, we take what it gives since we have nothing better.
-	 * Children of ebus may be wired on any input pin of PCIC.
-	 */
-	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
-	if ((len == -1) || (len == 0)) {
+	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
+		dev->num_irqs = 1;
+	} else if ((len = prom_getproperty(node, "interrupts",
+	    (char *)&irqs, sizeof(irqs)) == -1) || (len == 0)) {
 		dev->num_irqs = 0;
 		dev->irqs[0] = 0;
 		if (dev->parent->num_irqs != 0) {
@@ -177,8 +216,10 @@
 		dev->resource[i].start = baseaddr;	/* XXX Unaligned */
 	}
 
-	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
-	if ((len == -1) || (len == 0)) {
+	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
+		dev->num_irqs = 1;
+	} else if ((len = prom_getproperty(node, "interrupts",
+	    (char *)&irqs, sizeof(irqs)) == -1) || (len == 0)) {
 		dev->num_irqs = 0;
 		if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
 			 dev->num_irqs = 1;
@@ -226,6 +267,7 @@
 	struct linux_pbm_info *pbm;
 	struct linux_ebus_device *dev;
 	struct linux_ebus *ebus;
+	struct ebus_system_entry *sp;
 	struct pci_dev *pdev;
 	struct pcidev_cookie *cookie;
 	char lbuf[128];
@@ -238,11 +280,16 @@
 	if (!pci_present())
 		return;
 
+	prom_getstring(prom_root_node, "name", lbuf, sizeof(lbuf));
+	for (sp = ebus_blacklist; sp->esname != NULL; sp++) {
+		if (strcmp(lbuf, sp->esname) == 0) {
+			ebus_blackp = sp->ipt;
+			break;
+		}
+	}
+
 	pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
 	if (!pdev) {
-#ifdef PROM_DEBUG	
-		dprintk("ebus: No EBus's found.\n");
-#endif
 		return;
 	}
 	cookie = pdev->sysdata;
@@ -253,9 +300,6 @@
 	ebus->next = 0;
 
 	while (ebusnd) {
-#ifdef PROM_DEBUG	
-		dprintk("ebus%d:", num_ebus);
-#endif
 
 		prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
 		ebus->prom_node = ebusnd;
@@ -284,13 +328,7 @@
 
 			addr = regs[reg].phys_lo;
 			*base++ = addr;
-#ifdef PROM_DEBUG
-			dprintk(" %lx[%x]", addr, regs[reg].size_lo);
-#endif
 		}
-#ifdef PROM_DEBUG
-		dprintk("\n");
-#endif
 
 		nd = prom_getchild(ebusnd);
 		if (!nd)

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