Commit 24be5ae3a075319a57477fd03b1bdfb74f7f4d05
1 parent
2e719ba3
Add PowerPC 405 input pins (IRQ, resets, ...) model.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2654 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
133 additions
and
24 deletions
hw/ppc.c
| ... | ... | @@ -56,23 +56,23 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) |
| 56 | 56 | #endif |
| 57 | 57 | cur_level = (env->irq_input_state >> pin) & 1; |
| 58 | 58 | /* Don't generate spurious events */ |
| 59 | - if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0) || 0) { | |
| 59 | + if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { | |
| 60 | 60 | switch (pin) { |
| 61 | - case PPC_INPUT_INT: | |
| 62 | - /* Level sensitive - asserted high */ | |
| 61 | + case PPC6xx_INPUT_INT: | |
| 62 | + /* Level sensitive - active high */ | |
| 63 | 63 | #if defined(PPC_DEBUG_IRQ) |
| 64 | 64 | printf("%s: set the external IRQ state to %d\n", __func__, level); |
| 65 | 65 | #endif |
| 66 | 66 | ppc_set_irq(env, PPC_INTERRUPT_EXT, level); |
| 67 | 67 | break; |
| 68 | - case PPC_INPUT_SMI: | |
| 68 | + case PPC6xx_INPUT_SMI: | |
| 69 | 69 | /* Level sensitive - active high */ |
| 70 | 70 | #if defined(PPC_DEBUG_IRQ) |
| 71 | 71 | printf("%s: set the SMI IRQ state to %d\n", __func__, level); |
| 72 | 72 | #endif |
| 73 | 73 | ppc_set_irq(env, PPC_INTERRUPT_SMI, level); |
| 74 | 74 | break; |
| 75 | - case PPC_INPUT_MCP: | |
| 75 | + case PPC6xx_INPUT_MCP: | |
| 76 | 76 | /* Negative edge sensitive */ |
| 77 | 77 | /* XXX: TODO: actual reaction may depends on HID0 status |
| 78 | 78 | * 603/604/740/750: check HID0[EMCP] |
| ... | ... | @@ -84,7 +84,7 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) |
| 84 | 84 | ppc_set_irq(env, PPC_INTERRUPT_MCK, 1); |
| 85 | 85 | } |
| 86 | 86 | break; |
| 87 | - case PPC_INPUT_CKSTP_IN: | |
| 87 | + case PPC6xx_INPUT_CKSTP_IN: | |
| 88 | 88 | /* Level sensitive - active low */ |
| 89 | 89 | /* XXX: TODO: relay the signal to CKSTP_OUT pin */ |
| 90 | 90 | if (level) { |
| ... | ... | @@ -99,7 +99,7 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) |
| 99 | 99 | env->halted = 0; |
| 100 | 100 | } |
| 101 | 101 | break; |
| 102 | - case PPC_INPUT_HRESET: | |
| 102 | + case PPC6xx_INPUT_HRESET: | |
| 103 | 103 | /* Level sensitive - active low */ |
| 104 | 104 | if (level) { |
| 105 | 105 | #if 0 // XXX: TOFIX |
| ... | ... | @@ -110,7 +110,7 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) |
| 110 | 110 | #endif |
| 111 | 111 | } |
| 112 | 112 | break; |
| 113 | - case PPC_INPUT_SRESET: | |
| 113 | + case PPC6xx_INPUT_SRESET: | |
| 114 | 114 | #if defined(PPC_DEBUG_IRQ) |
| 115 | 115 | printf("%s: set the RESET IRQ state to %d\n", __func__, level); |
| 116 | 116 | #endif |
| ... | ... | @@ -135,6 +135,92 @@ void ppc6xx_irq_init (CPUState *env) |
| 135 | 135 | env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6); |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | +/* PowerPC 405 internal IRQ controller */ | |
| 139 | +static void ppc405_set_irq (void *opaque, int pin, int level) | |
| 140 | +{ | |
| 141 | + CPUState *env = opaque; | |
| 142 | + int cur_level; | |
| 143 | + | |
| 144 | +#if defined(PPC_DEBUG_IRQ) | |
| 145 | + printf("%s: env %p pin %d level %d\n", __func__, env, pin, level); | |
| 146 | +#endif | |
| 147 | + cur_level = (env->irq_input_state >> pin) & 1; | |
| 148 | + /* Don't generate spurious events */ | |
| 149 | + if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { | |
| 150 | + switch (pin) { | |
| 151 | + case PPC405_INPUT_RESET_SYS: | |
| 152 | + /* XXX: TODO: reset all peripherals */ | |
| 153 | + /* No break here */ | |
| 154 | + case PPC405_INPUT_RESET_CHIP: | |
| 155 | + /* XXX: TODO: reset on-chip peripherals */ | |
| 156 | + /* No break here */ | |
| 157 | + case PPC405_INPUT_RESET_CORE: | |
| 158 | + /* XXX: TODO: update DBSR[MRR] */ | |
| 159 | + if (level) { | |
| 160 | +#if 0 // XXX: TOFIX | |
| 161 | +#if defined(PPC_DEBUG_IRQ) | |
| 162 | + printf("%s: reset the CPU\n", __func__); | |
| 163 | +#endif | |
| 164 | + cpu_reset(env); | |
| 165 | +#endif | |
| 166 | + } | |
| 167 | + break; | |
| 168 | + case PPC405_INPUT_CINT: | |
| 169 | + /* Level sensitive - active high */ | |
| 170 | +#if defined(PPC_DEBUG_IRQ) | |
| 171 | + printf("%s: set the critical IRQ state to %d\n", __func__, level); | |
| 172 | +#endif | |
| 173 | + /* XXX: TOFIX */ | |
| 174 | + ppc_set_irq(env, PPC_INTERRUPT_RESET, level); | |
| 175 | + break; | |
| 176 | + case PPC405_INPUT_INT: | |
| 177 | + /* Level sensitive - active high */ | |
| 178 | +#if defined(PPC_DEBUG_IRQ) | |
| 179 | + printf("%s: set the external IRQ state to %d\n", __func__, level); | |
| 180 | +#endif | |
| 181 | + ppc_set_irq(env, PPC_INTERRUPT_EXT, level); | |
| 182 | + break; | |
| 183 | + case PPC405_INPUT_HALT: | |
| 184 | + /* Level sensitive - active low */ | |
| 185 | + if (level) { | |
| 186 | +#if defined(PPC_DEBUG_IRQ) | |
| 187 | + printf("%s: stop the CPU\n", __func__); | |
| 188 | +#endif | |
| 189 | + env->halted = 1; | |
| 190 | + } else { | |
| 191 | +#if defined(PPC_DEBUG_IRQ) | |
| 192 | + printf("%s: restart the CPU\n", __func__); | |
| 193 | +#endif | |
| 194 | + env->halted = 0; | |
| 195 | + } | |
| 196 | + break; | |
| 197 | + case PPC405_INPUT_DEBUG: | |
| 198 | + /* Level sensitive - active high */ | |
| 199 | +#if defined(PPC_DEBUG_IRQ) | |
| 200 | + printf("%s: set the external IRQ state to %d\n", __func__, level); | |
| 201 | +#endif | |
| 202 | + ppc_set_irq(env, EXCP_40x_DEBUG, level); | |
| 203 | + break; | |
| 204 | + default: | |
| 205 | + /* Unknown pin - do nothing */ | |
| 206 | +#if defined(PPC_DEBUG_IRQ) | |
| 207 | + printf("%s: unknown IRQ pin %d\n", __func__, pin); | |
| 208 | +#endif | |
| 209 | + return; | |
| 210 | + } | |
| 211 | + if (level) | |
| 212 | + env->irq_input_state |= 1 << pin; | |
| 213 | + else | |
| 214 | + env->irq_input_state &= ~(1 << pin); | |
| 215 | + } | |
| 216 | +} | |
| 217 | + | |
| 218 | +void ppc405_irq_init (CPUState *env) | |
| 219 | +{ | |
| 220 | + printf("%s\n", __func__); | |
| 221 | + env->irq_inputs = (void **)qemu_allocate_irqs(&ppc405_set_irq, env, 7); | |
| 222 | +} | |
| 223 | + | |
| 138 | 224 | /*****************************************************************************/ |
| 139 | 225 | /* PowerPC time base and decrementer emulation */ |
| 140 | 226 | //#define DEBUG_TB | ... | ... |
hw/ppc_chrp.c
| ... | ... | @@ -470,14 +470,14 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device, |
| 470 | 470 | */ |
| 471 | 471 | openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB); |
| 472 | 472 | openpic_irqs[i][OPENPIC_OUTPUT_INT] = |
| 473 | - ((qemu_irq *)env->irq_inputs)[PPC_INPUT_INT]; | |
| 473 | + ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; | |
| 474 | 474 | openpic_irqs[i][OPENPIC_OUTPUT_CINT] = |
| 475 | - ((qemu_irq *)env->irq_inputs)[PPC_INPUT_INT]; | |
| 475 | + ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; | |
| 476 | 476 | openpic_irqs[i][OPENPIC_OUTPUT_MCK] = |
| 477 | - ((qemu_irq *)env->irq_inputs)[PPC_INPUT_MCP]; | |
| 477 | + ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP]; | |
| 478 | 478 | openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Not connected ? */ |
| 479 | 479 | openpic_irqs[i][OPENPIC_OUTPUT_RESET] = |
| 480 | - ((qemu_irq *)env->irq_inputs)[PPC_INPUT_HRESET]; /* Check this */ | |
| 480 | + ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET]; /* Check this */ | |
| 481 | 481 | } |
| 482 | 482 | pic = openpic_init(NULL, &openpic_mem_index, smp_cpus, |
| 483 | 483 | openpic_irqs, NULL); | ... | ... |
hw/ppc_prep.c
| ... | ... | @@ -598,7 +598,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device, |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | 600 | isa_mem_base = 0xc0000000; |
| 601 | - i8259 = i8259_init(first_cpu->irq_inputs[PPC_INPUT_INT]); | |
| 601 | + i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]); | |
| 602 | 602 | pci_bus = pci_prep_init(i8259); |
| 603 | 603 | // pci_bus = i440fx_init(); |
| 604 | 604 | /* Register 8 MB of ISA IO space (needed for non-contiguous map) */ | ... | ... |
target-ppc/cpu.h
| ... | ... | @@ -1315,15 +1315,34 @@ enum { |
| 1315 | 1315 | /* Input pins definitions */ |
| 1316 | 1316 | enum { |
| 1317 | 1317 | /* 6xx bus input pins */ |
| 1318 | - PPC_INPUT_HRESET = 0, | |
| 1319 | - PPC_INPUT_SRESET = 1, | |
| 1320 | - PPC_INPUT_CKSTP_IN = 2, | |
| 1321 | - PPC_INPUT_MCP = 3, | |
| 1322 | - PPC_INPUT_SMI = 4, | |
| 1323 | - PPC_INPUT_INT = 5, | |
| 1318 | + PPC6xx_INPUT_HRESET = 0, | |
| 1319 | + PPC6xx_INPUT_SRESET = 1, | |
| 1320 | + PPC6xx_INPUT_CKSTP_IN = 2, | |
| 1321 | + PPC6xx_INPUT_MCP = 3, | |
| 1322 | + PPC6xx_INPUT_SMI = 4, | |
| 1323 | + PPC6xx_INPUT_INT = 5, | |
| 1324 | +}; | |
| 1325 | + | |
| 1326 | +enum { | |
| 1324 | 1327 | /* Embedded PowerPC input pins */ |
| 1325 | - PPC_INPUT_CINT = 6, | |
| 1326 | - PPC_INPUT_NB, | |
| 1328 | + PPCBookE_INPUT_HRESET = 0, | |
| 1329 | + PPCBookE_INPUT_SRESET = 1, | |
| 1330 | + PPCBookE_INPUT_CKSTP_IN = 2, | |
| 1331 | + PPCBookE_INPUT_MCP = 3, | |
| 1332 | + PPCBookE_INPUT_SMI = 4, | |
| 1333 | + PPCBookE_INPUT_INT = 5, | |
| 1334 | + PPCBookE_INPUT_CINT = 6, | |
| 1335 | +}; | |
| 1336 | + | |
| 1337 | +enum { | |
| 1338 | + /* PowerPC 405 input pins */ | |
| 1339 | + PPC405_INPUT_RESET_CORE = 0, | |
| 1340 | + PPC405_INPUT_RESET_CHIP = 1, | |
| 1341 | + PPC405_INPUT_RESET_SYS = 2, | |
| 1342 | + PPC405_INPUT_CINT = 3, | |
| 1343 | + PPC405_INPUT_INT = 4, | |
| 1344 | + PPC405_INPUT_HALT = 5, | |
| 1345 | + PPC405_INPUT_DEBUG = 6, | |
| 1327 | 1346 | }; |
| 1328 | 1347 | |
| 1329 | 1348 | /* Hardware exceptions definitions */ | ... | ... |
target-ppc/translate_init.c
| ... | ... | @@ -45,6 +45,7 @@ static inline void glue(glue(ppc, name),_irq_init) (CPUPPCState *env) \ |
| 45 | 45 | #define PPC_IRQ_INIT_FN(name) \ |
| 46 | 46 | void glue(glue(ppc, name),_irq_init) (CPUPPCState *env); |
| 47 | 47 | #endif |
| 48 | +PPC_IRQ_INIT_FN(405); | |
| 48 | 49 | PPC_IRQ_INIT_FN(6xx); |
| 49 | 50 | |
| 50 | 51 | /* Generic callbacks: |
| ... | ... | @@ -1909,7 +1910,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) |
| 1909 | 1910 | env->nb_tlb = 64; |
| 1910 | 1911 | env->nb_ways = 1; |
| 1911 | 1912 | env->id_tlbs = 0; |
| 1912 | - /* XXX: TODO: allocate internal IRQ controller */ | |
| 1913 | + /* Allocate hardware IRQ controller */ | |
| 1914 | + ppc405_irq_init(env); | |
| 1913 | 1915 | break; |
| 1914 | 1916 | |
| 1915 | 1917 | case CPU_PPC_NPE405H: /* NPe405 H family */ |
| ... | ... | @@ -1924,7 +1926,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) |
| 1924 | 1926 | env->nb_tlb = 64; |
| 1925 | 1927 | env->nb_ways = 1; |
| 1926 | 1928 | env->id_tlbs = 0; |
| 1927 | - /* XXX: TODO: allocate internal IRQ controller */ | |
| 1929 | + /* Allocate hardware IRQ controller */ | |
| 1930 | + ppc405_irq_init(env); | |
| 1928 | 1931 | break; |
| 1929 | 1932 | |
| 1930 | 1933 | #if defined (TODO) |
| ... | ... | @@ -1956,7 +1959,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) |
| 1956 | 1959 | env->nb_tlb = 64; |
| 1957 | 1960 | env->nb_ways = 1; |
| 1958 | 1961 | env->id_tlbs = 0; |
| 1959 | - /* XXX: TODO: allocate internal IRQ controller */ | |
| 1962 | + /* Allocate hardware IRQ controller */ | |
| 1963 | + ppc405_irq_init(env); | |
| 1960 | 1964 | break; |
| 1961 | 1965 | |
| 1962 | 1966 | case CPU_PPC_440EP: /* 440 EP family */ | ... | ... |