diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-04-16 07:34:39 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-04-16 07:34:39 +0000 |
commit | d0dfae6e91d9b2044523ed4db890860f898af86b (patch) | |
tree | 73f9615826e5129cd4e4e2eb8d9c09cc4763c74c /hw/ppc.c | |
parent | 08e46e54ea498b7e9a2a415435844f21c17064fc (diff) |
Add bus model (or input pins) into PowerPC CPU flags.
Add PowerPC 970 bus and exceptions model.
Add code provision for PowerPC 970 instanciation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2680 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/ppc.c')
-rw-r--r-- | hw/ppc.c | 122 |
1 files changed, 122 insertions, 0 deletions
@@ -161,6 +161,128 @@ void ppc6xx_irq_init (CPUState *env) env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6); } +/* PowerPC 970 internal IRQ controller */ +static void ppc970_set_irq (void *opaque, int pin, int level) +{ + CPUState *env = opaque; + int cur_level; + +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%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 PPC970_INPUT_INT: + /* Level sensitive - active high */ +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: set the external IRQ state to %d\n", + __func__, level); + } +#endif + ppc_set_irq(env, PPC_INTERRUPT_EXT, level); + break; + case PPC970_INPUT_THINT: + /* Level sensitive - active high */ +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__, + level); + } +#endif + ppc_set_irq(env, PPC_INTERRUPT_THERM, level); + break; + case PPC970_INPUT_MCP: + /* Negative edge sensitive */ + /* XXX: TODO: actual reaction may depends on HID0 status + * 603/604/740/750: check HID0[EMCP] + */ + if (cur_level == 1 && level == 0) { +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: raise machine check state\n", + __func__); + } +#endif + ppc_set_irq(env, PPC_INTERRUPT_MCK, 1); + } + break; + case PPC970_INPUT_CKSTP: + /* Level sensitive - active low */ + /* XXX: TODO: relay the signal to CKSTP_OUT pin */ + if (level) { +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: stop the CPU\n", __func__); + } +#endif + env->halted = 1; + } else { +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: restart the CPU\n", __func__); + } +#endif + env->halted = 0; + } + break; + case PPC970_INPUT_HRESET: + /* Level sensitive - active low */ + if (level) { +#if 0 // XXX: TOFIX +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: reset the CPU\n", __func__); + } +#endif + cpu_reset(env); +#endif + } + break; + case PPC970_INPUT_SRESET: +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: set the RESET IRQ state to %d\n", + __func__, level); + } +#endif + ppc_set_irq(env, PPC_INTERRUPT_RESET, level); + break; + case PPC970_INPUT_TBEN: +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: set the TBEN state to %d\n", __func__, + level); + } +#endif + /* XXX: TODO */ + break; + default: + /* Unknown pin - do nothing */ +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%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 ppc970_irq_init (CPUState *env) +{ + env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7); +} + /* PowerPC 405 internal IRQ controller */ static void ppc405_set_irq (void *opaque, int pin, int level) { |