2011-10-11 0:33:27
qemu_irq* goldfish_interrupt_init(uint32_t base, qemu_irq parent_irq, qemu_irq parent_fiq)
{
int ret;
struct goldfish_int_state *s;
qemu_irq* qi;
s = qemu_mallocz(sizeof(*s));
qi = qemu_allocate_irqs(goldfish_int_set_irq, s, 32);
s->dev.name = "goldfish_interrupt_controller";
s->dev.id = -1;
s->dev.base = base;
s->dev.size = 0x1000;
s->parent_irq = parent_irq;
s->parent_fiq = parent_fiq;
ret = goldfish_device_add(&s->dev, goldfish_int_readfn, goldfish_int_writefn, s);
if(ret) {
qemu_free(s);
return NULL;
}
register_savevm( "goldfish_int", 0, GOLDFISH_INT_SAVE_VERSION,
goldfish_int_save, goldfish_int_load, s);
return qi;
}
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
{
qemu_irq *s;
struct IRQState *p;
int i;
s = (qemu_irq *)qemu_mallocz(sizeof(qemu_irq) * n);
p = (struct IRQState *)qemu_mallocz(sizeof(struct IRQState) * n);
for (i = 0; i < n; i++) {
p->handler = handler;
p->opaque = opaque;
p->n = i;
s[i] = p;
p++;
}
return s;
}
32個IRQState
對應的handler方法爲
static void goldfish_int_update(struct goldfish_int_state *s)
{
uint32_t flags;
flags = (s->level & s->irq_enabled);
qemu_set_irq(s->parent_irq, flags != 0);
flags = (s->level & s->fiq_enabled);
qemu_set_irq(s->parent_fiq, flags != 0);
}
static void goldfish_int_set_irq(void *opaque, int irq, int level)
{
struct goldfish_int_state *s = (struct goldfish_int_state *)opaque;
uint32_t mask = (1U << irq);
if(level) {
if(!(s->level & mask)) {
if(s->irq_enabled & mask)
s->pending_count++;
s->level |= mask;
}
}
else {
if(s->level & mask) {
if(s->irq_enabled & mask)
s->pending_count--;
s->level &= ~mask;
}
}
goldfish_int_update(s);
}
由 goldfish_int_state 進行統計
PIC