mirror of https://github.com/xemu-project/xemu.git
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);
|
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,
|
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
|
||||||
int idx)
|
int idx)
|
||||||
{
|
{
|
||||||
OpenPICState *opp = opaque;
|
OpenPICState *opp = opaque;
|
||||||
IRQSource *src;
|
|
||||||
IRQDest *dst;
|
IRQDest *dst;
|
||||||
uint32_t retval;
|
uint32_t retval;
|
||||||
int n_IRQ;
|
|
||||||
|
|
||||||
DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
|
DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
|
||||||
retval = 0xFFFFFFFF;
|
retval = 0xFFFFFFFF;
|
||||||
|
@ -1004,46 +1054,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
|
||||||
retval = idx;
|
retval = idx;
|
||||||
break;
|
break;
|
||||||
case 0xA0: /* IACK */
|
case 0xA0: /* IACK */
|
||||||
DPRINTF("Lower OpenPIC INT output\n");
|
retval = openpic_iack(opp, dst, idx);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0xB0: /* EOI */
|
case 0xB0: /* EOI */
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
Loading…
Reference in New Issue