Fixed the PCI IRQ routing code so that it is aware of IRQ sharing.

This commit is contained in:
OBattler
2017-06-22 06:50:33 +02:00
parent 78966f4d0e
commit 62a270c79f

View File

@@ -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); uint8_t (*pci_card_read[32])(int func, int addr, void *priv);
void *pci_priv[32]; void *pci_priv[32];
static int pci_irq_routing[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_irqs[4];
static int pci_card_valid[32]; 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; static int pci_index, pci_func, pci_card, pci_bus, pci_enable, pci_key;
int pci_burst_time, pci_nonburst_time; 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); */ /* pclog("ELCR%i: WRITE %02X\n", port & 1, val); */
elcr[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) uint8_t elcr_read(uint16_t port, void *priv)
@@ -82,10 +85,17 @@ void elcr_reset(void)
pic_reset(); pic_reset();
elcr[0] = elcr[1] = 0; elcr[0] = elcr[1] = 0;
#if 0
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
{ {
pci_irq_active[i] = 0; 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); 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; 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 real_irq = irq & 7;
int irq_elcr = 0; /* int irq_elcr = 0; */
if (irq > 7) if (irq > 7)
{ {
irq_elcr = elcr[1] & (1 << real_irq); return !!(elcr[1] & (1 << real_irq));
} }
else 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); picintlevel(1 << irq);
} }
@@ -177,9 +190,10 @@ void pci_set_irq(int card, int pci_int)
if (pci_irq_routing[card]) 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_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; 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_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]); 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_card_write[c] = NULL;
pci_priv[c] = NULL; pci_priv[c] = NULL;
pci_irq_routing[c] = 0; pci_irq_routing[c] = 0;
pci_irq_active[c] = 0; /* pci_irq_active[c] = 0; */
pci_card_valid[c] = 0; pci_card_valid[c] = 0;
} }