Improved PCI IRQ steering a bit and made the PCI IDE IRQ operation correct.

This commit is contained in:
OBattler
2017-08-28 16:53:53 +02:00
parent 579f13402d
commit 68e3a3d737
3 changed files with 78 additions and 15 deletions

View File

@@ -172,16 +172,9 @@ void ide_irq_raise(IDE *ide)
if (!(ide->fdisk&2))
{
if (PCI && (ide->board < 2))
if (PCI && (ide->board < 2) && ide_bus_master_set_irq)
{
if (pci_irq_is_level(ide_irq[ide->board]))
{
picintlevel(1 << ide_irq[ide->board]);
}
else
{
picint(1 << ide_irq[ide->board]);
}
pci_ide_set_irq(ide->board, ide_irq[ide->board]);
}
else
{
@@ -211,7 +204,14 @@ void ide_irq_lower(IDE *ide)
ide_log("Lowering IRQ %i (board %i)\n", ide_irq[ide->board], ide->board);
if (PCI && (ide->board < 2) && ide_bus_master_set_irq)
{
pci_ide_clear_irq(ide->board, ide_irq[ide->board]);
}
else
{
picintc(1 << ide_irq[ide->board]);
}
ide->irqstat=0;
}
@@ -232,14 +232,28 @@ void ide_irq_update(IDE *ide)
pending &= (1 << mask);
if (ide->irqstat && !pending && !(ide->fdisk & 2))
{
if (PCI && (ide->board < 2) && ide_bus_master_set_irq)
{
pci_ide_set_irq(ide->board, ide_irq[ide->board]);
}
else
{
picint(1 << ide_irq[ide->board]);
}
}
else if (pending)
{
if (PCI && (ide->board < 2) && ide_bus_master_set_irq)
{
pci_ide_clear_irq(ide->board, ide_irq[ide->board]);
}
else
{
picintc(1 << ide_irq[ide->board]);
}
}
}
/**
* Copy a string into a buffer, padding with spaces, and placing characters as
* if they were packed into 16-bit values, stored little-endian.

View File

@@ -12,7 +12,7 @@ static int pci_irq_routing[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 uint64_t 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;
@@ -187,15 +187,46 @@ void pci_issue_irq(int irq)
}
}
void pci_ide_set_irq(int ide_board, int irq)
{
if (pci_irq_is_level(irq) && (pci_irq_hold[irq] & (1LL << (0x20LL + ide_board))))
{
/* IRQ already held, do nothing. */
return;
}
if (!pci_irq_is_level(irq) || !pci_irq_hold[irq])
{
/* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */
pci_issue_irq(irq);
}
/* If the IRQ is level-triggered, mark that this card is holding it. */
if (pci_irq_is_level(irq))
{
pci_irq_hold[irq] |= (1LL << (0x20LL + ide_board));
}
}
void pci_set_irq(int card, int pci_int)
{
int irq = ((pci_int - PCI_INTA) + (pci_irq_routing[card] - PCI_INTA)) & 3;
if (pci_irq_routing[card] && (pci_irqs[irq] != PCI_IRQ_DISABLED))
{
pci_issue_irq(pci_irqs[irq]);
if (pci_irq_is_level(pci_irqs[irq]) && (pci_irq_hold[pci_irqs[irq]] & (1 << card)))
{
/* IRQ already held, do nothing. */
return;
}
/* If the IRQ is set to edge, there is no need to hold it. */
if (!pci_irq_is_level(pci_irqs[irq]) || !pci_irq_hold[pci_irqs[irq]])
{
/* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */
pci_issue_irq(pci_irqs[irq]);
}
/* If the IRQ is level-triggered, mark that this card is holding it. */
if (pci_irq_is_level(pci_irqs[irq]))
{
pci_irq_hold[pci_irqs[irq]] |= (1 << card);
@@ -203,6 +234,22 @@ void pci_set_irq(int card, int pci_int)
}
}
void pci_ide_clear_irq(int ide_board, int irq)
{
if (pci_irq_is_level(irq))
{
pci_irq_hold[irq] &= ~(1LL << (0x20LL + ide_board));
if (!pci_irq_hold[irq])
{
picintc(1 << irq);
}
}
else
{
picintc(1 << irq);
}
}
void pci_clear_irq(int card, int pci_int)
{
int irq = ((pci_int - PCI_INTA) + (pci_irq_routing[card] - PCI_INTA)) & 3;

View File

@@ -6,7 +6,9 @@ void pci_add_specific(int card, uint8_t (*read)(int func, int addr, void *priv),
int pci_add(uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv);
void pci_set_irq_routing(int card, int irq);
void pci_set_card_routing(int card, int pci_int);
void pci_ide_set_irq(int ide_board, int irq);
void pci_set_irq(int card, int pci_int);
void pci_ide_clear_irq(int ide_board, int irq);
void pci_clear_irq(int card, int pci_int);
int pci_irq_is_level(int irq);