-/*
+/*
* ARM AMBA Generic/Distributed Interrupt Controller
*
* Copyright (c) 2006 CodeSourcery.
#ifdef DEBUG_GIC
#define DPRINTF(fmt, args...) \
-do { printf("arm_gic: " fmt , (int)s->base, ##args); } while (0)
+do { printf("arm_gic: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while(0)
#endif
typedef struct gic_state
{
- arm_pic_handler handler;
uint32_t base;
- void *parent;
- int parent_irq;
+ qemu_irq parent_irq;
int enabled;
int cpu_enabled;
s->current_pending = 1023;
if (!s->enabled || !s->cpu_enabled) {
- pic_set_irq_new(s->parent, s->parent_irq, 0);
+ qemu_irq_lower(s->parent_irq);
return;
}
best_prio = 0x100;
}
}
if (best_prio > s->priority_mask) {
- pic_set_irq_new(s->parent, s->parent_irq, 0);
+ qemu_irq_lower(s->parent_irq);
} else {
s->current_pending = best_irq;
if (best_prio < s->running_priority) {
DPRINTF("Raised pending IRQ %d\n", best_irq);
- pic_set_irq_new(s->parent, s->parent_irq, 1);
+ qemu_irq_raise(s->parent_irq);
}
}
}
gic_state *s = (gic_state *)opaque;
/* The first external input line is internal interrupt 32. */
irq += 32;
- if (level == GIC_TEST_LEVEL(irq))
+ if (level == GIC_TEST_LEVEL(irq))
return;
if (level) {
static void gic_set_running_irq(gic_state *s, int irq)
{
s->running_irq = irq;
- s->running_priority = s->priority[irq];
+ if (irq == 1023)
+ s->running_priority = 0x100;
+ else
+ s->running_priority = s->priority[irq];
gic_update(s);
}
DPRINTF("ACK no pending IRQ\n");
return 1023;
}
- pic_set_irq_new(s->parent, s->parent_irq, 0);
+ qemu_irq_lower(s->parent_irq);
s->last_active[new_irq] = s->running_irq;
/* For level triggered interrupts we clear the pending bit while
the interrupt is active. */
static void gic_complete_irq(gic_state * s, int irq)
{
int update = 0;
- DPRINTF("EIO %d\n", irq);
+ DPRINTF("EOI %d\n", irq);
if (s->running_irq == 1023)
return; /* No active IRQ. */
if (irq != 1023) {
s->irq_target[irq] = value;
} else if (offset < 0xf00) {
/* Interrupt Configuration. */
- irq = (offset - 0xc00) * 2;
+ irq = (offset - 0xc00) * 4;
if (irq >= GIC_NIRQ)
goto bad_reg;
for (i = 0; i < 4; i++) {
case 0x18: /* Highest Pending Interrupt */
return s->current_pending;
default:
- cpu_abort (cpu_single_env, "gic_cpu_writeb: Bad offset %x\n", offset);
+ cpu_abort (cpu_single_env, "gic_cpu_read: Bad offset %x\n", offset);
return 0;
}
}
case 0x10: /* End Of Interrupt */
return gic_complete_irq(s, value & 0x3ff);
default:
- cpu_abort (cpu_single_env, "gic_cpu_writeb: Bad offset %x\n", offset);
+ cpu_abort (cpu_single_env, "gic_cpu_write: Bad offset %x\n", offset);
return;
}
gic_update(s);
s->cpu_enabled = 0;
}
-void *arm_gic_init(uint32_t base, void *parent, int parent_irq)
+qemu_irq *arm_gic_init(uint32_t base, qemu_irq parent_irq)
{
gic_state *s;
+ qemu_irq *qi;
int iomemtype;
s = (gic_state *)qemu_mallocz(sizeof(gic_state));
if (!s)
return NULL;
- s->handler = gic_set_irq;
- s->parent = parent;
+ qi = qemu_allocate_irqs(gic_set_irq, s, GIC_NIRQ);
s->parent_irq = parent_irq;
if (base != 0xffffffff) {
iomemtype = cpu_register_io_memory(0, gic_cpu_readfn,
gic_cpu_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+ cpu_register_physical_memory(base, 0x00001000, iomemtype);
iomemtype = cpu_register_io_memory(0, gic_dist_readfn,
gic_dist_writefn, s);
- cpu_register_physical_memory(base + 0x1000, 0x00000fff, iomemtype);
+ cpu_register_physical_memory(base + 0x1000, 0x00001000, iomemtype);
s->base = base;
} else {
s->base = 0;
}
gic_reset(s);
- return s;
+ return qi;
}