diff --git a/src/pci.c b/src/pci.c index 0dc20b68f..c5e1ac33d 100644 --- a/src/pci.c +++ b/src/pci.c @@ -9,9 +9,10 @@ void (*pci_card_write[32])(int func, int addr, uint8_t val, void *priv); uint8_t (*pci_card_read[32])(int func, int addr, void *priv); void *pci_priv[32]; static int pci_irq_routing[32]; -static int pci_irq_active[32]; +/* static int pci_irq_active[32]; */ static int pci_irqs[4]; static int pci_card_valid[32]; +static int pci_irq_hold[16]; static int pci_index, pci_func, pci_card, pci_bus, pci_enable, pci_key; int pci_burst_time, pci_nonburst_time; @@ -67,6 +68,8 @@ void elcr_write(uint16_t port, uint8_t val, void *priv) { /* pclog("ELCR%i: WRITE %02X\n", port & 1, val); */ elcr[port & 1] = val; + + printf("ELCR %i: %c %c %c %c %c %c %c %c\n", port & 1, (val & 1) ? 'L' : 'E', (val & 2) ? 'L' : 'E', (val & 4) ? 'L' : 'E', (val & 8) ? 'L' : 'E', (val & 0x10) ? 'L' : 'E', (val & 0x20) ? 'L' : 'E', (val & 0x40) ? 'L' : 'E', (val & 0x80) ? 'L' : 'E'); } uint8_t elcr_read(uint16_t port, void *priv) @@ -82,10 +85,17 @@ void elcr_reset(void) pic_reset(); elcr[0] = elcr[1] = 0; +#if 0 for (i = 0; i < 32; i++) { pci_irq_active[i] = 0; } +#endif + + for (i = 0; i < 16; i++) + { + pci_irq_hold[i] = 0; + } } void pci_type2_write(uint16_t port, uint8_t val, void *priv); @@ -147,21 +157,24 @@ void pci_set_card_routing(int card, int pci_int) pci_irq_routing[card] = pci_int; } -void pci_issue_irq(int irq) +int pci_irq_is_level(int irq) { int real_irq = irq & 7; - int irq_elcr = 0; + /* int irq_elcr = 0; */ if (irq > 7) { - irq_elcr = elcr[1] & (1 << real_irq); + return !!(elcr[1] & (1 << real_irq)); } else { - irq_elcr = elcr[0] & (1 << real_irq); + return !!(elcr[0] & (1 << real_irq)); } +} - if (irq_elcr) +void pci_issue_irq(int irq) +{ + if (pci_irq_is_level(irq)) { picintlevel(1 << irq); } @@ -177,9 +190,10 @@ void pci_set_irq(int card, int pci_int) if (pci_irq_routing[card]) { - if (pci_irqs[irq] != PCI_IRQ_DISABLED && !pci_irq_active[card]) + if (pci_irqs[irq] != PCI_IRQ_DISABLED/* && !pci_irq_active[card] */) pci_issue_irq(pci_irqs[irq]); - pci_irq_active[card] = 1; + /* pci_irq_active[card] = 1; */ + pci_irq_hold[pci_irqs[irq]] |= (1 << card); } } @@ -187,11 +201,13 @@ void pci_clear_irq(int card, int pci_int) { int irq = ((pci_int - PCI_INTA) + (pci_irq_routing[card] - PCI_INTA)) & 3; + /* Do not clear the interrupt until we're the last card being serviced. */ if (pci_irq_routing[card]) { - if (pci_irqs[irq] != PCI_IRQ_DISABLED && pci_irq_active[card]) + pci_irq_hold[pci_irqs[irq]] &= ~(1 << card); + if (pci_irqs[irq] != PCI_IRQ_DISABLED/* && pci_irq_active[card]*/ && !pci_irq_hold[pci_irqs[irq]]) picintc(1 << pci_irqs[irq]); - pci_irq_active[card] = 0; + /* pci_irq_active[card] = 0; */ } } @@ -222,7 +238,7 @@ void pci_init(int type) pci_card_write[c] = NULL; pci_priv[c] = NULL; pci_irq_routing[c] = 0; - pci_irq_active[c] = 0; + /* pci_irq_active[c] = 0; */ pci_card_valid[c] = 0; }