mirror of https://github.com/xemu-project/xemu.git
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
This commit is contained in:
parent
bc380d1719
commit
72cc6cfeef
47
hw/pci.c
47
hw/pci.c
|
@ -498,23 +498,9 @@ static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
|
||||||
return (irq_num + slot_addend) & 3;
|
return (irq_num + slot_addend) & 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level)
|
static inline int get_pci_irq_level(int irq_num)
|
||||||
{
|
{
|
||||||
int irq_index, shift, pic_irq, pic_level;
|
int pic_level;
|
||||||
uint32_t *p;
|
|
||||||
|
|
||||||
irq_num = pci_slot_get_pirq(pci_dev, irq_num);
|
|
||||||
irq_index = pci_dev->irq_index;
|
|
||||||
p = &pci_irq_levels[irq_num][irq_index >> 5];
|
|
||||||
shift = (irq_index & 0x1f);
|
|
||||||
*p = (*p & ~(1 << shift)) | (level << shift);
|
|
||||||
|
|
||||||
/* now we change the pic irq level according to the piix irq mappings */
|
|
||||||
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)
|
#if (PCI_IRQ_WORDS == 2)
|
||||||
pic_level = ((pci_irq_levels[irq_num][0] |
|
pic_level = ((pci_irq_levels[irq_num][0] |
|
||||||
pci_irq_levels[irq_num][1]) != 0);
|
pci_irq_levels[irq_num][1]) != 0);
|
||||||
|
@ -530,6 +516,35 @@ static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
||||||
|
uint32_t *p;
|
||||||
|
|
||||||
|
irq_num = pci_slot_get_pirq(pci_dev, irq_num);
|
||||||
|
irq_index = pci_dev->irq_index;
|
||||||
|
p = &pci_irq_levels[irq_num][irq_index >> 5];
|
||||||
|
shift = (irq_index & 0x1f);
|
||||||
|
*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 (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);
|
pic_set_irq(pic_irq, pic_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue