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 */ | ... | ... |