ETRAX: Simplify the interrupt controller model.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
Edgar E. Iglesias 2009-05-05 12:38:39 +02:00
parent 7a3161bafb
commit 8d13fcc01b

View File

@ -29,33 +29,33 @@
#define D(x)
#define R_RW_MASK 0
#define R_R_VECT 1
#define R_R_MASKED_VECT 2
#define R_R_NMI 3
#define R_R_GURU 4
#define R_MAX 5
struct fs_pic_state_t
{
CPUState *env;
uint32_t rw_mask;
/* Active interrupt lines. */
uint32_t r_vect;
/* Active lines, gated through the mask. */
uint32_t r_masked_vect;
uint32_t r_nmi;
uint32_t r_guru;
uint32_t regs[R_MAX];
};
static void pic_update(struct fs_pic_state_t *fs)
{
CPUState *env = fs->env;
int i;
uint32_t vector = 0;
int i;
fs->r_masked_vect = fs->r_vect & fs->rw_mask;
fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
/* The ETRAX interrupt controller signals interrupts to teh core
through an interrupt request wire and an irq vector bus. If
multiple interrupts are simultaneously active it chooses vector
0x30 and lets the sw choose the priorities. */
if (fs->r_masked_vect) {
uint32_t mv = fs->r_masked_vect;
if (fs->regs[R_R_MASKED_VECT]) {
uint32_t mv = fs->regs[R_R_MASKED_VECT];
for (i = 0; i < 31; i++) {
if (mv & 1) {
vector = 0x31 + i;
@ -83,28 +83,7 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
struct fs_pic_state_t *fs = opaque;
uint32_t rval;
switch (addr)
{
case 0x0:
rval = fs->rw_mask;
break;
case 0x4:
rval = fs->r_vect;
break;
case 0x8:
rval = fs->r_masked_vect;
break;
case 0xc:
rval = fs->r_nmi;
break;
case 0x10:
rval = fs->r_guru;
break;
default:
cpu_abort(fs->env, "invalid PIC register.\n");
break;
}
rval = fs->regs[addr >> 2];
D(printf("%s %x=%x\n", __func__, addr, rval));
return rval;
}
@ -114,15 +93,10 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
struct fs_pic_state_t *fs = opaque;
D(printf("%s addr=%x val=%x\n", __func__, addr, value));
switch (addr)
{
case 0x0:
fs->rw_mask = value;
pic_update(fs);
break;
default:
cpu_abort(fs->env, "invalid PIC register.\n");
break;
if (addr == R_RW_MASK) {
fs->regs[R_RW_MASK] = value;
pic_update(fs);
}
}
@ -147,14 +121,9 @@ void irq_info(Monitor *mon)
static void irq_handler(void *opaque, int irq, int level)
{
struct fs_pic_state_t *fs = (void *)opaque;
D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n",
__func__, irq, level,
fs->rw_mask, fs->r_vect, fs->r_masked_vect));
irq -= 1;
fs->r_vect &= ~(1 << irq);
fs->r_vect |= (!!level << irq);
fs->regs[R_R_VECT] &= ~(1 << irq);
fs->regs[R_R_VECT] |= (!!level << irq);
pic_update(fs);
}
@ -167,11 +136,11 @@ static void nmi_handler(void *opaque, int irq, int level)
mask = 1 << irq;
if (level)
fs->r_nmi |= mask;
fs->regs[R_R_NMI] |= mask;
else
fs->r_nmi &= ~mask;
fs->regs[R_R_NMI] &= ~mask;
if (fs->r_nmi)
if (fs->regs[R_R_NMI])
cpu_interrupt(env, CPU_INTERRUPT_NMI);
else
cpu_reset_interrupt(env, CPU_INTERRUPT_NMI);
@ -180,9 +149,7 @@ static void nmi_handler(void *opaque, int irq, int level)
static void guru_handler(void *opaque, int irq, int level)
{
struct fs_pic_state_t *fs = (void *)opaque;
CPUState *env = fs->env;
cpu_abort(env, "%s unsupported exception\n", __func__);
cpu_abort(fs->env, "%s unsupported exception\n", __func__);
}
struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
@ -200,7 +167,7 @@ struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
pic->guru = qemu_allocate_irqs(guru_handler, fs, 1);
intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs);
cpu_register_physical_memory(base, 0x14, intr_vect_regs);
cpu_register_physical_memory(base, R_MAX * 4, intr_vect_regs);
return pic;
}