---
 arch/ppc/qemu/init.c    |    3 +
 arch/sparc64/openbios.c |    1 
 drivers/pci.c           |   76 ++++++++++++++++++++++++++++++++++++++++++++++--
 drivers/pci_database.h  |    2 +
 include/openbios/pci.h  |   27 ++++++++---------
 5 files changed, 93 insertions(+), 16 deletions(-)

Index: openbios-devel/arch/ppc/qemu/init.c
===================================================================
--- openbios-devel.orig/arch/ppc/qemu/init.c	2009-01-06 21:24:08.000000000 +0100
+++ openbios-devel/arch/ppc/qemu/init.c	2009-01-06 21:24:18.000000000 +0100
@@ -68,14 +68,17 @@
 	[ARCH_PREP] = { "PREP", 0x1057, 0x4801, 0x80800000, 0x800c0000,
 			0x80000000, 0x00100000, 0xf0000000, 0x10000000,
 			0x80000000, 0x00010000, 0x00000000, 0x00400000,
+			{ 9, 11, 9, 11 }
 		      },
 	[ARCH_MAC99] = { "MAC99", 0x106b, 0x001F, 0xf2800000, 0xf2c00000,
 			  0xf2000000, 0x02000000, 0x80000000, 0x10000000,
 			  0xf2000000, 0x00800000, 0x00000000, 0x01000000,
+			  { 8, 9, 10, 11 }
 		       },
 	[ARCH_HEATHROW] = { "HEATHROW", 0x1057, 0x0002, 0xfec00000, 0xfee00000,
 			    0x80000000, 0x7f000000, 0x80000000, 0x01000000,
 			    0xfe000000, 0x00800000, 0xfd000000, 0x01000000,
+			    { 21, 22, 23, 24 }
 			  },
 };
 uint32_t isa_io_base;
Index: openbios-devel/drivers/pci.c
===================================================================
--- openbios-devel.orig/drivers/pci.c	2009-01-06 21:24:08.000000000 +0100
+++ openbios-devel/drivers/pci.c	2009-01-06 21:28:29.000000000 +0100
@@ -195,6 +195,52 @@
         return 0;
 }
 
+static void pci_set_interrupt_map(const pci_config_t *config)
+{
+	phandle_t parent, dev;
+	cell props[4];
+	cell *old_props, *new_props;
+	int ncells;
+	int retlen;
+
+	if (config->irq_line != -1) {
+		dev = get_cur_dev();
+		activate_device(config->path);
+		activate_device("..");
+		parent = get_cur_dev();
+
+		ncells = 0;
+		if (get_property(parent, "interrupt-map-mask", NULL) == 0) {
+			props[ncells++] = 0xF800;
+			props[ncells++] = 0;
+			props[ncells++] = 0;
+			props[ncells++] = 0;
+			set_property(parent, "interrupt-map-mask",
+				     (char*)props, ncells * sizeof(cell));
+		}
+
+		old_props = (cell*)get_property(parent, "interrupt-map", &retlen);
+		if (old_props) {
+			new_props = malloc(retlen + 6 * 4);
+			memcpy(new_props, old_props, retlen);
+		} else {
+			retlen = 0;
+			new_props = malloc(6 * 4);
+		}
+		ncells = retlen / 4;
+		new_props[ncells++] = config->dev & 0xf800;	/* devfn */
+		new_props[ncells++] = 0;
+		new_props[ncells++] = 0;
+		new_props[ncells++] = 0;
+		new_props[ncells++] = 0;
+		new_props[ncells++] = config->irq_line;
+		set_property(parent, "interrupt-map",
+		             (char*)new_props, ncells * sizeof(cell));
+		free(new_props);
+		activate_dev(dev);
+	}
+}
+
 int macio_config_cb (const pci_config_t *config)
 {
 #ifdef CONFIG_DRIVER_MACIO
@@ -232,8 +278,8 @@
 	set_int_property(dev, "revision-id", rev);
 	set_int_property(dev, "class-code", class_code << 8);
 
-	set_int_property(dev, "interrupts",
-			pci_config_read8(addr, PCI_INTERRUPT_LINE));
+	if (config->irq_pin)
+		set_int_property(dev, "interrupts", config->irq_pin);
 
 	set_int_property(dev, "min-grant", pci_config_read8(addr, PCI_MIN_GNT));
 	set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT));
@@ -275,11 +321,24 @@
 	if (pci_dev->compat)
 		set_property(dev, "compatible",
 			     pci_dev->compat, pci_compat_len(pci_dev));
+
+	pci_set_interrupt_map(config);
+
+	if (pci_dev->acells)
+		set_int_property(dev, "#address-cells", pci_dev->acells);
+	if (pci_dev->scells)
+		set_int_property(dev, "#size-cells", pci_dev->scells);
+	if (pci_dev->icells)
+		set_int_property(dev, "#interrupt-cells", pci_dev->icells);
+
+#ifdef CONFIG_DEBUG_PCI
+	printk("\n");
+#endif
+
 	if (pci_dev->config_cb)
 		pci_dev->config_cb(config);
 }
 
-
 static void ob_pci_add_reg(pci_addr addr)
 {
 	PUSH(0);
@@ -342,6 +401,17 @@
         unsigned long base;
 	pci_addr config_addr;
 	int reg;
+	uint8_t irq_pin, irq_line;
+
+	irq_pin =  pci_config_read8(addr, PCI_INTERRUPT_PIN);
+	if (irq_pin) {
+		config->irq_pin = irq_pin;
+		irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3;
+		irq_line = arch->irqs[irq_pin];
+		pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line);
+		config->irq_line = irq_line;
+	} else
+		config->irq_line = -1;
 
 	omask = 0x00000000;
 	for (reg = 0; reg < 7; reg++) {
Index: openbios-devel/drivers/pci_database.h
===================================================================
--- openbios-devel.orig/drivers/pci_database.h	2009-01-06 21:24:08.000000000 +0100
+++ openbios-devel/drivers/pci_database.h	2009-01-06 21:24:18.000000000 +0100
@@ -5,6 +5,8 @@
 	uint32_t dev;		/* bus, dev, fn */
 	uint32_t regions[7];
 	uint32_t sizes[7];
+	int irq_pin;
+	int irq_line;
 };
 
 typedef struct pci_dev_t pci_dev_t;
Index: openbios-devel/include/openbios/pci.h
===================================================================
--- openbios-devel.orig/include/openbios/pci.h	2009-01-06 21:06:08.000000000 +0100
+++ openbios-devel/include/openbios/pci.h	2009-01-06 21:24:18.000000000 +0100
@@ -6,19 +6,20 @@
 typedef struct pci_arch_t pci_arch_t;
 
 struct pci_arch_t {
-    const char * name;
-    uint16_t vendor_id;
-    uint16_t device_id;
-    unsigned long cfg_addr;
-    unsigned long cfg_data;
-    unsigned long cfg_base;
-    unsigned long cfg_len;
-    unsigned long mem_base;
-    unsigned long mem_len;
-    unsigned long io_base;
-    unsigned long io_len;
-    unsigned long rbase;
-    unsigned long rlen;
+	const char * name;
+	uint16_t vendor_id;
+	uint16_t device_id;
+	unsigned long cfg_addr;
+	unsigned long cfg_data;
+	unsigned long cfg_base;
+	unsigned long cfg_len;
+	unsigned long mem_base;
+	unsigned long mem_len;
+	unsigned long io_base;
+	unsigned long io_len;
+	unsigned long rbase;
+	unsigned long rlen;
+	uint8_t irqs[4];
 };
 
 extern const pci_arch_t *arch;
Index: openbios-devel/arch/sparc64/openbios.c
===================================================================
--- openbios-devel.orig/arch/sparc64/openbios.c	2009-01-06 21:06:08.000000000 +0100
+++ openbios-devel/arch/sparc64/openbios.c	2009-01-06 21:24:18.000000000 +0100
@@ -68,6 +68,7 @@
             .cfg_data = 0,
             .cfg_base = 0x80000000ULL,
             .cfg_len = 0,
+            .irqs = { 1, 2, 3, 4 },
         },
         .machine_id_low = 0,
         .machine_id_high = 255,
