Commit 72cc6cfeef616f443761365c294a86057950f9bd

Authored by bellard
1 parent bc380d17

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
Showing 1 changed file with 30 additions and 15 deletions
hw/pci.c
@@ -498,6 +498,27 @@ static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) @@ -498,6 +498,27 @@ static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
498 return (irq_num + slot_addend) & 3; 498 return (irq_num + slot_addend) & 3;
499 } 499 }
500 500
  501 +static inline int get_pci_irq_level(int irq_num)
  502 +{
  503 + int pic_level;
  504 +#if (PCI_IRQ_WORDS == 2)
  505 + pic_level = ((pci_irq_levels[irq_num][0] |
  506 + pci_irq_levels[irq_num][1]) != 0);
  507 +#else
  508 + {
  509 + int i;
  510 + pic_level = 0;
  511 + for(i = 0; i < PCI_IRQ_WORDS; i++) {
  512 + if (pci_irq_levels[irq_num][i]) {
  513 + pic_level = 1;
  514 + break;
  515 + }
  516 + }
  517 + }
  518 +#endif
  519 + return pic_level;
  520 +}
  521 +
501 static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level) 522 static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level)
502 { 523 {
503 int irq_index, shift, pic_irq, pic_level; 524 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) @@ -510,26 +531,20 @@ static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level)
510 *p = (*p & ~(1 << shift)) | (level << shift); 531 *p = (*p & ~(1 << shift)) | (level << shift);
511 532
512 /* now we change the pic irq level according to the piix irq mappings */ 533 /* now we change the pic irq level according to the piix irq mappings */
  534 + /* XXX: optimize */
513 pic_irq = piix3_state->dev.config[0x60 + irq_num]; 535 pic_irq = piix3_state->dev.config[0x60 + irq_num];
514 if (pic_irq < 16) { 536 if (pic_irq < 16) {
515 /* the pic level is the logical OR of all the PCI irqs mapped 537 /* the pic level is the logical OR of all the PCI irqs mapped
516 to it */ 538 to it */
517 pic_level = 0; 539 pic_level = 0;
518 -#if (PCI_IRQ_WORDS == 2)  
519 - pic_level = ((pci_irq_levels[irq_num][0] |  
520 - pci_irq_levels[irq_num][1]) != 0);  
521 -#else  
522 - {  
523 - int i;  
524 - pic_level = 0;  
525 - for(i = 0; i < PCI_IRQ_WORDS; i++) {  
526 - if (pci_irq_levels[irq_num][i]) {  
527 - pic_level = 1;  
528 - break;  
529 - }  
530 - }  
531 - }  
532 -#endif 540 + if (pic_irq == piix3_state->dev.config[0x60])
  541 + pic_level |= get_pci_irq_level(0);
  542 + if (pic_irq == piix3_state->dev.config[0x61])
  543 + pic_level |= get_pci_irq_level(1);
  544 + if (pic_irq == piix3_state->dev.config[0x62])
  545 + pic_level |= get_pci_irq_level(2);
  546 + if (pic_irq == piix3_state->dev.config[0x63])
  547 + pic_level |= get_pci_irq_level(3);
533 pic_set_irq(pic_irq, pic_level); 548 pic_set_irq(pic_irq, pic_level);
534 } 549 }
535 } 550 }