openpic: move IACK to its own function
Besides making the code cleaner, we will need a separate way to access IACK in order to implement EPR (external proxy) interrupt delivery. Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
4417c73305
commit
a898a8fc96
95
hw/openpic.c
95
hw/openpic.c
@ -975,14 +975,64 @@ static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
|
||||
{
|
||||
IRQSource *src;
|
||||
int retval, irq;
|
||||
|
||||
DPRINTF("Lower OpenPIC INT output\n");
|
||||
qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
|
||||
|
||||
irq = IRQ_get_next(opp, &dst->raised);
|
||||
DPRINTF("IACK: irq=%d\n", irq);
|
||||
|
||||
if (irq == -1) {
|
||||
/* No more interrupt pending */
|
||||
return opp->spve;
|
||||
}
|
||||
|
||||
src = &opp->src[irq];
|
||||
if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
|
||||
!(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
|
||||
/* - Spurious level-sensitive IRQ
|
||||
* - Priorities has been changed
|
||||
* and the pending IRQ isn't allowed anymore
|
||||
*/
|
||||
src->ivpr &= ~IVPR_ACTIVITY_MASK;
|
||||
retval = opp->spve;
|
||||
} else {
|
||||
/* IRQ enter servicing state */
|
||||
IRQ_setbit(&dst->servicing, irq);
|
||||
retval = IVPR_VECTOR(opp, src->ivpr);
|
||||
}
|
||||
IRQ_resetbit(&dst->raised, irq);
|
||||
if (!src->level) {
|
||||
/* edge-sensitive IRQ */
|
||||
src->ivpr &= ~IVPR_ACTIVITY_MASK;
|
||||
src->pending = 0;
|
||||
}
|
||||
|
||||
if ((irq >= opp->irq_ipi0) && (irq < (opp->irq_ipi0 + MAX_IPI))) {
|
||||
src->idr &= ~(1 << cpu);
|
||||
if (src->idr && !src->level) {
|
||||
/* trigger on CPUs that didn't know about it yet */
|
||||
openpic_set_irq(opp, irq, 1);
|
||||
openpic_set_irq(opp, irq, 0);
|
||||
/* if all CPUs knew about it, set active bit again */
|
||||
src->ivpr |= IVPR_ACTIVITY_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
|
||||
int idx)
|
||||
{
|
||||
OpenPICState *opp = opaque;
|
||||
IRQSource *src;
|
||||
IRQDest *dst;
|
||||
uint32_t retval;
|
||||
int n_IRQ;
|
||||
|
||||
DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
|
||||
retval = 0xFFFFFFFF;
|
||||
@ -1004,46 +1054,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
|
||||
retval = idx;
|
||||
break;
|
||||
case 0xA0: /* IACK */
|
||||
DPRINTF("Lower OpenPIC INT output\n");
|
||||
qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
|
||||
n_IRQ = IRQ_get_next(opp, &dst->raised);
|
||||
DPRINTF("IACK: irq=%d\n", n_IRQ);
|
||||
if (n_IRQ == -1) {
|
||||
/* No more interrupt pending */
|
||||
retval = opp->spve;
|
||||
} else {
|
||||
src = &opp->src[n_IRQ];
|
||||
if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
|
||||
!(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
|
||||
/* - Spurious level-sensitive IRQ
|
||||
* - Priorities has been changed
|
||||
* and the pending IRQ isn't allowed anymore
|
||||
*/
|
||||
src->ivpr &= ~IVPR_ACTIVITY_MASK;
|
||||
retval = opp->spve;
|
||||
} else {
|
||||
/* IRQ enter servicing state */
|
||||
IRQ_setbit(&dst->servicing, n_IRQ);
|
||||
retval = IVPR_VECTOR(opp, src->ivpr);
|
||||
}
|
||||
IRQ_resetbit(&dst->raised, n_IRQ);
|
||||
if (!src->level) {
|
||||
/* edge-sensitive IRQ */
|
||||
src->ivpr &= ~IVPR_ACTIVITY_MASK;
|
||||
src->pending = 0;
|
||||
}
|
||||
|
||||
if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
|
||||
src->idr &= ~(1 << idx);
|
||||
if (src->idr && !src->level) {
|
||||
/* trigger on CPUs that didn't know about it yet */
|
||||
openpic_set_irq(opp, n_IRQ, 1);
|
||||
openpic_set_irq(opp, n_IRQ, 0);
|
||||
/* if all CPUs knew about it, set active bit again */
|
||||
src->ivpr |= IVPR_ACTIVITY_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
retval = openpic_iack(opp, dst, idx);
|
||||
break;
|
||||
case 0xB0: /* EOI */
|
||||
retval = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user