Patchwork [v3,26/26] ich9: add support pci assignment

login
register
mail settings
Submitter Jason Baron
Date Oct. 19, 2012, 8:43 p.m.
Message ID <70586f8d67caec173fb38008c8763bc183e1e685.1350677362.git.jbaron@redhat.com>
Download mbox | patch
Permalink /patch/192804/
State New
Headers show

Comments

Jason Baron - Oct. 19, 2012, 8:43 p.m.
From: Jason Baron <jbaron@redhat.com>

Fills out support for the pci assignment API. Added:

PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin)

Add calls to pci_bus_fire_intx_routing_notifier() when routing changes
are made.

Signed-off-by: Jason Baron <jbaron@redhat.com>
---
 hw/ich9.h     |    1 +
 hw/lpc_ich9.c |   33 +++++++++++++++++++++++++++++++++
 hw/pc_q35.c   |    1 +
 3 files changed, 35 insertions(+), 0 deletions(-)

Patch

diff --git a/hw/ich9.h b/hw/ich9.h
index 9e19266..cec655a 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -18,6 +18,7 @@ 
 
 void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
+PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin);
 void ich9_lpc_pm_init(PCIDevice *pci_lpc, qemu_irq cmos_s3);
 PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus);
 i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index a47d7a9..89cbcd4 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -173,6 +173,7 @@  static void ich9_cc_write(void *opaque, target_phys_addr_t addr,
 
     ich9_cc_addr_len(&addr, &len);
     memcpy(lpc->chip_config + addr, &val, len);
+    pci_bus_fire_intx_routing_notifier(lpc->d.bus);
     ich9_cc_update(lpc);
 }
 
@@ -301,6 +302,32 @@  int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx)
     return lpc->irr[PCI_SLOT(pci_dev->devfn)][intx];
 }
 
+PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin)
+{
+    ICH9LPCState *lpc = opaque;
+    PCIINTxRoute route;
+    int pic_irq;
+    int pic_dis;
+
+    assert(0 <= pirq_pin);
+    assert(pirq_pin < ICH9_LPC_NB_PIRQS);
+
+    route.mode = PCI_INTX_ENABLED;
+    ich9_lpc_pic_irq(lpc, pirq_pin, &pic_irq, &pic_dis);
+    if (!pic_dis) {
+        if (pic_irq < ICH9_LPC_PIC_NUM_PINS) {
+            route.irq = pic_irq;
+        } else {
+            route.mode = PCI_INTX_DISABLED;
+            route.irq = -1;
+        }
+    } else {
+        route.irq = ich9_pirq_to_gsi(pirq_pin);
+    }
+
+    return route;
+}
+
 static int ich9_lpc_sci_irq(ICH9LPCState *lpc)
 {
     switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] &
@@ -420,6 +447,12 @@  static void ich9_lpc_config_write(PCIDevice *d,
     if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) {
         ich9_lpc_rcba_update(lpc, rbca_old);
     }
+    if (ranges_overlap(addr, len, ICH9_LPC_PIRQA_ROUT, 4)) {
+        pci_bus_fire_intx_routing_notifier(lpc->d.bus);
+    }
+    if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) {
+        pci_bus_fire_intx_routing_notifier(lpc->d.bus);
+    }
 }
 
 static void ich9_lpc_reset(DeviceState *qdev)
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
index bde3749..aac56de 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -112,6 +112,7 @@  static void pc_q35_init_early(qemu_irq *gsi, GSIState *gsi_state,
     ich9_lpc->ioapic = gsi_state->ioapic_irq;
     pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
                  ICH9_LPC_NB_PIRQS);
+    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
 
     gmps->ram_memory = ram_memory;
     gmps->pci_address_space = pci_address_space;