Add PowerPC 405 input pins (IRQ, resets, ...) model.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2654 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/hw/ppc.c b/hw/ppc.c
index f502271..8438bc6 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -56,23 +56,23 @@
 #endif
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0) || 0) {
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
         switch (pin) {
-        case PPC_INPUT_INT:
-            /* Level sensitive - asserted high */
+        case PPC6xx_INPUT_INT:
+            /* Level sensitive - active high */
 #if defined(PPC_DEBUG_IRQ)
             printf("%s: set the external IRQ state to %d\n", __func__, level);
 #endif
             ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
             break;
-        case PPC_INPUT_SMI:
+        case PPC6xx_INPUT_SMI:
             /* Level sensitive - active high */
 #if defined(PPC_DEBUG_IRQ)
             printf("%s: set the SMI IRQ state to %d\n", __func__, level);
 #endif
             ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
             break;
-        case PPC_INPUT_MCP:
+        case PPC6xx_INPUT_MCP:
             /* Negative edge sensitive */
             /* XXX: TODO: actual reaction may depends on HID0 status
              *            603/604/740/750: check HID0[EMCP]
@@ -84,7 +84,7 @@
                 ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
             }
             break;
-        case PPC_INPUT_CKSTP_IN:
+        case PPC6xx_INPUT_CKSTP_IN:
             /* Level sensitive - active low */
             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
             if (level) {
@@ -99,7 +99,7 @@
                 env->halted = 0;
             }
             break;
-        case PPC_INPUT_HRESET:
+        case PPC6xx_INPUT_HRESET:
             /* Level sensitive - active low */
             if (level) {
 #if 0 // XXX: TOFIX
@@ -110,7 +110,7 @@
 #endif
             }
             break;
-        case PPC_INPUT_SRESET:
+        case PPC6xx_INPUT_SRESET:
 #if defined(PPC_DEBUG_IRQ)
             printf("%s: set the RESET IRQ state to %d\n", __func__, level);
 #endif
@@ -135,6 +135,92 @@
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
 }
 
+/* PowerPC 405 internal IRQ controller */
+static void ppc405_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    printf("%s: env %p pin %d level %d\n", __func__, env, pin, level);
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC405_INPUT_RESET_SYS:
+            /* XXX: TODO: reset all peripherals */
+            /* No break here */
+        case PPC405_INPUT_RESET_CHIP:
+            /* XXX: TODO: reset on-chip peripherals */
+            /* No break here */
+        case PPC405_INPUT_RESET_CORE:
+            /* XXX: TODO: update DBSR[MRR] */
+            if (level) {
+#if 0 // XXX: TOFIX
+#if defined(PPC_DEBUG_IRQ)
+                printf("%s: reset the CPU\n", __func__);
+#endif
+                cpu_reset(env);
+#endif
+            }
+            break;
+        case PPC405_INPUT_CINT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            printf("%s: set the critical IRQ state to %d\n", __func__, level);
+#endif
+            /* XXX: TOFIX */
+            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            break;
+        case PPC405_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            printf("%s: set the external IRQ state to %d\n", __func__, level);
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC405_INPUT_HALT:
+            /* Level sensitive - active low */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                printf("%s: stop the CPU\n", __func__);
+#endif
+                env->halted = 1;
+            } else {
+#if defined(PPC_DEBUG_IRQ)
+                printf("%s: restart the CPU\n", __func__);
+#endif
+                env->halted = 0;
+            }
+            break;
+        case PPC405_INPUT_DEBUG:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            printf("%s: set the external IRQ state to %d\n", __func__, level);
+#endif
+            ppc_set_irq(env, EXCP_40x_DEBUG, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            printf("%s: unknown IRQ pin %d\n", __func__, pin);
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc405_irq_init (CPUState *env)
+{
+    printf("%s\n", __func__);
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc405_set_irq, env, 7);
+}
+
 /*****************************************************************************/
 /* PowerPC time base and decrementer emulation */
 //#define DEBUG_TB
diff --git a/hw/ppc_chrp.c b/hw/ppc_chrp.c
index c418cd1..70571fd 100644
--- a/hw/ppc_chrp.c
+++ b/hw/ppc_chrp.c
@@ -470,14 +470,14 @@
              */
             openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
             openpic_irqs[i][OPENPIC_OUTPUT_INT] =
-                ((qemu_irq *)env->irq_inputs)[PPC_INPUT_INT];
+                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
             openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
-                ((qemu_irq *)env->irq_inputs)[PPC_INPUT_INT];
+                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
             openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
-                ((qemu_irq *)env->irq_inputs)[PPC_INPUT_MCP];
+                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
             openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Not connected ? */
             openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
-                ((qemu_irq *)env->irq_inputs)[PPC_INPUT_HRESET]; /* Check this */
+                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET]; /* Check this */
         }
         pic = openpic_init(NULL, &openpic_mem_index, smp_cpus,
                            openpic_irqs, NULL);
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 8b53ef3..421d189 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -598,7 +598,7 @@
     }
 
     isa_mem_base = 0xc0000000;
-    i8259 = i8259_init(first_cpu->irq_inputs[PPC_INPUT_INT]);
+    i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
     pci_bus = pci_prep_init(i8259);
     //    pci_bus = i440fx_init();
     /* Register 8 MB of ISA IO space (needed for non-contiguous map) */