i8259: Switch to per-PIC IRQ update

This converts pic_update_irq to work against a single PIC instead of the
complete cascade. Along this change, the required update after
pic_set_irq1 is now moved into that function.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
Jan Kiszka 2011-10-07 09:19:46 +02:00 committed by Blue Swirl
parent 86fbf97ceb
commit b76750c1ab
1 changed files with 20 additions and 39 deletions

View File

@ -118,39 +118,19 @@ static int pic_get_irq(PicState *s)
} }
} }
static void pic_set_irq1(PicState *s, int irq, int level); /* Update INT output. Must be called every time the output may have changed. */
static void pic_update_irq(PicState *s)
/* raise irq to CPU if necessary. must be called every time the active
irq may change */
static void pic_update_irq(PicState2 *s)
{ {
int irq2, irq; int irq;
/* first look at slave pic */ irq = pic_get_irq(s);
irq2 = pic_get_irq(&s->pics[1]);
if (irq2 >= 0) {
/* if irq request by slave pic, signal master PIC */
pic_set_irq1(&s->pics[0], 2, 1);
pic_set_irq1(&s->pics[0], 2, 0);
}
/* look at requested irq */
irq = pic_get_irq(&s->pics[0]);
if (irq >= 0) { if (irq >= 0) {
#if defined(DEBUG_PIC) DPRINTF("pic%d: imr=%x irr=%x padd=%d\n",
{ s == &s->pics_state->pics[0] ? 0 : 1, s->imr, s->irr,
int i; s->priority_add);
for(i = 0; i < 2; i++) { qemu_irq_raise(s->int_out);
printf("pic%d: imr=%x irr=%x padd=%d\n",
i, s->pics[i].imr, s->pics[i].irr,
s->pics[i].priority_add);
}
}
printf("pic: cpu_interrupt\n");
#endif
qemu_irq_raise(s->pics[0].int_out);
} else { } else {
qemu_irq_lower(s->pics[0].int_out); qemu_irq_lower(s->int_out);
} }
} }
@ -179,6 +159,7 @@ static void pic_set_irq1(PicState *s, int irq, int level)
s->last_irr &= ~mask; s->last_irr &= ~mask;
} }
} }
pic_update_irq(s);
} }
#ifdef DEBUG_IRQ_LATENCY #ifdef DEBUG_IRQ_LATENCY
@ -205,7 +186,6 @@ static void i8259_set_irq(void *opaque, int irq, int level)
} }
#endif #endif
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
pic_update_irq(s);
} }
/* acknowledge interrupt 'irq' */ /* acknowledge interrupt 'irq' */
@ -220,6 +200,7 @@ static void pic_intack(PicState *s, int irq)
/* We don't clear a level sensitive interrupt here */ /* We don't clear a level sensitive interrupt here */
if (!(s->elcr & (1 << irq))) if (!(s->elcr & (1 << irq)))
s->irr &= ~(1 << irq); s->irr &= ~(1 << irq);
pic_update_irq(s);
} }
int pic_read_irq(PicState2 *s) int pic_read_irq(PicState2 *s)
@ -246,7 +227,6 @@ int pic_read_irq(PicState2 *s)
irq = 7; irq = 7;
intno = s->pics[0].irq_base + irq; intno = s->pics[0].irq_base + irq;
} }
pic_update_irq(s);
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY) #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
if (irq == 2) { if (irq == 2) {
@ -281,7 +261,7 @@ static void pic_init_reset(PicState *s)
s->init4 = 0; s->init4 = 0;
s->single_mode = 0; s->single_mode = 0;
/* Note: ELCR is not reset */ /* Note: ELCR is not reset */
pic_update_irq(s->pics_state); pic_update_irq(s);
} }
static void pic_reset(void *opaque) static void pic_reset(void *opaque)
@ -331,23 +311,23 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
s->isr &= ~(1 << irq); s->isr &= ~(1 << irq);
if (cmd == 5) if (cmd == 5)
s->priority_add = (irq + 1) & 7; s->priority_add = (irq + 1) & 7;
pic_update_irq(s->pics_state); pic_update_irq(s);
} }
break; break;
case 3: case 3:
irq = val & 7; irq = val & 7;
s->isr &= ~(1 << irq); s->isr &= ~(1 << irq);
pic_update_irq(s->pics_state); pic_update_irq(s);
break; break;
case 6: case 6:
s->priority_add = (val + 1) & 7; s->priority_add = (val + 1) & 7;
pic_update_irq(s->pics_state); pic_update_irq(s);
break; break;
case 7: case 7:
irq = val & 7; irq = val & 7;
s->isr &= ~(1 << irq); s->isr &= ~(1 << irq);
s->priority_add = (irq + 1) & 7; s->priority_add = (irq + 1) & 7;
pic_update_irq(s->pics_state); pic_update_irq(s);
break; break;
default: default:
/* no operation */ /* no operation */
@ -359,7 +339,7 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
case 0: case 0:
/* normal mode */ /* normal mode */
s->imr = val; s->imr = val;
pic_update_irq(s->pics_state); pic_update_irq(s);
break; break;
case 1: case 1:
s->irq_base = val & 0xf8; s->irq_base = val & 0xf8;
@ -395,8 +375,9 @@ static uint32_t pic_poll_read(PicState *s)
} }
s->irr &= ~(1 << ret); s->irr &= ~(1 << ret);
s->isr &= ~(1 << ret); s->isr &= ~(1 << ret);
if (slave || ret != 2) if (slave || ret != 2) {
pic_update_irq(s->pics_state); pic_update_irq(s);
}
} else { } else {
ret = 0x07; ret = 0x07;
} }