aboutsummaryrefslogtreecommitdiff
path: root/hw/pci.c
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-09-24 00:16:34 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-09-24 00:16:34 +0000
commitd2b5931756fdb9f839180e33898cd1e3e4fbdc90 (patch)
treee8e31fd9d7497dce68c6be46136a8bbfc37528d3 /hw/pci.c
parente69954b9fc698996c8416a2fb26c6b50ad9f49a9 (diff)
PCI shared IRQ fix (original patch by andrzej zaborowski).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2165 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/pci.c')
-rw-r--r--hw/pci.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/hw/pci.c b/hw/pci.c
index 75bd981104..78f05cd90f 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -29,11 +29,15 @@ struct PCIBus {
int bus_num;
int devfn_min;
pci_set_irq_fn set_irq;
+ pci_map_irq_fn map_irq;
uint32_t config_reg; /* XXX: suppress */
/* low level pic */
SetIRQFunc *low_set_irq;
void *irq_opaque;
PCIDevice *devices[256];
+ /* The bus IRQ state is the logical OR of the connected devices.
+ Keep a count of the number of devices with raised IRQs. */
+ int irq_count[4];
};
static void pci_update_mappings(PCIDevice *d);
@@ -42,13 +46,16 @@ target_phys_addr_t pci_mem_base;
static int pci_irq_index;
static PCIBus *first_bus;
-PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)
+PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+ void *pic, int devfn_min)
{
PCIBus *bus;
bus = qemu_mallocz(sizeof(PCIBus));
bus->set_irq = set_irq;
+ bus->map_irq = map_irq;
bus->irq_opaque = pic;
bus->devfn_min = devfn_min;
+ memset(bus->irq_count, 0, sizeof(bus->irq_count));
first_bus = bus;
return bus;
}
@@ -100,6 +107,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
pci_dev->bus = bus;
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
+ memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
if (!config_read)
config_read = pci_default_read_config;
@@ -404,7 +412,11 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
{
PCIBus *bus = pci_dev->bus;
- bus->set_irq(pci_dev, bus->irq_opaque, irq_num, level);
+
+ irq_num = bus->map_irq(pci_dev, irq_num);
+ bus->irq_count[irq_num] += level - pci_dev->irq_state[irq_num];
+ pci_dev->irq_state[irq_num] = level;
+ bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
}
/***********************************************************/