Fixed the PCI IRQ routing code so that it is aware of IRQ sharing.
This commit is contained in:
38
src/pci.c
38
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user