patch-2.1.97 linux/arch/ppc/kernel/pci.c

Next file: linux/arch/ppc/kernel/pmac_pci.c
Previous file: linux/arch/ppc/kernel/pci-bridge.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.96/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
@@ -1,24 +1,27 @@
 /*
- * $Id: pci.c,v 1.18 1997/10/29 03:35:07 cort Exp $
+ * $Id: pci.c,v 1.24 1998/02/19 21:29:49 cort Exp $
  * Common pmac/prep/chrp pci routines. -- Cort
  */
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/config.h>
 #include <linux/pci.h>
+#include <linux/openpic.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
+#include <asm/irq.h>
 
-#if !defined(CONFIG_MACH_SPECIFIC)
+#if !defined(CONFIG_MACH_SPECIFIC) || defined(CONFIG_PMAC)
 unsigned long isa_io_base;
+#endif /* CONFIG_MACH_SPECIFIC || CONFIG_PMAC */
+#if !defined(CONFIG_MACH_SPECIFIC)
 unsigned long isa_mem_base;
 unsigned long pci_dram_offset;
 #endif /* CONFIG_MACH_SPECIFIC */
@@ -121,49 +124,6 @@
 	return 1;
 }
 
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
-			 unsigned short index, unsigned char *bus,
-			 unsigned char *devfn)
-{
-	unsigned int curr = 0;
-	struct pci_dev *dev;
-	for (dev = pci_devices; dev; dev = dev->next) {
-		if (dev->vendor == vendor && dev->device == device_id) {
-			if (curr == index) {
-				*devfn = dev->devfn;
-				*bus = dev->bus->number;
-				return PCIBIOS_SUCCESSFUL;
-			}
-			++curr;
-		}
-	}
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-/*
- * Given the class, find the n'th instance of that device
- * in the system.
- */
-int pcibios_find_class (unsigned int class_code, unsigned short index,
-			unsigned char *bus, unsigned char *devfn)
-{
-	unsigned int curr = 0;
-	struct pci_dev *dev;
-
-	for (dev = pci_devices; dev; dev = dev->next) {
-		if (dev->class == class_code) {
-			if (curr == index) {
-				*devfn = dev->devfn;
-				*bus = dev->bus->number;
-				return PCIBIOS_SUCCESSFUL;
-			}
-			++curr;
-		}
-	}
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-
 __initfunc(unsigned long
 	   pcibios_init(unsigned long mem_start,unsigned long mem_end))
 {
@@ -203,6 +163,70 @@
 
 __initfunc(unsigned long
 	   pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
+
 {
+	extern route_pci_interrupts(void);
+	struct pci_dev *dev;
+	extern struct bridge_data **bridges;
+	extern unsigned char *Motherboard_map;
+	extern unsigned char *Motherboard_routes;
+	
+	/*
+	 * FIXME: This is broken: We should not assign IRQ's to IRQless
+	 *	  devices (look at PCI_INTERRUPT_PIN) and we also should
+	 *	  honor the existence of multi-function devices where
+	 *	  different functions have different interrupt pins. [mj]
+	 */
+	switch (_machine )
+	{
+	case _MACH_prep:
+		route_pci_interrupts();
+		for(dev=pci_devices; dev; dev=dev->next)
+		{
+			unsigned char d = PCI_SLOT(dev->devfn);
+			dev->irq = Motherboard_routes[Motherboard_map[d]];
+		}
+		break;
+	case _MACH_chrp:
+		/* PCI interrupts are controlled by the OpenPIC */
+		for(dev=pci_devices; dev; dev=dev->next)
+			if (dev->irq)
+				dev->irq = openpic_to_irq(dev->irq);
+		break;
+	case _MACH_Pmac:
+		for(dev=pci_devices; dev; dev=dev->next)
+		{
+			/*
+			 * Open Firmware often doesn't initialize the,
+			 * PCI_INTERRUPT_LINE config register properly, so we
+			 * should find the device node and se if it has an
+			 * AAPL,interrupts property.
+			 */
+			struct bridge_data *bp = bridges[dev->bus->number];
+			struct device_node *node;
+			unsigned int *reg;
+			unsigned char pin;
+			
+			if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
+			    !pin)
+				continue;	/* No interrupt generated -> no fixup */
+			for (node = bp->node->child; node != 0;
+			     node = node->sibling) {
+				reg = (unsigned int *) get_property(node, "reg", 0);
+				if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)
+					continue;
+				/* this is the node, see if it has interrupts */
+				if (node->n_intrs > 0)
+					dev->irq = node->intrs[0].line;
+				break;
+			}
+		}
+		break;
+	}
 	return mem_start;
+}
+
+__initfunc(char *pcibios_setup(char *str))
+{
+	return str;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov