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:
Scott Wood 2013-01-03 13:25:39 +00:00 committed by Alexander Graf
parent 4417c73305
commit a898a8fc96

View File

@ -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;