Improved PCI IRQ steering a bit and made the PCI IDE IRQ operation correct.
This commit is contained in:
@@ -172,16 +172,9 @@ void ide_irq_raise(IDE *ide)
|
|||||||
|
|
||||||
if (!(ide->fdisk&2))
|
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]))
|
pci_ide_set_irq(ide->board, ide_irq[ide->board]);
|
||||||
{
|
|
||||||
picintlevel(1 << ide_irq[ide->board]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
picint(1 << ide_irq[ide->board]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
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);
|
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]);
|
picintc(1 << ide_irq[ide->board]);
|
||||||
|
}
|
||||||
ide->irqstat=0;
|
ide->irqstat=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,14 +232,28 @@ void ide_irq_update(IDE *ide)
|
|||||||
pending &= (1 << mask);
|
pending &= (1 << mask);
|
||||||
|
|
||||||
if (ide->irqstat && !pending && !(ide->fdisk & 2))
|
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]);
|
picint(1 << ide_irq[ide->board]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (pending)
|
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]);
|
picintc(1 << ide_irq[ide->board]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Copy a string into a buffer, padding with spaces, and placing characters as
|
* Copy a string into a buffer, padding with spaces, and placing characters as
|
||||||
* if they were packed into 16-bit values, stored little-endian.
|
* if they were packed into 16-bit values, stored little-endian.
|
||||||
|
|||||||
53
src/pci.c
53
src/pci.c
@@ -12,7 +12,7 @@ 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 uint64_t 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;
|
||||||
@@ -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)
|
void pci_set_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;
|
||||||
|
|
||||||
if (pci_irq_routing[card] && (pci_irqs[irq] != PCI_IRQ_DISABLED))
|
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]))
|
if (pci_irq_is_level(pci_irqs[irq]))
|
||||||
{
|
{
|
||||||
pci_irq_hold[pci_irqs[irq]] |= (1 << card);
|
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)
|
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;
|
||||||
|
|||||||
@@ -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);
|
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_irq_routing(int card, int irq);
|
||||||
void pci_set_card_routing(int card, int pci_int);
|
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_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);
|
void pci_clear_irq(int card, int pci_int);
|
||||||
int pci_irq_is_level(int irq);
|
int pci_irq_is_level(int irq);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user