Initialize and configure 3 PCI bridges (Intel 82801 PCI Bridge rev d9),
which have no special handling (quirks) in current Linux versions.

IO base/limit registers are initialized with zero and read-only,
indicating that the bridge does not support IO address ranges.

To avoid potentially breaking SPARC, a separate pci_set_irq function
is introduced to handle the flat IRQ space.

Signed-off-by: Marcelo Tosatti <[EMAIL PROTECTED]>

Index: kvm-userspace.pci3/qemu/hw/pci.c
===================================================================
--- kvm-userspace.pci3.orig/qemu/hw/pci.c
+++ kvm-userspace.pci3/qemu/hw/pci.c
@@ -528,6 +528,8 @@ uint32_t pci_data_read(void *opaque, uin
 /***********************************************************/
 /* generic PCI irq support */
 
+/* SPARC uses the IRQ assigned to the bridge device for its children??? */
+#ifdef TARGET_SPARC
 /* 0 <= irq_num <= 3. level must be 0 or 1 */
 static void pci_set_irq(void *opaque, int irq_num, int level)
 {
@@ -550,6 +552,33 @@ static void pci_set_irq(void *opaque, in
     bus->irq_count[irq_num] += change;
     bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
 }
+#else
+/* 0 <= irq_num <= 3. level must be 0 or 1 */
+static void pci_set_irq(void *opaque, int irq_num, int level)
+{
+    PCIDevice *pci_dev = (PCIDevice *)opaque;
+    PCIDevice *host_dev;
+    PCIBus *bus;
+    int change;
+
+    change = level - pci_dev->irq_state[irq_num];
+    if (!change)
+        return;
+
+    pci_dev->irq_state[irq_num] = level;
+    host_dev = pci_dev;
+    for (;;) {
+        bus = host_dev->bus;
+        if (bus->set_irq) {
+            irq_num = bus->map_irq(pci_dev, irq_num);
+            break;
+        }
+        host_dev = bus->parent_dev;
+    }
+    bus->irq_count[irq_num] += change;
+    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
+}
+#endif
 
 /***********************************************************/
 /* monitor info on PCI */
@@ -706,11 +735,6 @@ PCIDevice *pci_nic_init(PCIBus *bus, NIC
     return pci_dev;
 }
 
-typedef struct {
-    PCIDevice dev;
-    PCIBus *bus;
-} PCIBridge;
-
 static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
@@ -725,6 +749,13 @@ static void pci_bridge_write_config(PCID
         printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
 #endif
     }
+#ifdef TARGET_I386
+    /* on x86 the bridges do not implement I/O address ranges, I/O base/limit
+     * registers are read-only and should return 0.
+     */
+    if (address == 0x1c || address == 0x1d)
+        return;
+#endif
     pci_default_write_config(d, address, val, len);
 }
 
@@ -755,7 +786,7 @@ PCIDevice *pci_find_device(int bus_num, 
     return NULL;
 }
 
-PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
+PCIBridge *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
                         pci_map_irq_fn map_irq, const char *name)
 {
     PCIBridge *s;
@@ -778,5 +809,5 @@ PCIBus *pci_bridge_init(PCIBus *bus, int
     s->dev.config[0x1E] = 0xa0; // secondary status
 
     s->bus = pci_register_secondary_bus(&s->dev, map_irq);
-    return s->bus;
+    return s;
 }
Index: kvm-userspace.pci3/bios/rombios32.c
===================================================================
--- kvm-userspace.pci3.orig/bios/rombios32.c
+++ kvm-userspace.pci3/bios/rombios32.c
@@ -652,6 +652,30 @@ static void bios_lock_shadow_ram(void)
     pci_config_writeb(d, 0x59, v);
 }
 
+static int nr_bridges = 1;
+static int current_bridge = 0;
+
+static void pci_bios_count_p2p(PCIDevice *d)
+{
+    uint16_t vendor_id, device_id;
+
+    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
+    device_id = pci_config_readw(d, PCI_DEVICE_ID);
+    if (vendor_id == 0x8086 && device_id == 0x244e)
+        nr_bridges++;
+}
+
+int fls(int i)
+{
+    int bit;
+
+    for (bit=31; bit >= 0; bit--)
+        if (i & (1 << bit))
+            return bit+1;
+
+    return 0;
+}
+
 static void pci_bios_init_bridges(PCIDevice *d)
 {
     uint16_t vendor_id, device_id;
@@ -681,6 +705,20 @@ static void pci_bios_init_bridges(PCIDev
     } else if (vendor_id == 0x8086 && device_id == 0x1237) {
         /* i440 PCI bridge */
         bios_shadow_init(d);
+    } else if (vendor_id == 0x8086 && device_id == 0x244e) {
+        int len, base;
+
+        len = (0xfebfffff - 0xf0000000) / nr_bridges;
+        if (len & (len-1))
+            len = 1 << fls(len);
+
+         /* memory IO */
+         base = (0xf0000000+len) + (current_bridge*len);
+         base >>= 16;
+         pci_config_writew(d, 0x20, base);
+         pci_config_writew(d, 0x22, base);
+
+         current_bridge++;
     }
 }
 
@@ -775,6 +813,8 @@ static void pci_bios_init_device(PCIDevi
             pci_set_io_region_addr(d, 0, 0x80800000);
         }
         break;
+    case 0x0604:
+        break;
     default:
     default_map:
         /* default memory mappings */
@@ -859,6 +899,8 @@ void pci_bios_init(void)
     if (pci_bios_bigmem_addr < 0x90000000)
         pci_bios_bigmem_addr = 0x90000000;
 
+    pci_for_each_device(pci_bios_count_p2p);
+
     pci_for_each_device(pci_bios_init_bridges);
 
     pci_for_each_device(pci_bios_init_device);
Index: kvm-userspace.pci3/qemu/hw/piix_pci.c
===================================================================
--- kvm-userspace.pci3.orig/qemu/hw/piix_pci.c
+++ kvm-userspace.pci3/qemu/hw/piix_pci.c
@@ -172,6 +172,7 @@ static int i440fx_load(QEMUFile* f, void
 PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
 {
     PCIBus *b;
+    PCIBridge *b1, *b2, *b3;
     PCIDevice *d;
     I440FXState *s;
 
@@ -203,6 +204,15 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_
 
     d->config[0x72] = 0x02; /* SMRAM */
 
+    b1 = pci_bridge_init(s->bus, 24, 0x8086244e, pci_slot_get_pirq,
+                         "first PCI-to-PCI bridge ");
+    b2 = pci_bridge_init(s->bus, 32, 0x8086244e, pci_slot_get_pirq,
+                         "second PCI-to-PCI bridge");
+    b3 = pci_bridge_init(s->bus, 40, 0x8086244e, pci_slot_get_pirq,
+                         "third PCI-to-PCI bridge");
+    b1->dev.config[0x1c] = b2->dev.config[0x1c] = b3->dev.config[0x1c] = 0;
+    b1->dev.config[0x1d] = b2->dev.config[0x1d] = b3->dev.config[0x1d] = 0;
+
     register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d);
     *pi440fx_state = d;
     return b;
Index: kvm-userspace.pci3/qemu/hw/apb_pci.c
===================================================================
--- kvm-userspace.pci3.orig/qemu/hw/apb_pci.c
+++ kvm-userspace.pci3/qemu/hw/apb_pci.c
@@ -214,7 +214,7 @@ PCIBus *pci_apb_init(target_phys_addr_t 
     APBState *s;
     PCIDevice *d;
     int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
-    PCIBus *secondary;
+    PCIBridge *secondary;
 
     s = qemu_mallocz(sizeof(APBState));
     /* Ultrasparc PBM main bus */
@@ -254,7 +254,7 @@ PCIBus *pci_apb_init(target_phys_addr_t 
     /* APB secondary busses */
     secondary = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq, 
"Advanced PCI Bus secondary bridge 1");
     pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus 
secondary bridge 2");
-    return secondary;
+    return secondary->bus;
 }
 
 
Index: kvm-userspace.pci3/qemu/hw/pci.h
===================================================================
--- kvm-userspace.pci3.orig/qemu/hw/pci.h
+++ kvm-userspace.pci3/qemu/hw/pci.h
@@ -70,6 +70,11 @@ struct PCIDevice {
     int irq_state[4];
 };
 
+typedef struct {
+    PCIDevice dev;
+    PCIBus *bus;
+} PCIBridge;
+
 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
                                int instance_size, int devfn,
                                PCIConfigReadFunc *config_read,
@@ -102,7 +107,7 @@ PCIBus *pci_find_bus(int bus_num);
 PCIDevice *pci_find_device(int bus_num, int slot);
 
 void pci_info(void);
-PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
+PCIBridge *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
                         pci_map_irq_fn map_irq, const char *name);
 
 /* lsi53c895a.c */

-- 


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to