summaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel/pci.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
commitdcec8a13bf565e47942a1751a9cec21bec5648fe (patch)
tree548b69625b18cc2e88c3e68d0923be546c9ebb03 /arch/ppc/kernel/pci.c
parent2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff)
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash. o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'arch/ppc/kernel/pci.c')
-rw-r--r--arch/ppc/kernel/pci.c116
1 files changed, 70 insertions, 46 deletions
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 7e39487d8..186165a46 100644
--- a/arch/ppc/kernel/pci.c
+++ b/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 @@ int pcibios_present(void)
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(void
__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;
+}