UniNorth PCI bridge support
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 21 Jun 2004 16:52:24 +0000 (16:52 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 21 Jun 2004 16:52:24 +0000 (16:52 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@955 c046a42c-6fe2-441c-8c8c-71466251a162

hw/pci.c

index b05d5d9..de97cb9 100644 (file)
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -45,7 +45,7 @@ typedef struct PCIBridge {
     PCIDevice **pci_bus[256];
 } PCIBridge;
 
-static PCIBridge pci_bridge;
+static PCIBridge pci_bridge[3];
 target_phys_addr_t pci_mem_base;
 static int pci_irq_index;
 static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
@@ -56,7 +56,7 @@ PCIDevice *pci_register_device(const char *name, int instance_size,
                                PCIConfigReadFunc *config_read, 
                                PCIConfigWriteFunc *config_write)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     PCIDevice *pci_dev, **bus;
 
     if (pci_irq_index >= PCI_DEVICES_MAX)
@@ -70,6 +70,10 @@ PCIDevice *pci_register_device(const char *name, int instance_size,
     bus = s->pci_bus[bus_num];
     if (devfn < 0) {
         for(devfn = 0 ; devfn < 256; devfn += 8) {
+#ifdef TARGET_PPC
+            if ((devfn >> 3) < 11)
+                continue;
+#endif
             if (!bus[devfn])
                 goto found;
         }
@@ -425,7 +429,7 @@ static uint32_t pci_data_readl(void* opaque, uint32_t addr)
 
 void i440fx_init(void)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     PCIDevice *d;
 
     register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s);
@@ -604,7 +608,7 @@ static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
 
 void pci_prep_init(void)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     PCIDevice *d;
     int PPC_io_memory;
 
@@ -629,7 +633,9 @@ void pci_prep_init(void)
 
 /* pmac pci init */
 
-static void pci_pmac_config_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
+/* Grackle PCI host */
+static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr,
+                                       uint32_t val)
 {
     PCIBridge *s = opaque;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -638,7 +644,7 @@ static void pci_pmac_config_writel (void *opaque, target_phys_addr_t addr, uint3
     s->config_reg = val;
 }
 
-static uint32_t pci_pmac_config_readl (void *opaque, target_phys_addr_t addr)
+static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr)
 {
     PCIBridge *s = opaque;
     uint32_t val;
@@ -650,25 +656,27 @@ static uint32_t pci_pmac_config_readl (void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static CPUWriteMemoryFunc *pci_pmac_config_write[] = {
-    &pci_pmac_config_writel,
-    &pci_pmac_config_writel,
-    &pci_pmac_config_writel,
+static CPUWriteMemoryFunc *pci_grackle_config_write[] = {
+    &pci_grackle_config_writel,
+    &pci_grackle_config_writel,
+    &pci_grackle_config_writel,
 };
 
-static CPUReadMemoryFunc *pci_pmac_config_read[] = {
-    &pci_pmac_config_readl,
-    &pci_pmac_config_readl,
-    &pci_pmac_config_readl,
+static CPUReadMemoryFunc *pci_grackle_config_read[] = {
+    &pci_grackle_config_readl,
+    &pci_grackle_config_readl,
+    &pci_grackle_config_readl,
 };
 
-static void pci_pmac_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
+static void pci_grackle_writeb (void *opaque, target_phys_addr_t addr,
+                                uint32_t val)
 {
     PCIBridge *s = opaque;
     pci_data_write(s, addr, val, 1);
 }
 
-static void pci_pmac_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
+static void pci_grackle_writew (void *opaque, target_phys_addr_t addr,
+                                uint32_t val)
 {
     PCIBridge *s = opaque;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -677,7 +685,8 @@ static void pci_pmac_writew (void *opaque, target_phys_addr_t addr, uint32_t val
     pci_data_write(s, addr, val, 2);
 }
 
-static void pci_pmac_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
+static void pci_grackle_writel (void *opaque, target_phys_addr_t addr,
+                                uint32_t val)
 {
     PCIBridge *s = opaque;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -686,7 +695,7 @@ static void pci_pmac_writel (void *opaque, target_phys_addr_t addr, uint32_t val
     pci_data_write(s, addr, val, 4);
 }
 
-static uint32_t pci_pmac_readb (void *opaque, target_phys_addr_t addr)
+static uint32_t pci_grackle_readb (void *opaque, target_phys_addr_t addr)
 {
     PCIBridge *s = opaque;
     uint32_t val;
@@ -694,7 +703,7 @@ static uint32_t pci_pmac_readb (void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static uint32_t pci_pmac_readw (void *opaque, target_phys_addr_t addr)
+static uint32_t pci_grackle_readw (void *opaque, target_phys_addr_t addr)
 {
     PCIBridge *s = opaque;
     uint32_t val;
@@ -705,7 +714,131 @@ static uint32_t pci_pmac_readw (void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static uint32_t pci_pmac_readl (void *opaque, target_phys_addr_t addr)
+static uint32_t pci_grackle_readl (void *opaque, target_phys_addr_t addr)
+{
+    PCIBridge *s = opaque;
+    uint32_t val;
+
+    val = pci_data_read(s, addr, 4);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
+static CPUWriteMemoryFunc *pci_grackle_write[] = {
+    &pci_grackle_writeb,
+    &pci_grackle_writew,
+    &pci_grackle_writel,
+};
+
+static CPUReadMemoryFunc *pci_grackle_read[] = {
+    &pci_grackle_readb,
+    &pci_grackle_readw,
+    &pci_grackle_readl,
+};
+
+/* Uninorth PCI host (for all Mac99 and newer machines */
+static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr,
+                                         uint32_t val)
+{
+    PCIBridge *s = opaque;
+    int i;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+
+    for (i = 11; i < 32; i++) {
+        if ((val & (1 << i)) != 0)
+            break;
+    }
+#if 0
+    s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11);
+#else
+    s->config_reg = 0x80000000 | (0 << 16) | (val & 0x7FC) | (i << 11);
+#endif
+}
+
+static uint32_t pci_unin_main_config_readl (void *opaque,
+                                            target_phys_addr_t addr)
+{
+    PCIBridge *s = opaque;
+    uint32_t val;
+    int devfn;
+
+    devfn = (s->config_reg >> 8) & 0xFF;
+    val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+
+    return val;
+}
+
+static CPUWriteMemoryFunc *pci_unin_main_config_write[] = {
+    &pci_unin_main_config_writel,
+    &pci_unin_main_config_writel,
+    &pci_unin_main_config_writel,
+};
+
+static CPUReadMemoryFunc *pci_unin_main_config_read[] = {
+    &pci_unin_main_config_readl,
+    &pci_unin_main_config_readl,
+    &pci_unin_main_config_readl,
+};
+
+static void pci_unin_main_writeb (void *opaque, target_phys_addr_t addr,
+                                  uint32_t val)
+{
+    PCIBridge *s = opaque;
+    pci_data_write(s, addr & 7, val, 1);
+}
+
+static void pci_unin_main_writew (void *opaque, target_phys_addr_t addr,
+                                  uint32_t val)
+{
+    PCIBridge *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    pci_data_write(s, addr & 7, val, 2);
+}
+
+static void pci_unin_main_writel (void *opaque, target_phys_addr_t addr,
+                                uint32_t val)
+{
+    PCIBridge *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    pci_data_write(s, addr & 7, val, 4);
+}
+
+static uint32_t pci_unin_main_readb (void *opaque, target_phys_addr_t addr)
+{
+    PCIBridge *s = opaque;
+    uint32_t val;
+
+    val = pci_data_read(s, addr & 7, 1);
+
+    return val;
+}
+
+static uint32_t pci_unin_main_readw (void *opaque, target_phys_addr_t addr)
+{
+    PCIBridge *s = opaque;
+    uint32_t val;
+
+    val = pci_data_read(s, addr & 7, 2);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+
+    return val;
+}
+
+static uint32_t pci_unin_main_readl (void *opaque, target_phys_addr_t addr)
 {
     PCIBridge *s = opaque;
     uint32_t val;
@@ -714,37 +847,246 @@ static uint32_t pci_pmac_readl (void *opaque, target_phys_addr_t addr)
 #ifdef TARGET_WORDS_BIGENDIAN
     val = bswap32(val);
 #endif
+
+    return val;
+}
+
+static CPUWriteMemoryFunc *pci_unin_main_write[] = {
+    &pci_unin_main_writeb,
+    &pci_unin_main_writew,
+    &pci_unin_main_writel,
+};
+
+static CPUReadMemoryFunc *pci_unin_main_read[] = {
+    &pci_unin_main_readb,
+    &pci_unin_main_readw,
+    &pci_unin_main_readl,
+};
+
+static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
+                                    uint32_t val)
+{
+    PCIBridge *s = opaque;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    s->config_reg = 0x80000000 | (val & ~0x00000001);
+}
+
+static uint32_t pci_unin_config_readl (void *opaque,
+                                       target_phys_addr_t addr)
+{
+    PCIBridge *s = opaque;
+    uint32_t val;
+
+    val = (s->config_reg | 0x00000001) & ~0x80000000;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+
+    return val;
+}
+
+static CPUWriteMemoryFunc *pci_unin_config_write[] = {
+    &pci_unin_config_writel,
+    &pci_unin_config_writel,
+    &pci_unin_config_writel,
+};
+
+static CPUReadMemoryFunc *pci_unin_config_read[] = {
+    &pci_unin_config_readl,
+    &pci_unin_config_readl,
+    &pci_unin_config_readl,
+};
+
+static void pci_unin_writeb (void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    PCIBridge *s = opaque;
+    pci_data_write(s, addr & 3, val, 1);
+}
+
+static void pci_unin_writew (void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    PCIBridge *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    pci_data_write(s, addr & 3, val, 2);
+}
+
+static void pci_unin_writel (void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    PCIBridge *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    pci_data_write(s, addr & 3, val, 4);
+}
+
+static uint32_t pci_unin_readb (void *opaque, target_phys_addr_t addr)
+{
+    PCIBridge *s = opaque;
+    uint32_t val;
+
+    val = pci_data_read(s, addr & 3, 1);
+
+    return val;
+}
+
+static uint32_t pci_unin_readw (void *opaque, target_phys_addr_t addr)
+{
+    PCIBridge *s = opaque;
+    uint32_t val;
+
+    val = pci_data_read(s, addr & 3, 2);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+
+    return val;
+}
+
+static uint32_t pci_unin_readl (void *opaque, target_phys_addr_t addr)
+{
+    PCIBridge *s = opaque;
+    uint32_t val;
+
+    val = pci_data_read(s, addr & 3, 4);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+
     return val;
 }
 
-static CPUWriteMemoryFunc *pci_pmac_write[] = {
-    &pci_pmac_writeb,
-    &pci_pmac_writew,
-    &pci_pmac_writel,
+static CPUWriteMemoryFunc *pci_unin_write[] = {
+    &pci_unin_writeb,
+    &pci_unin_writew,
+    &pci_unin_writel,
 };
 
-static CPUReadMemoryFunc *pci_pmac_read[] = {
-    &pci_pmac_readb,
-    &pci_pmac_readw,
-    &pci_pmac_readl,
+static CPUReadMemoryFunc *pci_unin_read[] = {
+    &pci_unin_readb,
+    &pci_unin_readw,
+    &pci_unin_readl,
 };
 
 void pci_pmac_init(void)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s;
     PCIDevice *d;
     int pci_mem_config, pci_mem_data;
 
-    pci_mem_config = cpu_register_io_memory(0, pci_pmac_config_read, 
-                                            pci_pmac_config_write, s);
-    pci_mem_data = cpu_register_io_memory(0, pci_pmac_read, pci_pmac_write, s);
-
-    cpu_register_physical_memory(0xfec00000, 0x1000, pci_mem_config);
-    cpu_register_physical_memory(0xfee00000, 0x1000, pci_mem_data);
-
-    d = pci_register_device("MPC106", sizeof(PCIDevice), 0, 0, 
+    /* Use values found on a real PowerMac */
+    /* Uninorth main bus */
+    s = &pci_bridge[0];
+    pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read, 
+                                            pci_unin_main_config_write, s);
+    pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read,
+                                          pci_unin_main_write, s);
+    cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config);
+    cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data);
+
+    d = pci_register_device("Uni-north main", sizeof(PCIDevice), 0, 11 << 3,
                             NULL, NULL);
+    d->config[0x00] = 0x6b; // vendor_id : Apple
+    d->config[0x01] = 0x10;
+    d->config[0x02] = 0x1F; // device_id
+    d->config[0x03] = 0x00;
+    d->config[0x08] = 0x00; // revision
+    d->config[0x0A] = 0x00; // class_sub = pci host
+    d->config[0x0B] = 0x06; // class_base = PCI_bridge
+    d->config[0x0C] = 0x08; // cache_line_size
+    d->config[0x0D] = 0x10; // latency_timer
+    d->config[0x0E] = 0x00; // header_type
+    d->config[0x34] = 0x00; // capabilities_pointer
+
+#if 0 // XXX: not activated as PPC BIOS doesn't handle mutiple buses properly
+    /* pci-to-pci bridge */
+    d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
+                            NULL, NULL);
+    d->config[0x00] = 0x11; // vendor_id : TI
+    d->config[0x01] = 0x10;
+    d->config[0x02] = 0x26; // device_id
+    d->config[0x03] = 0x00;
+    d->config[0x08] = 0x05; // revision
+    d->config[0x0A] = 0x04; // class_sub = pci2pci
+    d->config[0x0B] = 0x06; // class_base = PCI_bridge
+    d->config[0x0C] = 0x08; // cache_line_size
+    d->config[0x0D] = 0x20; // latency_timer
+    d->config[0x0E] = 0x01; // header_type
+
+    d->config[0x18] = 0x01; // primary_bus
+    d->config[0x19] = 0x02; // secondary_bus
+    d->config[0x1A] = 0x02; // subordinate_bus
+    d->config[0x1B] = 0x20; // secondary_latency_timer
+    d->config[0x1C] = 0x11; // io_base
+    d->config[0x1D] = 0x01; // io_limit
+    d->config[0x20] = 0x00; // memory_base
+    d->config[0x21] = 0x80;
+    d->config[0x22] = 0x00; // memory_limit
+    d->config[0x23] = 0x80;
+    d->config[0x24] = 0x01; // prefetchable_memory_base
+    d->config[0x25] = 0x80;
+    d->config[0x26] = 0xF1; // prefectchable_memory_limit
+    d->config[0x27] = 0x7F;
+    // d->config[0x34] = 0xdc // capabilities_pointer
+#endif
+#if 0 // XXX: not needed for now
+    /* Uninorth AGP bus */
+    s = &pci_bridge[1];
+    pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read, 
+                                            pci_unin_config_write, s);
+    pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
+                                          pci_unin_write, s);
+    cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config);
+    cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);
+
+    d = pci_register_device("Uni-north AGP", sizeof(PCIDevice), 0, 11 << 3,
+                            NULL, NULL);
+    d->config[0x00] = 0x6b; // vendor_id : Apple
+    d->config[0x01] = 0x10;
+    d->config[0x02] = 0x20; // device_id
+    d->config[0x03] = 0x00;
+    d->config[0x08] = 0x00; // revision
+    d->config[0x0A] = 0x00; // class_sub = pci host
+    d->config[0x0B] = 0x06; // class_base = PCI_bridge
+    d->config[0x0C] = 0x08; // cache_line_size
+    d->config[0x0D] = 0x10; // latency_timer
+    d->config[0x0E] = 0x00; // header_type
+    //    d->config[0x34] = 0x80; // capabilities_pointer
+#endif
 
+#if 0 // XXX: not needed for now
+    /* Uninorth internal bus */
+    s = &pci_bridge[2];
+    pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read, 
+                                            pci_unin_config_write, s);
+    pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
+                                          pci_unin_write, s);
+    cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config);
+    cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data);
+
+    d = pci_register_device("Uni-north internal", sizeof(PCIDevice),
+                            3, 11 << 3, NULL, NULL);
+    d->config[0x00] = 0x6b; // vendor_id : Apple
+    d->config[0x01] = 0x10;
+    d->config[0x02] = 0x1E; // device_id
+    d->config[0x03] = 0x00;
+    d->config[0x08] = 0x00; // revision
+    d->config[0x0A] = 0x00; // class_sub = pci host
+    d->config[0x0B] = 0x06; // class_base = PCI_bridge
+    d->config[0x0C] = 0x08; // cache_line_size
+    d->config[0x0D] = 0x10; // latency_timer
+    d->config[0x0E] = 0x00; // header_type
+    d->config[0x34] = 0x00; // capabilities_pointer
+#endif
+
+#if 0 // Grackle ?
     /* same values as PearPC - check this */
     d->config[0x00] = 0x11; // vendor_id
     d->config[0x01] = 0x10;
@@ -770,6 +1112,7 @@ void pci_pmac_init(void)
     d->config[0x25] = 0x84;
     d->config[0x26] = 0x00; // prefetchable_memory_limit
     d->config[0x27] = 0x85;
+#endif
 }
 
 /***********************************************************/
@@ -878,7 +1221,7 @@ static void pci_info_device(PCIDevice *d)
 
 void pci_info(void)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     PCIDevice **bus;
     int bus_num, devfn;
     
@@ -928,7 +1271,7 @@ static void isa_outl(uint32_t val, uint32_t addr)
 
 static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     s->config_reg = 0x80000000 | (d->bus_num << 16) | 
         (d->devfn << 8) | addr;
     pci_data_write(s, 0, val, 4);
@@ -936,7 +1279,7 @@ static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
 
 static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     s->config_reg = 0x80000000 | (d->bus_num << 16) | 
         (d->devfn << 8) | (addr & ~3);
     pci_data_write(s, addr & 3, val, 2);
@@ -944,7 +1287,7 @@ static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
 
 static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     s->config_reg = 0x80000000 | (d->bus_num << 16) | 
         (d->devfn << 8) | (addr & ~3);
     pci_data_write(s, addr & 3, val, 1);
@@ -952,7 +1295,7 @@ static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
 
 static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     s->config_reg = 0x80000000 | (d->bus_num << 16) | 
         (d->devfn << 8) | addr;
     return pci_data_read(s, 0, 4);
@@ -960,7 +1303,7 @@ static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
 
 static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     s->config_reg = 0x80000000 | (d->bus_num << 16) | 
         (d->devfn << 8) | (addr & ~3);
     return pci_data_read(s, addr & 3, 2);
@@ -968,7 +1311,7 @@ static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
 
 static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     s->config_reg = 0x80000000 | (d->bus_num << 16) | 
         (d->devfn << 8) | (addr & ~3);
     return pci_data_read(s, addr & 3, 1);
@@ -1036,8 +1379,21 @@ static void pci_bios_init_device(PCIDevice *d)
         /* VGA: map frame buffer to default Bochs VBE address */
         pci_set_io_region_addr(d, 0, 0xE0000000);
         break;
+    case 0x0800:
+        /* PIC */
+        vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
+        device_id = pci_config_readw(d, PCI_DEVICE_ID);
+        if (vendor_id == 0x1014) {
+            /* IBM */
+            if (device_id == 0x0046 || device_id == 0xFFFF) {
+                /* MPIC & MPIC2 */
+                pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
+            }
+        }
+        break;
     case 0xff00:
-        if (vendor_id == 0x0106b && device_id == 0x0017) {
+        if (vendor_id == 0x0106b &&
+            (device_id == 0x0017 || device_id == 0x0022)) {
             /* macio bridge */
             pci_set_io_region_addr(d, 0, 0x80800000);
         }
@@ -1076,7 +1432,7 @@ static void pci_bios_init_device(PCIDevice *d)
  */
 void pci_bios_init(void)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     PCIDevice **bus;
     int bus_num, devfn, i, irq;
     uint8_t elcr[2];
@@ -1115,10 +1471,13 @@ void pci_bios_init(void)
  */
 void pci_ppc_bios_init(void)
 {
-    PCIBridge *s = &pci_bridge;
+    PCIBridge *s = &pci_bridge[0];
     PCIDevice **bus;
-    int bus_num, devfn, i, irq;
+    int bus_num, devfn;
+#if 0
+    int i, irq;
     uint8_t elcr[2];
+#endif
 
     pci_bios_io_addr = 0xc000;
     pci_bios_mem_addr = 0xc0000000;