summaryrefslogtreecommitdiff
path: root/hw/slavio_intctl.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-04-06 20:47:48 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-04-06 20:47:48 +0000
commit66321a11a4ef45942b3bee7377a36bb94831365a (patch)
treef038f1aef344fa93923d874d348d09542d4c5b68 /hw/slavio_intctl.c
parentc44644bb966bd0cf7e09d94b043814ea0740fe8f (diff)
downloadqemu-66321a11a4ef45942b3bee7377a36bb94831365a.tar.gz
sparc update (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1350 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/slavio_intctl.c')
-rw-r--r--hw/slavio_intctl.c60
1 files changed, 48 insertions, 12 deletions
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 352ae1f0f0..9c8ddd0d0c 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -1,7 +1,7 @@
/*
* QEMU Sparc SLAVIO interrupt controller emulation
*
- * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2003-2005 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +23,14 @@
*/
#include "vl.h"
//#define DEBUG_IRQ_COUNT
+//#define DEBUG_IRQ
+
+#ifdef DEBUG_IRQ
+#define DPRINTF(fmt, args...) \
+do { printf("IRQ: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
/*
* Registers of interrupt controller in sun4m.
@@ -49,6 +57,7 @@ typedef struct SLAVIO_INTCTLState {
#define INTCTL_MAXADDR 0xf
#define INTCTLM_MAXADDR 0xf
+static void slavio_check_interrupts(void *opaque);
// per-cpu interrupt controller
static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
@@ -82,10 +91,12 @@ static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint
val |= 80000000;
val &= 0xfffe0000;
s->intreg_pending[cpu] &= ~val;
+ DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
break;
case 2: // set softint
val &= 0xfffe0000;
s->intreg_pending[cpu] |= val;
+ DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
break;
default:
break;
@@ -135,15 +146,19 @@ static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uin
// Force clear unused bits
val &= ~0x7fb2007f;
s->intregm_disabled &= ~val;
+ DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
+ slavio_check_interrupts(s);
break;
case 3: // set (disable, clear pending)
// Force clear unused bits
val &= ~0x7fb2007f;
s->intregm_disabled |= val;
s->intregm_pending &= ~val;
+ DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
break;
case 4:
s->target_cpu = val & (MAX_CPUS - 1);
+ DPRINTF("Set master irq cpu %d\n", s->target_cpu);
break;
default:
break;
@@ -196,6 +211,36 @@ static const uint32_t intbit_to_level[32] = {
6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0,
};
+static void slavio_check_interrupts(void *opaque)
+{
+ SLAVIO_INTCTLState *s = opaque;
+ uint32_t pending = s->intregm_pending;
+ unsigned int i, max = 0;
+
+ pending &= ~s->intregm_disabled;
+
+ if (pending && !(s->intregm_disabled & 0x80000000)) {
+ for (i = 0; i < 32; i++) {
+ if (pending & (1 << i)) {
+ if (max < intbit_to_level[i])
+ max = intbit_to_level[i];
+ }
+ }
+ if (cpu_single_env->interrupt_index == 0) {
+ DPRINTF("Triggered pil %d\n", max);
+#ifdef DEBUG_IRQ_COUNT
+ s->irq_count[max]++;
+#endif
+ cpu_single_env->interrupt_index = TT_EXTINT | max;
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
+ }
+ else
+ DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, cpu_single_env->interrupt_index);
+ }
+ else
+ DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
+}
+
/*
* "irq" here is the bit number in the system interrupt register to
* separate serial and keyboard interrupts sharing a level.
@@ -204,6 +249,7 @@ void slavio_pic_set_irq(void *opaque, int irq, int level)
{
SLAVIO_INTCTLState *s = opaque;
+ DPRINTF("Set irq %d level %d\n", irq, level);
if (irq < 32) {
uint32_t mask = 1 << irq;
uint32_t pil = intbit_to_level[irq];
@@ -216,19 +262,9 @@ void slavio_pic_set_irq(void *opaque, int irq, int level)
s->intregm_pending &= ~mask;
s->intreg_pending[s->target_cpu] &= ~(1 << pil);
}
- if (level &&
- !(s->intregm_disabled & mask) &&
- !(s->intregm_disabled & 0x80000000) &&
- (pil == 15 || (pil > cpu_single_env->psrpil && cpu_single_env->psret == 1))) {
-#ifdef DEBUG_IRQ_COUNT
- if (level == 1)
- s->irq_count[pil]++;
-#endif
- cpu_single_env->interrupt_index = TT_EXTINT | pil;
- cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
- }
}
}
+ slavio_check_interrupts(s);
}
static void slavio_intctl_save(QEMUFile *f, void *opaque)