aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorJason Baron <jbaron@redhat.com>2013-01-22 19:11:37 -0700
committerMichael S. Tsirkin <mst@redhat.com>2013-01-30 01:31:09 +0200
commit91c3f2f00810a9ba5e4404c9611197efd8f694c8 (patch)
tree317b938e539954fda77f338ad20aeab4e3dcdaa3 /hw
parentdd23454ba2c83168b453155365671e67723b881f (diff)
ich9: add support for pci assignment
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> Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/ich9.h1
-rw-r--r--hw/lpc_ich9.c33
-rw-r--r--hw/pc_q35.c1
3 files changed, 35 insertions, 0 deletions
diff --git a/hw/ich9.h b/hw/ich9.h
index b8d8e6d3df..d4509bb606 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 16843d76bc..e25689bf87 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -158,6 +158,7 @@ static void ich9_cc_write(void *opaque, hwaddr 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);
}
@@ -286,6 +287,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] &
@@ -405,6 +432,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 d82353e84f..6f5ff8dcae 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -147,6 +147,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
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);
isa_bus = ich9_lpc->isa_bus;
/*end early*/