aboutsummaryrefslogtreecommitdiff
path: root/hw/pci.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-05-13 23:08:13 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-05-13 23:08:13 +0000
commit72cc6cfeef616f443761365c294a86057950f9bd (patch)
treefa1072b0bcb80c9c87b6ae7c3c7549e65281c067 /hw/pci.c
parentbc380d1719ddcd70841784b2fb0a3b3c0ba935fa (diff)
downloadqemu-72cc6cfeef616f443761365c294a86057950f9bd.zip
qemu-72cc6cfeef616f443761365c294a86057950f9bd.tar.gz
qemu-72cc6cfeef616f443761365c294a86057950f9bd.tar.bz2
handle the case where several PCI irqs share the same PIC irq
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1433 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/pci.c')
-rw-r--r--hw/pci.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/hw/pci.c b/hw/pci.c
index cb7131a..6283684 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -498,6 +498,27 @@ static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
return (irq_num + slot_addend) & 3;
}
+static inline int get_pci_irq_level(int irq_num)
+{
+ int pic_level;
+#if (PCI_IRQ_WORDS == 2)
+ pic_level = ((pci_irq_levels[irq_num][0] |
+ pci_irq_levels[irq_num][1]) != 0);
+#else
+ {
+ int i;
+ pic_level = 0;
+ for(i = 0; i < PCI_IRQ_WORDS; i++) {
+ if (pci_irq_levels[irq_num][i]) {
+ pic_level = 1;
+ break;
+ }
+ }
+ }
+#endif
+ return pic_level;
+}
+
static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level)
{
int irq_index, shift, pic_irq, pic_level;
@@ -510,26 +531,20 @@ static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level)
*p = (*p & ~(1 << shift)) | (level << shift);
/* now we change the pic irq level according to the piix irq mappings */
+ /* XXX: optimize */
pic_irq = piix3_state->dev.config[0x60 + irq_num];
if (pic_irq < 16) {
/* the pic level is the logical OR of all the PCI irqs mapped
to it */
pic_level = 0;
-#if (PCI_IRQ_WORDS == 2)
- pic_level = ((pci_irq_levels[irq_num][0] |
- pci_irq_levels[irq_num][1]) != 0);
-#else
- {
- int i;
- pic_level = 0;
- for(i = 0; i < PCI_IRQ_WORDS; i++) {
- if (pci_irq_levels[irq_num][i]) {
- pic_level = 1;
- break;
- }
- }
- }
-#endif
+ if (pic_irq == piix3_state->dev.config[0x60])
+ pic_level |= get_pci_irq_level(0);
+ if (pic_irq == piix3_state->dev.config[0x61])
+ pic_level |= get_pci_irq_level(1);
+ if (pic_irq == piix3_state->dev.config[0x62])
+ pic_level |= get_pci_irq_level(2);
+ if (pic_irq == piix3_state->dev.config[0x63])
+ pic_level |= get_pci_irq_level(3);
pic_set_irq(pic_irq, pic_level);
}
}