Statistics
| Branch: | Revision:

root / hw / ppc.c @ dbdd2506

History | View | Annotate | Download (39.6 kB)

1 a541f297 bellard
/*
2 e9df014c j_mayer
 * QEMU generic PowerPC hardware System Emulator
3 5fafdf24 ths
 *
4 76a66253 j_mayer
 * Copyright (c) 2003-2007 Jocelyn Mayer
5 5fafdf24 ths
 *
6 a541f297 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 a541f297 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 a541f297 bellard
 * in the Software without restriction, including without limitation the rights
9 a541f297 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 a541f297 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 a541f297 bellard
 * furnished to do so, subject to the following conditions:
12 a541f297 bellard
 *
13 a541f297 bellard
 * The above copyright notice and this permission notice shall be included in
14 a541f297 bellard
 * all copies or substantial portions of the Software.
15 a541f297 bellard
 *
16 a541f297 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 a541f297 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 a541f297 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 a541f297 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 a541f297 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 a541f297 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 a541f297 bellard
 * THE SOFTWARE.
23 a541f297 bellard
 */
24 a541f297 bellard
#include "vl.h"
25 fd0bbb12 bellard
#include "m48t59.h"
26 a541f297 bellard
27 e9df014c j_mayer
//#define PPC_DEBUG_IRQ
28 4b6d0a4c j_mayer
//#define PPC_DEBUG_TB
29 e9df014c j_mayer
30 47103572 j_mayer
extern FILE *logfile;
31 47103572 j_mayer
extern int loglevel;
32 47103572 j_mayer
33 dbdd2506 j_mayer
static void cpu_ppc_tb_stop (CPUState *env);
34 dbdd2506 j_mayer
static void cpu_ppc_tb_start (CPUState *env);
35 dbdd2506 j_mayer
36 00af685f j_mayer
static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
37 47103572 j_mayer
{
38 47103572 j_mayer
    if (level) {
39 47103572 j_mayer
        env->pending_interrupts |= 1 << n_IRQ;
40 47103572 j_mayer
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
41 47103572 j_mayer
    } else {
42 47103572 j_mayer
        env->pending_interrupts &= ~(1 << n_IRQ);
43 47103572 j_mayer
        if (env->pending_interrupts == 0)
44 47103572 j_mayer
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
45 47103572 j_mayer
    }
46 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
47 a496775f j_mayer
    if (loglevel & CPU_LOG_INT) {
48 a496775f j_mayer
        fprintf(logfile, "%s: %p n_IRQ %d level %d => pending %08x req %08x\n",
49 a496775f j_mayer
                __func__, env, n_IRQ, level,
50 a496775f j_mayer
                env->pending_interrupts, env->interrupt_request);
51 a496775f j_mayer
    }
52 47103572 j_mayer
#endif
53 47103572 j_mayer
}
54 47103572 j_mayer
55 e9df014c j_mayer
/* PowerPC 6xx / 7xx internal IRQ controller */
56 e9df014c j_mayer
static void ppc6xx_set_irq (void *opaque, int pin, int level)
57 d537cf6c pbrook
{
58 e9df014c j_mayer
    CPUState *env = opaque;
59 e9df014c j_mayer
    int cur_level;
60 d537cf6c pbrook
61 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
62 a496775f j_mayer
    if (loglevel & CPU_LOG_INT) {
63 a496775f j_mayer
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
64 a496775f j_mayer
                env, pin, level);
65 a496775f j_mayer
    }
66 e9df014c j_mayer
#endif
67 e9df014c j_mayer
    cur_level = (env->irq_input_state >> pin) & 1;
68 e9df014c j_mayer
    /* Don't generate spurious events */
69 24be5ae3 j_mayer
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
70 e9df014c j_mayer
        switch (pin) {
71 dbdd2506 j_mayer
        case PPC6xx_INPUT_TBEN:
72 dbdd2506 j_mayer
            /* Level sensitive - active high */
73 dbdd2506 j_mayer
#if defined(PPC_DEBUG_IRQ)
74 dbdd2506 j_mayer
            if (loglevel & CPU_LOG_INT) {
75 dbdd2506 j_mayer
                fprintf(logfile, "%s: %s the time base\n",
76 dbdd2506 j_mayer
                        __func__, level ? "start" : "stop");
77 dbdd2506 j_mayer
            }
78 dbdd2506 j_mayer
#endif
79 dbdd2506 j_mayer
            if (level) {
80 dbdd2506 j_mayer
                cpu_ppc_tb_start(env);
81 dbdd2506 j_mayer
            } else {
82 dbdd2506 j_mayer
                cpu_ppc_tb_stop(env);
83 dbdd2506 j_mayer
            }
84 24be5ae3 j_mayer
        case PPC6xx_INPUT_INT:
85 24be5ae3 j_mayer
            /* Level sensitive - active high */
86 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
87 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
88 a496775f j_mayer
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
89 a496775f j_mayer
                        __func__, level);
90 a496775f j_mayer
            }
91 e9df014c j_mayer
#endif
92 e9df014c j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
93 e9df014c j_mayer
            break;
94 24be5ae3 j_mayer
        case PPC6xx_INPUT_SMI:
95 e9df014c j_mayer
            /* Level sensitive - active high */
96 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
97 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
98 a496775f j_mayer
                fprintf(logfile, "%s: set the SMI IRQ state to %d\n",
99 a496775f j_mayer
                        __func__, level);
100 a496775f j_mayer
            }
101 e9df014c j_mayer
#endif
102 e9df014c j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
103 e9df014c j_mayer
            break;
104 24be5ae3 j_mayer
        case PPC6xx_INPUT_MCP:
105 e9df014c j_mayer
            /* Negative edge sensitive */
106 e9df014c j_mayer
            /* XXX: TODO: actual reaction may depends on HID0 status
107 e9df014c j_mayer
             *            603/604/740/750: check HID0[EMCP]
108 e9df014c j_mayer
             */
109 e9df014c j_mayer
            if (cur_level == 1 && level == 0) {
110 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
111 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
112 a496775f j_mayer
                    fprintf(logfile, "%s: raise machine check state\n",
113 a496775f j_mayer
                            __func__);
114 a496775f j_mayer
                }
115 e9df014c j_mayer
#endif
116 e9df014c j_mayer
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
117 e9df014c j_mayer
            }
118 e9df014c j_mayer
            break;
119 24be5ae3 j_mayer
        case PPC6xx_INPUT_CKSTP_IN:
120 e9df014c j_mayer
            /* Level sensitive - active low */
121 e9df014c j_mayer
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
122 e63ecc6f j_mayer
            /* XXX: Note that the only way to restart the CPU is to reset it */
123 e9df014c j_mayer
            if (level) {
124 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
125 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
126 a496775f j_mayer
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
127 a496775f j_mayer
                }
128 e9df014c j_mayer
#endif
129 e9df014c j_mayer
                env->halted = 1;
130 e9df014c j_mayer
            }
131 e9df014c j_mayer
            break;
132 24be5ae3 j_mayer
        case PPC6xx_INPUT_HRESET:
133 e9df014c j_mayer
            /* Level sensitive - active low */
134 e9df014c j_mayer
            if (level) {
135 e9df014c j_mayer
#if 0 // XXX: TOFIX
136 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
137 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
138 a496775f j_mayer
                    fprintf(logfile, "%s: reset the CPU\n", __func__);
139 a496775f j_mayer
                }
140 e9df014c j_mayer
#endif
141 e9df014c j_mayer
                cpu_reset(env);
142 e9df014c j_mayer
#endif
143 e9df014c j_mayer
            }
144 e9df014c j_mayer
            break;
145 24be5ae3 j_mayer
        case PPC6xx_INPUT_SRESET:
146 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
147 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
148 a496775f j_mayer
                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
149 a496775f j_mayer
                        __func__, level);
150 a496775f j_mayer
            }
151 e9df014c j_mayer
#endif
152 e9df014c j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
153 e9df014c j_mayer
            break;
154 e9df014c j_mayer
        default:
155 e9df014c j_mayer
            /* Unknown pin - do nothing */
156 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
157 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
158 a496775f j_mayer
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
159 a496775f j_mayer
            }
160 e9df014c j_mayer
#endif
161 e9df014c j_mayer
            return;
162 e9df014c j_mayer
        }
163 e9df014c j_mayer
        if (level)
164 e9df014c j_mayer
            env->irq_input_state |= 1 << pin;
165 e9df014c j_mayer
        else
166 e9df014c j_mayer
            env->irq_input_state &= ~(1 << pin);
167 d537cf6c pbrook
    }
168 d537cf6c pbrook
}
169 d537cf6c pbrook
170 e9df014c j_mayer
void ppc6xx_irq_init (CPUState *env)
171 47103572 j_mayer
{
172 e9df014c j_mayer
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
173 47103572 j_mayer
}
174 47103572 j_mayer
175 00af685f j_mayer
#if defined(TARGET_PPC64)
176 d0dfae6e j_mayer
/* PowerPC 970 internal IRQ controller */
177 d0dfae6e j_mayer
static void ppc970_set_irq (void *opaque, int pin, int level)
178 d0dfae6e j_mayer
{
179 d0dfae6e j_mayer
    CPUState *env = opaque;
180 d0dfae6e j_mayer
    int cur_level;
181 d0dfae6e j_mayer
182 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
183 d0dfae6e j_mayer
    if (loglevel & CPU_LOG_INT) {
184 d0dfae6e j_mayer
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
185 d0dfae6e j_mayer
                env, pin, level);
186 d0dfae6e j_mayer
    }
187 d0dfae6e j_mayer
#endif
188 d0dfae6e j_mayer
    cur_level = (env->irq_input_state >> pin) & 1;
189 d0dfae6e j_mayer
    /* Don't generate spurious events */
190 d0dfae6e j_mayer
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
191 d0dfae6e j_mayer
        switch (pin) {
192 d0dfae6e j_mayer
        case PPC970_INPUT_INT:
193 d0dfae6e j_mayer
            /* Level sensitive - active high */
194 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
195 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
196 d0dfae6e j_mayer
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
197 d0dfae6e j_mayer
                        __func__, level);
198 d0dfae6e j_mayer
            }
199 d0dfae6e j_mayer
#endif
200 d0dfae6e j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
201 d0dfae6e j_mayer
            break;
202 d0dfae6e j_mayer
        case PPC970_INPUT_THINT:
203 d0dfae6e j_mayer
            /* Level sensitive - active high */
204 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
205 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
206 d0dfae6e j_mayer
                fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
207 d0dfae6e j_mayer
                        level);
208 d0dfae6e j_mayer
            }
209 d0dfae6e j_mayer
#endif
210 d0dfae6e j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
211 d0dfae6e j_mayer
            break;
212 d0dfae6e j_mayer
        case PPC970_INPUT_MCP:
213 d0dfae6e j_mayer
            /* Negative edge sensitive */
214 d0dfae6e j_mayer
            /* XXX: TODO: actual reaction may depends on HID0 status
215 d0dfae6e j_mayer
             *            603/604/740/750: check HID0[EMCP]
216 d0dfae6e j_mayer
             */
217 d0dfae6e j_mayer
            if (cur_level == 1 && level == 0) {
218 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
219 d0dfae6e j_mayer
                if (loglevel & CPU_LOG_INT) {
220 d0dfae6e j_mayer
                    fprintf(logfile, "%s: raise machine check state\n",
221 d0dfae6e j_mayer
                            __func__);
222 d0dfae6e j_mayer
                }
223 d0dfae6e j_mayer
#endif
224 d0dfae6e j_mayer
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
225 d0dfae6e j_mayer
            }
226 d0dfae6e j_mayer
            break;
227 d0dfae6e j_mayer
        case PPC970_INPUT_CKSTP:
228 d0dfae6e j_mayer
            /* Level sensitive - active low */
229 d0dfae6e j_mayer
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
230 d0dfae6e j_mayer
            if (level) {
231 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
232 d0dfae6e j_mayer
                if (loglevel & CPU_LOG_INT) {
233 d0dfae6e j_mayer
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
234 d0dfae6e j_mayer
                }
235 d0dfae6e j_mayer
#endif
236 d0dfae6e j_mayer
                env->halted = 1;
237 d0dfae6e j_mayer
            } else {
238 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
239 d0dfae6e j_mayer
                if (loglevel & CPU_LOG_INT) {
240 d0dfae6e j_mayer
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
241 d0dfae6e j_mayer
                }
242 d0dfae6e j_mayer
#endif
243 d0dfae6e j_mayer
                env->halted = 0;
244 d0dfae6e j_mayer
            }
245 d0dfae6e j_mayer
            break;
246 d0dfae6e j_mayer
        case PPC970_INPUT_HRESET:
247 d0dfae6e j_mayer
            /* Level sensitive - active low */
248 d0dfae6e j_mayer
            if (level) {
249 d0dfae6e j_mayer
#if 0 // XXX: TOFIX
250 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
251 d0dfae6e j_mayer
                if (loglevel & CPU_LOG_INT) {
252 d0dfae6e j_mayer
                    fprintf(logfile, "%s: reset the CPU\n", __func__);
253 d0dfae6e j_mayer
                }
254 d0dfae6e j_mayer
#endif
255 d0dfae6e j_mayer
                cpu_reset(env);
256 d0dfae6e j_mayer
#endif
257 d0dfae6e j_mayer
            }
258 d0dfae6e j_mayer
            break;
259 d0dfae6e j_mayer
        case PPC970_INPUT_SRESET:
260 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
261 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
262 d0dfae6e j_mayer
                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
263 d0dfae6e j_mayer
                        __func__, level);
264 d0dfae6e j_mayer
            }
265 d0dfae6e j_mayer
#endif
266 d0dfae6e j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
267 d0dfae6e j_mayer
            break;
268 d0dfae6e j_mayer
        case PPC970_INPUT_TBEN:
269 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
270 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
271 d0dfae6e j_mayer
                fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
272 d0dfae6e j_mayer
                        level);
273 d0dfae6e j_mayer
            }
274 d0dfae6e j_mayer
#endif
275 d0dfae6e j_mayer
            /* XXX: TODO */
276 d0dfae6e j_mayer
            break;
277 d0dfae6e j_mayer
        default:
278 d0dfae6e j_mayer
            /* Unknown pin - do nothing */
279 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
280 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
281 d0dfae6e j_mayer
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
282 d0dfae6e j_mayer
            }
283 d0dfae6e j_mayer
#endif
284 d0dfae6e j_mayer
            return;
285 d0dfae6e j_mayer
        }
286 d0dfae6e j_mayer
        if (level)
287 d0dfae6e j_mayer
            env->irq_input_state |= 1 << pin;
288 d0dfae6e j_mayer
        else
289 d0dfae6e j_mayer
            env->irq_input_state &= ~(1 << pin);
290 d0dfae6e j_mayer
    }
291 d0dfae6e j_mayer
}
292 d0dfae6e j_mayer
293 d0dfae6e j_mayer
void ppc970_irq_init (CPUState *env)
294 d0dfae6e j_mayer
{
295 d0dfae6e j_mayer
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
296 d0dfae6e j_mayer
}
297 00af685f j_mayer
#endif /* defined(TARGET_PPC64) */
298 d0dfae6e j_mayer
299 4e290a0b j_mayer
/* PowerPC 40x internal IRQ controller */
300 4e290a0b j_mayer
static void ppc40x_set_irq (void *opaque, int pin, int level)
301 24be5ae3 j_mayer
{
302 24be5ae3 j_mayer
    CPUState *env = opaque;
303 24be5ae3 j_mayer
    int cur_level;
304 24be5ae3 j_mayer
305 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
306 8ecc7913 j_mayer
    if (loglevel & CPU_LOG_INT) {
307 8ecc7913 j_mayer
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
308 8ecc7913 j_mayer
                env, pin, level);
309 8ecc7913 j_mayer
    }
310 24be5ae3 j_mayer
#endif
311 24be5ae3 j_mayer
    cur_level = (env->irq_input_state >> pin) & 1;
312 24be5ae3 j_mayer
    /* Don't generate spurious events */
313 24be5ae3 j_mayer
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
314 24be5ae3 j_mayer
        switch (pin) {
315 4e290a0b j_mayer
        case PPC40x_INPUT_RESET_SYS:
316 8ecc7913 j_mayer
            if (level) {
317 8ecc7913 j_mayer
#if defined(PPC_DEBUG_IRQ)
318 8ecc7913 j_mayer
                if (loglevel & CPU_LOG_INT) {
319 8ecc7913 j_mayer
                    fprintf(logfile, "%s: reset the PowerPC system\n",
320 8ecc7913 j_mayer
                            __func__);
321 8ecc7913 j_mayer
                }
322 8ecc7913 j_mayer
#endif
323 8ecc7913 j_mayer
                ppc40x_system_reset(env);
324 8ecc7913 j_mayer
            }
325 8ecc7913 j_mayer
            break;
326 4e290a0b j_mayer
        case PPC40x_INPUT_RESET_CHIP:
327 8ecc7913 j_mayer
            if (level) {
328 8ecc7913 j_mayer
#if defined(PPC_DEBUG_IRQ)
329 8ecc7913 j_mayer
                if (loglevel & CPU_LOG_INT) {
330 8ecc7913 j_mayer
                    fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
331 8ecc7913 j_mayer
                }
332 8ecc7913 j_mayer
#endif
333 8ecc7913 j_mayer
                ppc40x_chip_reset(env);
334 8ecc7913 j_mayer
            }
335 8ecc7913 j_mayer
            break;
336 4e290a0b j_mayer
        case PPC40x_INPUT_RESET_CORE:
337 24be5ae3 j_mayer
            /* XXX: TODO: update DBSR[MRR] */
338 24be5ae3 j_mayer
            if (level) {
339 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
340 8ecc7913 j_mayer
                if (loglevel & CPU_LOG_INT) {
341 8ecc7913 j_mayer
                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
342 8ecc7913 j_mayer
                }
343 24be5ae3 j_mayer
#endif
344 8ecc7913 j_mayer
                ppc40x_core_reset(env);
345 24be5ae3 j_mayer
            }
346 24be5ae3 j_mayer
            break;
347 4e290a0b j_mayer
        case PPC40x_INPUT_CINT:
348 24be5ae3 j_mayer
            /* Level sensitive - active high */
349 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
350 8ecc7913 j_mayer
            if (loglevel & CPU_LOG_INT) {
351 8ecc7913 j_mayer
                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
352 8ecc7913 j_mayer
                        __func__, level);
353 8ecc7913 j_mayer
            }
354 24be5ae3 j_mayer
#endif
355 4e290a0b j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
356 24be5ae3 j_mayer
            break;
357 4e290a0b j_mayer
        case PPC40x_INPUT_INT:
358 24be5ae3 j_mayer
            /* Level sensitive - active high */
359 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
360 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
361 a496775f j_mayer
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
362 a496775f j_mayer
                        __func__, level);
363 a496775f j_mayer
            }
364 24be5ae3 j_mayer
#endif
365 24be5ae3 j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
366 24be5ae3 j_mayer
            break;
367 4e290a0b j_mayer
        case PPC40x_INPUT_HALT:
368 24be5ae3 j_mayer
            /* Level sensitive - active low */
369 24be5ae3 j_mayer
            if (level) {
370 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
371 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
372 a496775f j_mayer
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
373 a496775f j_mayer
                }
374 24be5ae3 j_mayer
#endif
375 24be5ae3 j_mayer
                env->halted = 1;
376 24be5ae3 j_mayer
            } else {
377 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
378 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
379 a496775f j_mayer
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
380 a496775f j_mayer
                }
381 24be5ae3 j_mayer
#endif
382 24be5ae3 j_mayer
                env->halted = 0;
383 24be5ae3 j_mayer
            }
384 24be5ae3 j_mayer
            break;
385 4e290a0b j_mayer
        case PPC40x_INPUT_DEBUG:
386 24be5ae3 j_mayer
            /* Level sensitive - active high */
387 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
388 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
389 a750fc0b j_mayer
                fprintf(logfile, "%s: set the debug pin state to %d\n",
390 a496775f j_mayer
                        __func__, level);
391 a496775f j_mayer
            }
392 24be5ae3 j_mayer
#endif
393 a750fc0b j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
394 24be5ae3 j_mayer
            break;
395 24be5ae3 j_mayer
        default:
396 24be5ae3 j_mayer
            /* Unknown pin - do nothing */
397 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
398 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
399 a496775f j_mayer
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
400 a496775f j_mayer
            }
401 24be5ae3 j_mayer
#endif
402 24be5ae3 j_mayer
            return;
403 24be5ae3 j_mayer
        }
404 24be5ae3 j_mayer
        if (level)
405 24be5ae3 j_mayer
            env->irq_input_state |= 1 << pin;
406 24be5ae3 j_mayer
        else
407 24be5ae3 j_mayer
            env->irq_input_state &= ~(1 << pin);
408 24be5ae3 j_mayer
    }
409 24be5ae3 j_mayer
}
410 24be5ae3 j_mayer
411 4e290a0b j_mayer
void ppc40x_irq_init (CPUState *env)
412 24be5ae3 j_mayer
{
413 4e290a0b j_mayer
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
414 4e290a0b j_mayer
                                                  env, PPC40x_INPUT_NB);
415 24be5ae3 j_mayer
}
416 24be5ae3 j_mayer
417 9fddaa0c bellard
/*****************************************************************************/
418 e9df014c j_mayer
/* PowerPC time base and decrementer emulation */
419 9fddaa0c bellard
struct ppc_tb_t {
420 9fddaa0c bellard
    /* Time base management */
421 dbdd2506 j_mayer
    int64_t  tb_offset;    /* Compensation                    */
422 dbdd2506 j_mayer
    int64_t  atb_offset;   /* Compensation                    */
423 dbdd2506 j_mayer
    uint32_t tb_freq;      /* TB frequency                    */
424 9fddaa0c bellard
    /* Decrementer management */
425 dbdd2506 j_mayer
    uint64_t decr_next;    /* Tick for next decr interrupt    */
426 dbdd2506 j_mayer
    uint32_t decr_freq;    /* decrementer frequency           */
427 9fddaa0c bellard
    struct QEMUTimer *decr_timer;
428 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
429 58a7d328 j_mayer
    /* Hypervisor decrementer management */
430 58a7d328 j_mayer
    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
431 58a7d328 j_mayer
    struct QEMUTimer *hdecr_timer;
432 58a7d328 j_mayer
    uint64_t purr_load;
433 58a7d328 j_mayer
    uint64_t purr_start;
434 58a7d328 j_mayer
#endif
435 47103572 j_mayer
    void *opaque;
436 9fddaa0c bellard
};
437 9fddaa0c bellard
438 dbdd2506 j_mayer
static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
439 b068d6a7 j_mayer
                                              int64_t tb_offset)
440 9fddaa0c bellard
{
441 9fddaa0c bellard
    /* TB time in tb periods */
442 dbdd2506 j_mayer
    return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
443 9fddaa0c bellard
}
444 9fddaa0c bellard
445 9fddaa0c bellard
uint32_t cpu_ppc_load_tbl (CPUState *env)
446 9fddaa0c bellard
{
447 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
448 9fddaa0c bellard
    uint64_t tb;
449 9fddaa0c bellard
450 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
451 a062e36c j_mayer
#if defined(PPC_DEBUG_TB)
452 a062e36c j_mayer
    if (loglevel != 0) {
453 a062e36c j_mayer
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
454 9fddaa0c bellard
    }
455 9fddaa0c bellard
#endif
456 9fddaa0c bellard
457 9fddaa0c bellard
    return tb & 0xFFFFFFFF;
458 9fddaa0c bellard
}
459 9fddaa0c bellard
460 b068d6a7 j_mayer
static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
461 9fddaa0c bellard
{
462 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
463 9fddaa0c bellard
    uint64_t tb;
464 9fddaa0c bellard
465 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
466 4b6d0a4c j_mayer
#if defined(PPC_DEBUG_TB)
467 4b6d0a4c j_mayer
    if (loglevel != 0) {
468 a496775f j_mayer
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
469 a496775f j_mayer
    }
470 9fddaa0c bellard
#endif
471 76a66253 j_mayer
472 9fddaa0c bellard
    return tb >> 32;
473 9fddaa0c bellard
}
474 9fddaa0c bellard
475 8a84de23 j_mayer
uint32_t cpu_ppc_load_tbu (CPUState *env)
476 8a84de23 j_mayer
{
477 8a84de23 j_mayer
    return _cpu_ppc_load_tbu(env);
478 8a84de23 j_mayer
}
479 8a84de23 j_mayer
480 dbdd2506 j_mayer
static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
481 b068d6a7 j_mayer
                                            int64_t *tb_offsetp,
482 b068d6a7 j_mayer
                                            uint64_t value)
483 9fddaa0c bellard
{
484 dbdd2506 j_mayer
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
485 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
486 4b6d0a4c j_mayer
    if (loglevel != 0) {
487 4b6d0a4c j_mayer
        fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
488 a062e36c j_mayer
                *tb_offsetp);
489 a496775f j_mayer
    }
490 9fddaa0c bellard
#endif
491 9fddaa0c bellard
}
492 9fddaa0c bellard
493 a062e36c j_mayer
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
494 a062e36c j_mayer
{
495 a062e36c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
496 a062e36c j_mayer
    uint64_t tb;
497 a062e36c j_mayer
498 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
499 a062e36c j_mayer
    tb &= 0xFFFFFFFF00000000ULL;
500 dbdd2506 j_mayer
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
501 dbdd2506 j_mayer
                     &tb_env->tb_offset, tb | (uint64_t)value);
502 a062e36c j_mayer
}
503 a062e36c j_mayer
504 b068d6a7 j_mayer
static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
505 9fddaa0c bellard
{
506 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
507 a062e36c j_mayer
    uint64_t tb;
508 9fddaa0c bellard
509 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
510 a062e36c j_mayer
    tb &= 0x00000000FFFFFFFFULL;
511 dbdd2506 j_mayer
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
512 dbdd2506 j_mayer
                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
513 9fddaa0c bellard
}
514 9fddaa0c bellard
515 8a84de23 j_mayer
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
516 8a84de23 j_mayer
{
517 8a84de23 j_mayer
    _cpu_ppc_store_tbu(env, value);
518 8a84de23 j_mayer
}
519 8a84de23 j_mayer
520 a062e36c j_mayer
uint32_t cpu_ppc_load_atbl (CPUState *env)
521 a062e36c j_mayer
{
522 a062e36c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
523 a062e36c j_mayer
    uint64_t tb;
524 a062e36c j_mayer
525 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
526 a062e36c j_mayer
#if defined(PPC_DEBUG_TB)
527 a062e36c j_mayer
    if (loglevel != 0) {
528 a062e36c j_mayer
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
529 a062e36c j_mayer
    }
530 a062e36c j_mayer
#endif
531 a062e36c j_mayer
532 a062e36c j_mayer
    return tb & 0xFFFFFFFF;
533 a062e36c j_mayer
}
534 a062e36c j_mayer
535 a062e36c j_mayer
uint32_t cpu_ppc_load_atbu (CPUState *env)
536 a062e36c j_mayer
{
537 a062e36c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
538 a062e36c j_mayer
    uint64_t tb;
539 a062e36c j_mayer
540 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
541 a062e36c j_mayer
#if defined(PPC_DEBUG_TB)
542 a062e36c j_mayer
    if (loglevel != 0) {
543 a062e36c j_mayer
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
544 a062e36c j_mayer
    }
545 a062e36c j_mayer
#endif
546 a062e36c j_mayer
547 a062e36c j_mayer
    return tb >> 32;
548 a062e36c j_mayer
}
549 a062e36c j_mayer
550 a062e36c j_mayer
void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
551 a062e36c j_mayer
{
552 a062e36c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
553 a062e36c j_mayer
    uint64_t tb;
554 a062e36c j_mayer
555 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
556 a062e36c j_mayer
    tb &= 0xFFFFFFFF00000000ULL;
557 dbdd2506 j_mayer
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
558 dbdd2506 j_mayer
                     &tb_env->atb_offset, tb | (uint64_t)value);
559 a062e36c j_mayer
}
560 a062e36c j_mayer
561 a062e36c j_mayer
void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
562 9fddaa0c bellard
{
563 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
564 a062e36c j_mayer
    uint64_t tb;
565 9fddaa0c bellard
566 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
567 a062e36c j_mayer
    tb &= 0x00000000FFFFFFFFULL;
568 dbdd2506 j_mayer
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
569 dbdd2506 j_mayer
                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
570 dbdd2506 j_mayer
}
571 dbdd2506 j_mayer
572 dbdd2506 j_mayer
static void cpu_ppc_tb_stop (CPUState *env)
573 dbdd2506 j_mayer
{
574 dbdd2506 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
575 dbdd2506 j_mayer
    uint64_t tb, atb, vmclk;
576 dbdd2506 j_mayer
577 dbdd2506 j_mayer
    /* If the time base is already frozen, do nothing */
578 dbdd2506 j_mayer
    if (tb_env->tb_freq != 0) {
579 dbdd2506 j_mayer
        vmclk = qemu_get_clock(vm_clock);
580 dbdd2506 j_mayer
        /* Get the time base */
581 dbdd2506 j_mayer
        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
582 dbdd2506 j_mayer
        /* Get the alternate time base */
583 dbdd2506 j_mayer
        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
584 dbdd2506 j_mayer
        /* Store the time base value (ie compute the current offset) */
585 dbdd2506 j_mayer
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
586 dbdd2506 j_mayer
        /* Store the alternate time base value (compute the current offset) */
587 dbdd2506 j_mayer
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
588 dbdd2506 j_mayer
        /* Set the time base frequency to zero */
589 dbdd2506 j_mayer
        tb_env->tb_freq = 0;
590 dbdd2506 j_mayer
        /* Now, the time bases are frozen to tb_offset / atb_offset value */
591 dbdd2506 j_mayer
    }
592 dbdd2506 j_mayer
}
593 dbdd2506 j_mayer
594 dbdd2506 j_mayer
static void cpu_ppc_tb_start (CPUState *env)
595 dbdd2506 j_mayer
{
596 dbdd2506 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
597 dbdd2506 j_mayer
    uint64_t tb, atb, vmclk;
598 dbdd2506 j_mayer
    
599 dbdd2506 j_mayer
    /* If the time base is not frozen, do nothing */
600 dbdd2506 j_mayer
    if (tb_env->tb_freq == 0) {
601 dbdd2506 j_mayer
        vmclk = qemu_get_clock(vm_clock);
602 dbdd2506 j_mayer
        /* Get the time base from tb_offset */
603 dbdd2506 j_mayer
        tb = tb_env->tb_offset;
604 dbdd2506 j_mayer
        /* Get the alternate time base from atb_offset */
605 dbdd2506 j_mayer
        atb = tb_env->atb_offset;
606 dbdd2506 j_mayer
        /* Restore the tb frequency from the decrementer frequency */
607 dbdd2506 j_mayer
        tb_env->tb_freq = tb_env->decr_freq;
608 dbdd2506 j_mayer
        /* Store the time base value */
609 dbdd2506 j_mayer
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
610 dbdd2506 j_mayer
        /* Store the alternate time base value */
611 dbdd2506 j_mayer
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
612 dbdd2506 j_mayer
    }
613 9fddaa0c bellard
}
614 9fddaa0c bellard
615 b068d6a7 j_mayer
static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
616 b068d6a7 j_mayer
                                                  uint64_t *next)
617 9fddaa0c bellard
{
618 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
619 9fddaa0c bellard
    uint32_t decr;
620 4e588a4d bellard
    int64_t diff;
621 9fddaa0c bellard
622 4e588a4d bellard
    diff = tb_env->decr_next - qemu_get_clock(vm_clock);
623 4e588a4d bellard
    if (diff >= 0)
624 dbdd2506 j_mayer
        decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
625 4e588a4d bellard
    else
626 dbdd2506 j_mayer
        decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
627 4b6d0a4c j_mayer
#if defined(PPC_DEBUG_TB)
628 4b6d0a4c j_mayer
    if (loglevel != 0) {
629 a496775f j_mayer
        fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
630 a496775f j_mayer
    }
631 9fddaa0c bellard
#endif
632 76a66253 j_mayer
633 9fddaa0c bellard
    return decr;
634 9fddaa0c bellard
}
635 9fddaa0c bellard
636 58a7d328 j_mayer
uint32_t cpu_ppc_load_decr (CPUState *env)
637 58a7d328 j_mayer
{
638 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
639 58a7d328 j_mayer
640 58a7d328 j_mayer
    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
641 58a7d328 j_mayer
}
642 58a7d328 j_mayer
643 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
644 58a7d328 j_mayer
uint32_t cpu_ppc_load_hdecr (CPUState *env)
645 58a7d328 j_mayer
{
646 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
647 58a7d328 j_mayer
648 58a7d328 j_mayer
    return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
649 58a7d328 j_mayer
}
650 58a7d328 j_mayer
651 58a7d328 j_mayer
uint64_t cpu_ppc_load_purr (CPUState *env)
652 58a7d328 j_mayer
{
653 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
654 58a7d328 j_mayer
    uint64_t diff;
655 58a7d328 j_mayer
656 58a7d328 j_mayer
    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
657 b33c17e1 j_mayer
658 58a7d328 j_mayer
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
659 58a7d328 j_mayer
}
660 58a7d328 j_mayer
#endif /* defined(TARGET_PPC64H) */
661 58a7d328 j_mayer
662 9fddaa0c bellard
/* When decrementer expires,
663 9fddaa0c bellard
 * all we need to do is generate or queue a CPU exception
664 9fddaa0c bellard
 */
665 b068d6a7 j_mayer
static always_inline void cpu_ppc_decr_excp (CPUState *env)
666 9fddaa0c bellard
{
667 9fddaa0c bellard
    /* Raise it */
668 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
669 4b6d0a4c j_mayer
    if (loglevel != 0) {
670 a496775f j_mayer
        fprintf(logfile, "raise decrementer exception\n");
671 a496775f j_mayer
    }
672 9fddaa0c bellard
#endif
673 47103572 j_mayer
    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
674 9fddaa0c bellard
}
675 9fddaa0c bellard
676 b068d6a7 j_mayer
static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
677 58a7d328 j_mayer
{
678 58a7d328 j_mayer
    /* Raise it */
679 58a7d328 j_mayer
#ifdef PPC_DEBUG_TB
680 58a7d328 j_mayer
    if (loglevel != 0) {
681 58a7d328 j_mayer
        fprintf(logfile, "raise decrementer exception\n");
682 58a7d328 j_mayer
    }
683 58a7d328 j_mayer
#endif
684 58a7d328 j_mayer
    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
685 58a7d328 j_mayer
}
686 58a7d328 j_mayer
687 58a7d328 j_mayer
static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
688 b33c17e1 j_mayer
                                  struct QEMUTimer *timer,
689 b33c17e1 j_mayer
                                  void (*raise_excp)(CPUState *),
690 b33c17e1 j_mayer
                                  uint32_t decr, uint32_t value,
691 b33c17e1 j_mayer
                                  int is_excp)
692 9fddaa0c bellard
{
693 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
694 9fddaa0c bellard
    uint64_t now, next;
695 9fddaa0c bellard
696 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
697 4b6d0a4c j_mayer
    if (loglevel != 0) {
698 a496775f j_mayer
        fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
699 a496775f j_mayer
    }
700 9fddaa0c bellard
#endif
701 9fddaa0c bellard
    now = qemu_get_clock(vm_clock);
702 dbdd2506 j_mayer
    next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
703 9fddaa0c bellard
    if (is_excp)
704 58a7d328 j_mayer
        next += *nextp - now;
705 9fddaa0c bellard
    if (next == now)
706 76a66253 j_mayer
        next++;
707 58a7d328 j_mayer
    *nextp = next;
708 9fddaa0c bellard
    /* Adjust timer */
709 58a7d328 j_mayer
    qemu_mod_timer(timer, next);
710 9fddaa0c bellard
    /* If we set a negative value and the decrementer was positive,
711 9fddaa0c bellard
     * raise an exception.
712 9fddaa0c bellard
     */
713 9fddaa0c bellard
    if ((value & 0x80000000) && !(decr & 0x80000000))
714 58a7d328 j_mayer
        (*raise_excp)(env);
715 58a7d328 j_mayer
}
716 58a7d328 j_mayer
717 b068d6a7 j_mayer
static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
718 b068d6a7 j_mayer
                                               uint32_t value, int is_excp)
719 58a7d328 j_mayer
{
720 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
721 58a7d328 j_mayer
722 58a7d328 j_mayer
    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
723 58a7d328 j_mayer
                         &cpu_ppc_decr_excp, decr, value, is_excp);
724 9fddaa0c bellard
}
725 9fddaa0c bellard
726 9fddaa0c bellard
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
727 9fddaa0c bellard
{
728 9fddaa0c bellard
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
729 9fddaa0c bellard
}
730 9fddaa0c bellard
731 9fddaa0c bellard
static void cpu_ppc_decr_cb (void *opaque)
732 9fddaa0c bellard
{
733 9fddaa0c bellard
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
734 9fddaa0c bellard
}
735 9fddaa0c bellard
736 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
737 b068d6a7 j_mayer
static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
738 b068d6a7 j_mayer
                                                uint32_t value, int is_excp)
739 58a7d328 j_mayer
{
740 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
741 58a7d328 j_mayer
742 58a7d328 j_mayer
    __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
743 58a7d328 j_mayer
                         &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
744 58a7d328 j_mayer
}
745 58a7d328 j_mayer
746 58a7d328 j_mayer
void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
747 58a7d328 j_mayer
{
748 58a7d328 j_mayer
    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
749 58a7d328 j_mayer
}
750 58a7d328 j_mayer
751 58a7d328 j_mayer
static void cpu_ppc_hdecr_cb (void *opaque)
752 58a7d328 j_mayer
{
753 58a7d328 j_mayer
    _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
754 58a7d328 j_mayer
}
755 58a7d328 j_mayer
756 58a7d328 j_mayer
void cpu_ppc_store_purr (CPUState *env, uint64_t value)
757 58a7d328 j_mayer
{
758 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
759 58a7d328 j_mayer
760 58a7d328 j_mayer
    tb_env->purr_load = value;
761 58a7d328 j_mayer
    tb_env->purr_start = qemu_get_clock(vm_clock);
762 58a7d328 j_mayer
}
763 58a7d328 j_mayer
#endif /* defined(TARGET_PPC64H) */
764 58a7d328 j_mayer
765 8ecc7913 j_mayer
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
766 8ecc7913 j_mayer
{
767 8ecc7913 j_mayer
    CPUState *env = opaque;
768 8ecc7913 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
769 8ecc7913 j_mayer
770 8ecc7913 j_mayer
    tb_env->tb_freq = freq;
771 dbdd2506 j_mayer
    tb_env->decr_freq = freq;
772 8ecc7913 j_mayer
    /* There is a bug in Linux 2.4 kernels:
773 8ecc7913 j_mayer
     * if a decrementer exception is pending when it enables msr_ee at startup,
774 8ecc7913 j_mayer
     * it's not ready to handle it...
775 8ecc7913 j_mayer
     */
776 8ecc7913 j_mayer
    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
777 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
778 58a7d328 j_mayer
    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
779 58a7d328 j_mayer
    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
780 58a7d328 j_mayer
#endif /* defined(TARGET_PPC64H) */
781 8ecc7913 j_mayer
}
782 8ecc7913 j_mayer
783 9fddaa0c bellard
/* Set up (once) timebase frequency (in Hz) */
784 8ecc7913 j_mayer
clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
785 9fddaa0c bellard
{
786 9fddaa0c bellard
    ppc_tb_t *tb_env;
787 9fddaa0c bellard
788 9fddaa0c bellard
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
789 9fddaa0c bellard
    if (tb_env == NULL)
790 9fddaa0c bellard
        return NULL;
791 9fddaa0c bellard
    env->tb_env = tb_env;
792 8ecc7913 j_mayer
    /* Create new timer */
793 8ecc7913 j_mayer
    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
794 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
795 58a7d328 j_mayer
    tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
796 58a7d328 j_mayer
#endif /* defined(TARGET_PPC64H) */
797 8ecc7913 j_mayer
    cpu_ppc_set_tb_clk(env, freq);
798 9fddaa0c bellard
799 8ecc7913 j_mayer
    return &cpu_ppc_set_tb_clk;
800 9fddaa0c bellard
}
801 9fddaa0c bellard
802 76a66253 j_mayer
/* Specific helpers for POWER & PowerPC 601 RTC */
803 8ecc7913 j_mayer
clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
804 76a66253 j_mayer
{
805 76a66253 j_mayer
    return cpu_ppc_tb_init(env, 7812500);
806 76a66253 j_mayer
}
807 76a66253 j_mayer
808 76a66253 j_mayer
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
809 8a84de23 j_mayer
{
810 8a84de23 j_mayer
    _cpu_ppc_store_tbu(env, value);
811 8a84de23 j_mayer
}
812 76a66253 j_mayer
813 76a66253 j_mayer
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
814 8a84de23 j_mayer
{
815 8a84de23 j_mayer
    return _cpu_ppc_load_tbu(env);
816 8a84de23 j_mayer
}
817 76a66253 j_mayer
818 76a66253 j_mayer
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
819 76a66253 j_mayer
{
820 76a66253 j_mayer
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
821 76a66253 j_mayer
}
822 76a66253 j_mayer
823 76a66253 j_mayer
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
824 76a66253 j_mayer
{
825 76a66253 j_mayer
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
826 76a66253 j_mayer
}
827 76a66253 j_mayer
828 636aaad7 j_mayer
/*****************************************************************************/
829 76a66253 j_mayer
/* Embedded PowerPC timers */
830 636aaad7 j_mayer
831 636aaad7 j_mayer
/* PIT, FIT & WDT */
832 636aaad7 j_mayer
typedef struct ppcemb_timer_t ppcemb_timer_t;
833 636aaad7 j_mayer
struct ppcemb_timer_t {
834 636aaad7 j_mayer
    uint64_t pit_reload;  /* PIT auto-reload value        */
835 636aaad7 j_mayer
    uint64_t fit_next;    /* Tick for next FIT interrupt  */
836 636aaad7 j_mayer
    struct QEMUTimer *fit_timer;
837 636aaad7 j_mayer
    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
838 636aaad7 j_mayer
    struct QEMUTimer *wdt_timer;
839 636aaad7 j_mayer
};
840 3b46e624 ths
841 636aaad7 j_mayer
/* Fixed interval timer */
842 636aaad7 j_mayer
static void cpu_4xx_fit_cb (void *opaque)
843 636aaad7 j_mayer
{
844 636aaad7 j_mayer
    CPUState *env;
845 636aaad7 j_mayer
    ppc_tb_t *tb_env;
846 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
847 636aaad7 j_mayer
    uint64_t now, next;
848 636aaad7 j_mayer
849 636aaad7 j_mayer
    env = opaque;
850 636aaad7 j_mayer
    tb_env = env->tb_env;
851 636aaad7 j_mayer
    ppcemb_timer = tb_env->opaque;
852 636aaad7 j_mayer
    now = qemu_get_clock(vm_clock);
853 636aaad7 j_mayer
    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
854 636aaad7 j_mayer
    case 0:
855 636aaad7 j_mayer
        next = 1 << 9;
856 636aaad7 j_mayer
        break;
857 636aaad7 j_mayer
    case 1:
858 636aaad7 j_mayer
        next = 1 << 13;
859 636aaad7 j_mayer
        break;
860 636aaad7 j_mayer
    case 2:
861 636aaad7 j_mayer
        next = 1 << 17;
862 636aaad7 j_mayer
        break;
863 636aaad7 j_mayer
    case 3:
864 636aaad7 j_mayer
        next = 1 << 21;
865 636aaad7 j_mayer
        break;
866 636aaad7 j_mayer
    default:
867 636aaad7 j_mayer
        /* Cannot occur, but makes gcc happy */
868 636aaad7 j_mayer
        return;
869 636aaad7 j_mayer
    }
870 636aaad7 j_mayer
    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
871 636aaad7 j_mayer
    if (next == now)
872 636aaad7 j_mayer
        next++;
873 636aaad7 j_mayer
    qemu_mod_timer(ppcemb_timer->fit_timer, next);
874 636aaad7 j_mayer
    env->spr[SPR_40x_TSR] |= 1 << 26;
875 636aaad7 j_mayer
    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
876 636aaad7 j_mayer
        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
877 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
878 4b6d0a4c j_mayer
    if (loglevel != 0) {
879 e96efcfc j_mayer
        fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
880 e96efcfc j_mayer
                (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
881 636aaad7 j_mayer
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
882 636aaad7 j_mayer
    }
883 4b6d0a4c j_mayer
#endif
884 636aaad7 j_mayer
}
885 636aaad7 j_mayer
886 636aaad7 j_mayer
/* Programmable interval timer */
887 4b6d0a4c j_mayer
static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
888 76a66253 j_mayer
{
889 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
890 636aaad7 j_mayer
    uint64_t now, next;
891 636aaad7 j_mayer
892 636aaad7 j_mayer
    ppcemb_timer = tb_env->opaque;
893 4b6d0a4c j_mayer
    if (ppcemb_timer->pit_reload <= 1 ||
894 4b6d0a4c j_mayer
        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
895 4b6d0a4c j_mayer
        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
896 4b6d0a4c j_mayer
        /* Stop PIT */
897 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
898 4b6d0a4c j_mayer
        if (loglevel != 0) {
899 4b6d0a4c j_mayer
            fprintf(logfile, "%s: stop PIT\n", __func__);
900 4b6d0a4c j_mayer
        }
901 4b6d0a4c j_mayer
#endif
902 4b6d0a4c j_mayer
        qemu_del_timer(tb_env->decr_timer);
903 4b6d0a4c j_mayer
    } else {
904 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
905 4b6d0a4c j_mayer
        if (loglevel != 0) {
906 4b6d0a4c j_mayer
            fprintf(logfile, "%s: start PIT 0x" REGX "\n",
907 4b6d0a4c j_mayer
                    __func__, ppcemb_timer->pit_reload);
908 4b6d0a4c j_mayer
        }
909 4b6d0a4c j_mayer
#endif
910 4b6d0a4c j_mayer
        now = qemu_get_clock(vm_clock);
911 636aaad7 j_mayer
        next = now + muldiv64(ppcemb_timer->pit_reload,
912 dbdd2506 j_mayer
                              ticks_per_sec, tb_env->decr_freq);
913 4b6d0a4c j_mayer
        if (is_excp)
914 4b6d0a4c j_mayer
            next += tb_env->decr_next - now;
915 636aaad7 j_mayer
        if (next == now)
916 636aaad7 j_mayer
            next++;
917 636aaad7 j_mayer
        qemu_mod_timer(tb_env->decr_timer, next);
918 636aaad7 j_mayer
        tb_env->decr_next = next;
919 636aaad7 j_mayer
    }
920 4b6d0a4c j_mayer
}
921 4b6d0a4c j_mayer
922 4b6d0a4c j_mayer
static void cpu_4xx_pit_cb (void *opaque)
923 4b6d0a4c j_mayer
{
924 4b6d0a4c j_mayer
    CPUState *env;
925 4b6d0a4c j_mayer
    ppc_tb_t *tb_env;
926 4b6d0a4c j_mayer
    ppcemb_timer_t *ppcemb_timer;
927 4b6d0a4c j_mayer
928 4b6d0a4c j_mayer
    env = opaque;
929 4b6d0a4c j_mayer
    tb_env = env->tb_env;
930 4b6d0a4c j_mayer
    ppcemb_timer = tb_env->opaque;
931 636aaad7 j_mayer
    env->spr[SPR_40x_TSR] |= 1 << 27;
932 636aaad7 j_mayer
    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
933 636aaad7 j_mayer
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
934 4b6d0a4c j_mayer
    start_stop_pit(env, tb_env, 1);
935 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
936 4b6d0a4c j_mayer
    if (loglevel != 0) {
937 e96efcfc j_mayer
        fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
938 e96efcfc j_mayer
                "%016" PRIx64 "\n", __func__,
939 e96efcfc j_mayer
                (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
940 e96efcfc j_mayer
                (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
941 636aaad7 j_mayer
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
942 636aaad7 j_mayer
                ppcemb_timer->pit_reload);
943 636aaad7 j_mayer
    }
944 4b6d0a4c j_mayer
#endif
945 636aaad7 j_mayer
}
946 636aaad7 j_mayer
947 636aaad7 j_mayer
/* Watchdog timer */
948 636aaad7 j_mayer
static void cpu_4xx_wdt_cb (void *opaque)
949 636aaad7 j_mayer
{
950 636aaad7 j_mayer
    CPUState *env;
951 636aaad7 j_mayer
    ppc_tb_t *tb_env;
952 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
953 636aaad7 j_mayer
    uint64_t now, next;
954 636aaad7 j_mayer
955 636aaad7 j_mayer
    env = opaque;
956 636aaad7 j_mayer
    tb_env = env->tb_env;
957 636aaad7 j_mayer
    ppcemb_timer = tb_env->opaque;
958 636aaad7 j_mayer
    now = qemu_get_clock(vm_clock);
959 636aaad7 j_mayer
    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
960 636aaad7 j_mayer
    case 0:
961 636aaad7 j_mayer
        next = 1 << 17;
962 636aaad7 j_mayer
        break;
963 636aaad7 j_mayer
    case 1:
964 636aaad7 j_mayer
        next = 1 << 21;
965 636aaad7 j_mayer
        break;
966 636aaad7 j_mayer
    case 2:
967 636aaad7 j_mayer
        next = 1 << 25;
968 636aaad7 j_mayer
        break;
969 636aaad7 j_mayer
    case 3:
970 636aaad7 j_mayer
        next = 1 << 29;
971 636aaad7 j_mayer
        break;
972 636aaad7 j_mayer
    default:
973 636aaad7 j_mayer
        /* Cannot occur, but makes gcc happy */
974 636aaad7 j_mayer
        return;
975 636aaad7 j_mayer
    }
976 dbdd2506 j_mayer
    next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
977 636aaad7 j_mayer
    if (next == now)
978 636aaad7 j_mayer
        next++;
979 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
980 4b6d0a4c j_mayer
    if (loglevel != 0) {
981 e96efcfc j_mayer
        fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
982 636aaad7 j_mayer
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
983 636aaad7 j_mayer
    }
984 4b6d0a4c j_mayer
#endif
985 636aaad7 j_mayer
    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
986 636aaad7 j_mayer
    case 0x0:
987 636aaad7 j_mayer
    case 0x1:
988 636aaad7 j_mayer
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
989 636aaad7 j_mayer
        ppcemb_timer->wdt_next = next;
990 636aaad7 j_mayer
        env->spr[SPR_40x_TSR] |= 1 << 31;
991 636aaad7 j_mayer
        break;
992 636aaad7 j_mayer
    case 0x2:
993 636aaad7 j_mayer
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
994 636aaad7 j_mayer
        ppcemb_timer->wdt_next = next;
995 636aaad7 j_mayer
        env->spr[SPR_40x_TSR] |= 1 << 30;
996 636aaad7 j_mayer
        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
997 636aaad7 j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
998 636aaad7 j_mayer
        break;
999 636aaad7 j_mayer
    case 0x3:
1000 636aaad7 j_mayer
        env->spr[SPR_40x_TSR] &= ~0x30000000;
1001 636aaad7 j_mayer
        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
1002 636aaad7 j_mayer
        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
1003 636aaad7 j_mayer
        case 0x0:
1004 636aaad7 j_mayer
            /* No reset */
1005 636aaad7 j_mayer
            break;
1006 636aaad7 j_mayer
        case 0x1: /* Core reset */
1007 8ecc7913 j_mayer
            ppc40x_core_reset(env);
1008 8ecc7913 j_mayer
            break;
1009 636aaad7 j_mayer
        case 0x2: /* Chip reset */
1010 8ecc7913 j_mayer
            ppc40x_chip_reset(env);
1011 8ecc7913 j_mayer
            break;
1012 636aaad7 j_mayer
        case 0x3: /* System reset */
1013 8ecc7913 j_mayer
            ppc40x_system_reset(env);
1014 8ecc7913 j_mayer
            break;
1015 636aaad7 j_mayer
        }
1016 636aaad7 j_mayer
    }
1017 76a66253 j_mayer
}
1018 76a66253 j_mayer
1019 76a66253 j_mayer
void store_40x_pit (CPUState *env, target_ulong val)
1020 76a66253 j_mayer
{
1021 636aaad7 j_mayer
    ppc_tb_t *tb_env;
1022 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
1023 636aaad7 j_mayer
1024 636aaad7 j_mayer
    tb_env = env->tb_env;
1025 636aaad7 j_mayer
    ppcemb_timer = tb_env->opaque;
1026 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1027 4b6d0a4c j_mayer
    if (loglevel != 0) {
1028 636aaad7 j_mayer
        fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
1029 a496775f j_mayer
    }
1030 4b6d0a4c j_mayer
#endif
1031 636aaad7 j_mayer
    ppcemb_timer->pit_reload = val;
1032 4b6d0a4c j_mayer
    start_stop_pit(env, tb_env, 0);
1033 76a66253 j_mayer
}
1034 76a66253 j_mayer
1035 636aaad7 j_mayer
target_ulong load_40x_pit (CPUState *env)
1036 76a66253 j_mayer
{
1037 636aaad7 j_mayer
    return cpu_ppc_load_decr(env);
1038 76a66253 j_mayer
}
1039 76a66253 j_mayer
1040 76a66253 j_mayer
void store_booke_tsr (CPUState *env, target_ulong val)
1041 76a66253 j_mayer
{
1042 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1043 4b6d0a4c j_mayer
    if (loglevel != 0) {
1044 4b6d0a4c j_mayer
        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1045 4b6d0a4c j_mayer
    }
1046 4b6d0a4c j_mayer
#endif
1047 4b6d0a4c j_mayer
    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
1048 4b6d0a4c j_mayer
    if (val & 0x80000000)
1049 4b6d0a4c j_mayer
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
1050 636aaad7 j_mayer
}
1051 636aaad7 j_mayer
1052 636aaad7 j_mayer
void store_booke_tcr (CPUState *env, target_ulong val)
1053 636aaad7 j_mayer
{
1054 4b6d0a4c j_mayer
    ppc_tb_t *tb_env;
1055 4b6d0a4c j_mayer
1056 4b6d0a4c j_mayer
    tb_env = env->tb_env;
1057 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1058 4b6d0a4c j_mayer
    if (loglevel != 0) {
1059 4b6d0a4c j_mayer
        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1060 4b6d0a4c j_mayer
    }
1061 4b6d0a4c j_mayer
#endif
1062 4b6d0a4c j_mayer
    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1063 4b6d0a4c j_mayer
    start_stop_pit(env, tb_env, 1);
1064 8ecc7913 j_mayer
    cpu_4xx_wdt_cb(env);
1065 636aaad7 j_mayer
}
1066 636aaad7 j_mayer
1067 4b6d0a4c j_mayer
static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1068 4b6d0a4c j_mayer
{
1069 4b6d0a4c j_mayer
    CPUState *env = opaque;
1070 4b6d0a4c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
1071 4b6d0a4c j_mayer
1072 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1073 4b6d0a4c j_mayer
    if (loglevel != 0) {
1074 4b6d0a4c j_mayer
        fprintf(logfile, "%s set new frequency to %u\n", __func__, freq);
1075 4b6d0a4c j_mayer
    }
1076 4b6d0a4c j_mayer
#endif
1077 4b6d0a4c j_mayer
    tb_env->tb_freq = freq;
1078 dbdd2506 j_mayer
    tb_env->decr_freq = freq;
1079 4b6d0a4c j_mayer
    /* XXX: we should also update all timers */
1080 4b6d0a4c j_mayer
}
1081 4b6d0a4c j_mayer
1082 8ecc7913 j_mayer
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
1083 636aaad7 j_mayer
{
1084 636aaad7 j_mayer
    ppc_tb_t *tb_env;
1085 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
1086 636aaad7 j_mayer
1087 8ecc7913 j_mayer
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
1088 4b6d0a4c j_mayer
    if (tb_env == NULL) {
1089 8ecc7913 j_mayer
        return NULL;
1090 4b6d0a4c j_mayer
    }
1091 8ecc7913 j_mayer
    env->tb_env = tb_env;
1092 636aaad7 j_mayer
    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
1093 8ecc7913 j_mayer
    tb_env->tb_freq = freq;
1094 dbdd2506 j_mayer
    tb_env->decr_freq = freq;
1095 636aaad7 j_mayer
    tb_env->opaque = ppcemb_timer;
1096 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1097 4b6d0a4c j_mayer
    if (loglevel != 0) {
1098 4b6d0a4c j_mayer
        fprintf(logfile, "%s %p %p %p\n", __func__, tb_env, ppcemb_timer,
1099 4b6d0a4c j_mayer
                &ppc_emb_set_tb_clk);
1100 8ecc7913 j_mayer
    }
1101 4b6d0a4c j_mayer
#endif
1102 636aaad7 j_mayer
    if (ppcemb_timer != NULL) {
1103 636aaad7 j_mayer
        /* We use decr timer for PIT */
1104 636aaad7 j_mayer
        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
1105 636aaad7 j_mayer
        ppcemb_timer->fit_timer =
1106 636aaad7 j_mayer
            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
1107 636aaad7 j_mayer
        ppcemb_timer->wdt_timer =
1108 636aaad7 j_mayer
            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
1109 636aaad7 j_mayer
    }
1110 8ecc7913 j_mayer
1111 4b6d0a4c j_mayer
    return &ppc_emb_set_tb_clk;
1112 76a66253 j_mayer
}
1113 76a66253 j_mayer
1114 2e719ba3 j_mayer
/*****************************************************************************/
1115 2e719ba3 j_mayer
/* Embedded PowerPC Device Control Registers */
1116 2e719ba3 j_mayer
typedef struct ppc_dcrn_t ppc_dcrn_t;
1117 2e719ba3 j_mayer
struct ppc_dcrn_t {
1118 2e719ba3 j_mayer
    dcr_read_cb dcr_read;
1119 2e719ba3 j_mayer
    dcr_write_cb dcr_write;
1120 2e719ba3 j_mayer
    void *opaque;
1121 2e719ba3 j_mayer
};
1122 2e719ba3 j_mayer
1123 a750fc0b j_mayer
/* XXX: on 460, DCR addresses are 32 bits wide,
1124 a750fc0b j_mayer
 *      using DCRIPR to get the 22 upper bits of the DCR address
1125 a750fc0b j_mayer
 */
1126 2e719ba3 j_mayer
#define DCRN_NB 1024
1127 2e719ba3 j_mayer
struct ppc_dcr_t {
1128 2e719ba3 j_mayer
    ppc_dcrn_t dcrn[DCRN_NB];
1129 2e719ba3 j_mayer
    int (*read_error)(int dcrn);
1130 2e719ba3 j_mayer
    int (*write_error)(int dcrn);
1131 2e719ba3 j_mayer
};
1132 2e719ba3 j_mayer
1133 2e719ba3 j_mayer
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1134 2e719ba3 j_mayer
{
1135 2e719ba3 j_mayer
    ppc_dcrn_t *dcr;
1136 2e719ba3 j_mayer
1137 2e719ba3 j_mayer
    if (dcrn < 0 || dcrn >= DCRN_NB)
1138 2e719ba3 j_mayer
        goto error;
1139 2e719ba3 j_mayer
    dcr = &dcr_env->dcrn[dcrn];
1140 2e719ba3 j_mayer
    if (dcr->dcr_read == NULL)
1141 2e719ba3 j_mayer
        goto error;
1142 2e719ba3 j_mayer
    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1143 2e719ba3 j_mayer
1144 2e719ba3 j_mayer
    return 0;
1145 2e719ba3 j_mayer
1146 2e719ba3 j_mayer
 error:
1147 2e719ba3 j_mayer
    if (dcr_env->read_error != NULL)
1148 2e719ba3 j_mayer
        return (*dcr_env->read_error)(dcrn);
1149 2e719ba3 j_mayer
1150 2e719ba3 j_mayer
    return -1;
1151 2e719ba3 j_mayer
}
1152 2e719ba3 j_mayer
1153 2e719ba3 j_mayer
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1154 2e719ba3 j_mayer
{
1155 2e719ba3 j_mayer
    ppc_dcrn_t *dcr;
1156 2e719ba3 j_mayer
1157 2e719ba3 j_mayer
    if (dcrn < 0 || dcrn >= DCRN_NB)
1158 2e719ba3 j_mayer
        goto error;
1159 2e719ba3 j_mayer
    dcr = &dcr_env->dcrn[dcrn];
1160 2e719ba3 j_mayer
    if (dcr->dcr_write == NULL)
1161 2e719ba3 j_mayer
        goto error;
1162 2e719ba3 j_mayer
    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1163 2e719ba3 j_mayer
1164 2e719ba3 j_mayer
    return 0;
1165 2e719ba3 j_mayer
1166 2e719ba3 j_mayer
 error:
1167 2e719ba3 j_mayer
    if (dcr_env->write_error != NULL)
1168 2e719ba3 j_mayer
        return (*dcr_env->write_error)(dcrn);
1169 2e719ba3 j_mayer
1170 2e719ba3 j_mayer
    return -1;
1171 2e719ba3 j_mayer
}
1172 2e719ba3 j_mayer
1173 2e719ba3 j_mayer
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1174 2e719ba3 j_mayer
                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1175 2e719ba3 j_mayer
{
1176 2e719ba3 j_mayer
    ppc_dcr_t *dcr_env;
1177 2e719ba3 j_mayer
    ppc_dcrn_t *dcr;
1178 2e719ba3 j_mayer
1179 2e719ba3 j_mayer
    dcr_env = env->dcr_env;
1180 2e719ba3 j_mayer
    if (dcr_env == NULL)
1181 2e719ba3 j_mayer
        return -1;
1182 2e719ba3 j_mayer
    if (dcrn < 0 || dcrn >= DCRN_NB)
1183 2e719ba3 j_mayer
        return -1;
1184 2e719ba3 j_mayer
    dcr = &dcr_env->dcrn[dcrn];
1185 2e719ba3 j_mayer
    if (dcr->opaque != NULL ||
1186 2e719ba3 j_mayer
        dcr->dcr_read != NULL ||
1187 2e719ba3 j_mayer
        dcr->dcr_write != NULL)
1188 2e719ba3 j_mayer
        return -1;
1189 2e719ba3 j_mayer
    dcr->opaque = opaque;
1190 2e719ba3 j_mayer
    dcr->dcr_read = dcr_read;
1191 2e719ba3 j_mayer
    dcr->dcr_write = dcr_write;
1192 2e719ba3 j_mayer
1193 2e719ba3 j_mayer
    return 0;
1194 2e719ba3 j_mayer
}
1195 2e719ba3 j_mayer
1196 2e719ba3 j_mayer
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1197 2e719ba3 j_mayer
                  int (*write_error)(int dcrn))
1198 2e719ba3 j_mayer
{
1199 2e719ba3 j_mayer
    ppc_dcr_t *dcr_env;
1200 2e719ba3 j_mayer
1201 2e719ba3 j_mayer
    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1202 2e719ba3 j_mayer
    if (dcr_env == NULL)
1203 2e719ba3 j_mayer
        return -1;
1204 2e719ba3 j_mayer
    dcr_env->read_error = read_error;
1205 2e719ba3 j_mayer
    dcr_env->write_error = write_error;
1206 2e719ba3 j_mayer
    env->dcr_env = dcr_env;
1207 2e719ba3 j_mayer
1208 2e719ba3 j_mayer
    return 0;
1209 2e719ba3 j_mayer
}
1210 2e719ba3 j_mayer
1211 9fddaa0c bellard
#if 0
1212 9fddaa0c bellard
/*****************************************************************************/
1213 9fddaa0c bellard
/* Handle system reset (for now, just stop emulation) */
1214 9fddaa0c bellard
void cpu_ppc_reset (CPUState *env)
1215 9fddaa0c bellard
{
1216 9fddaa0c bellard
    printf("Reset asked... Stop emulation\n");
1217 9fddaa0c bellard
    abort();
1218 9fddaa0c bellard
}
1219 9fddaa0c bellard
#endif
1220 9fddaa0c bellard
1221 64201201 bellard
/*****************************************************************************/
1222 64201201 bellard
/* Debug port */
1223 fd0bbb12 bellard
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1224 64201201 bellard
{
1225 64201201 bellard
    addr &= 0xF;
1226 64201201 bellard
    switch (addr) {
1227 64201201 bellard
    case 0:
1228 64201201 bellard
        printf("%c", val);
1229 64201201 bellard
        break;
1230 64201201 bellard
    case 1:
1231 64201201 bellard
        printf("\n");
1232 64201201 bellard
        fflush(stdout);
1233 64201201 bellard
        break;
1234 64201201 bellard
    case 2:
1235 64201201 bellard
        printf("Set loglevel to %04x\n", val);
1236 fd0bbb12 bellard
        cpu_set_log(val | 0x100);
1237 64201201 bellard
        break;
1238 64201201 bellard
    }
1239 64201201 bellard
}
1240 64201201 bellard
1241 64201201 bellard
/*****************************************************************************/
1242 64201201 bellard
/* NVRAM helpers */
1243 64201201 bellard
void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
1244 64201201 bellard
{
1245 819385c5 bellard
    m48t59_write(nvram, addr, value);
1246 64201201 bellard
}
1247 64201201 bellard
1248 64201201 bellard
uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
1249 64201201 bellard
{
1250 819385c5 bellard
    return m48t59_read(nvram, addr);
1251 64201201 bellard
}
1252 64201201 bellard
1253 64201201 bellard
void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
1254 64201201 bellard
{
1255 819385c5 bellard
    m48t59_write(nvram, addr, value >> 8);
1256 819385c5 bellard
    m48t59_write(nvram, addr + 1, value & 0xFF);
1257 64201201 bellard
}
1258 64201201 bellard
1259 64201201 bellard
uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
1260 64201201 bellard
{
1261 64201201 bellard
    uint16_t tmp;
1262 64201201 bellard
1263 819385c5 bellard
    tmp = m48t59_read(nvram, addr) << 8;
1264 819385c5 bellard
    tmp |= m48t59_read(nvram, addr + 1);
1265 64201201 bellard
    return tmp;
1266 64201201 bellard
}
1267 64201201 bellard
1268 64201201 bellard
void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
1269 64201201 bellard
{
1270 819385c5 bellard
    m48t59_write(nvram, addr, value >> 24);
1271 819385c5 bellard
    m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
1272 819385c5 bellard
    m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
1273 819385c5 bellard
    m48t59_write(nvram, addr + 3, value & 0xFF);
1274 64201201 bellard
}
1275 64201201 bellard
1276 64201201 bellard
uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
1277 64201201 bellard
{
1278 64201201 bellard
    uint32_t tmp;
1279 64201201 bellard
1280 819385c5 bellard
    tmp = m48t59_read(nvram, addr) << 24;
1281 819385c5 bellard
    tmp |= m48t59_read(nvram, addr + 1) << 16;
1282 819385c5 bellard
    tmp |= m48t59_read(nvram, addr + 2) << 8;
1283 819385c5 bellard
    tmp |= m48t59_read(nvram, addr + 3);
1284 76a66253 j_mayer
1285 64201201 bellard
    return tmp;
1286 64201201 bellard
}
1287 64201201 bellard
1288 64201201 bellard
void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
1289 64201201 bellard
                       const unsigned char *str, uint32_t max)
1290 64201201 bellard
{
1291 64201201 bellard
    int i;
1292 64201201 bellard
1293 64201201 bellard
    for (i = 0; i < max && str[i] != '\0'; i++) {
1294 819385c5 bellard
        m48t59_write(nvram, addr + i, str[i]);
1295 64201201 bellard
    }
1296 819385c5 bellard
    m48t59_write(nvram, addr + max - 1, '\0');
1297 64201201 bellard
}
1298 64201201 bellard
1299 64201201 bellard
int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
1300 64201201 bellard
{
1301 64201201 bellard
    int i;
1302 64201201 bellard
1303 64201201 bellard
    memset(dst, 0, max);
1304 64201201 bellard
    for (i = 0; i < max; i++) {
1305 64201201 bellard
        dst[i] = NVRAM_get_byte(nvram, addr + i);
1306 64201201 bellard
        if (dst[i] == '\0')
1307 64201201 bellard
            break;
1308 64201201 bellard
    }
1309 64201201 bellard
1310 64201201 bellard
    return i;
1311 64201201 bellard
}
1312 64201201 bellard
1313 64201201 bellard
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1314 64201201 bellard
{
1315 64201201 bellard
    uint16_t tmp;
1316 64201201 bellard
    uint16_t pd, pd1, pd2;
1317 64201201 bellard
1318 64201201 bellard
    tmp = prev >> 8;
1319 64201201 bellard
    pd = prev ^ value;
1320 64201201 bellard
    pd1 = pd & 0x000F;
1321 64201201 bellard
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1322 64201201 bellard
    tmp ^= (pd1 << 3) | (pd1 << 8);
1323 64201201 bellard
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1324 64201201 bellard
1325 64201201 bellard
    return tmp;
1326 64201201 bellard
}
1327 64201201 bellard
1328 64201201 bellard
uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
1329 64201201 bellard
{
1330 64201201 bellard
    uint32_t i;
1331 64201201 bellard
    uint16_t crc = 0xFFFF;
1332 64201201 bellard
    int odd;
1333 64201201 bellard
1334 64201201 bellard
    odd = count & 1;
1335 64201201 bellard
    count &= ~1;
1336 64201201 bellard
    for (i = 0; i != count; i++) {
1337 76a66253 j_mayer
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1338 64201201 bellard
    }
1339 64201201 bellard
    if (odd) {
1340 76a66253 j_mayer
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1341 64201201 bellard
    }
1342 64201201 bellard
1343 64201201 bellard
    return crc;
1344 64201201 bellard
}
1345 64201201 bellard
1346 fd0bbb12 bellard
#define CMDLINE_ADDR 0x017ff000
1347 fd0bbb12 bellard
1348 64201201 bellard
int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
1349 64201201 bellard
                          const unsigned char *arch,
1350 64201201 bellard
                          uint32_t RAM_size, int boot_device,
1351 64201201 bellard
                          uint32_t kernel_image, uint32_t kernel_size,
1352 fd0bbb12 bellard
                          const char *cmdline,
1353 64201201 bellard
                          uint32_t initrd_image, uint32_t initrd_size,
1354 fd0bbb12 bellard
                          uint32_t NVRAM_image,
1355 fd0bbb12 bellard
                          int width, int height, int depth)
1356 64201201 bellard
{
1357 64201201 bellard
    uint16_t crc;
1358 64201201 bellard
1359 64201201 bellard
    /* Set parameters for Open Hack'Ware BIOS */
1360 64201201 bellard
    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1361 64201201 bellard
    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
1362 64201201 bellard
    NVRAM_set_word(nvram,   0x14, NVRAM_size);
1363 64201201 bellard
    NVRAM_set_string(nvram, 0x20, arch, 16);
1364 64201201 bellard
    NVRAM_set_lword(nvram,  0x30, RAM_size);
1365 64201201 bellard
    NVRAM_set_byte(nvram,   0x34, boot_device);
1366 64201201 bellard
    NVRAM_set_lword(nvram,  0x38, kernel_image);
1367 64201201 bellard
    NVRAM_set_lword(nvram,  0x3C, kernel_size);
1368 fd0bbb12 bellard
    if (cmdline) {
1369 fd0bbb12 bellard
        /* XXX: put the cmdline in NVRAM too ? */
1370 fd0bbb12 bellard
        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
1371 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
1372 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
1373 fd0bbb12 bellard
    } else {
1374 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x40, 0);
1375 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x44, 0);
1376 fd0bbb12 bellard
    }
1377 64201201 bellard
    NVRAM_set_lword(nvram,  0x48, initrd_image);
1378 64201201 bellard
    NVRAM_set_lword(nvram,  0x4C, initrd_size);
1379 64201201 bellard
    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
1380 fd0bbb12 bellard
1381 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x54, width);
1382 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x56, height);
1383 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x58, depth);
1384 fd0bbb12 bellard
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1385 fd0bbb12 bellard
    NVRAM_set_word(nvram,  0xFC, crc);
1386 64201201 bellard
1387 64201201 bellard
    return 0;
1388 a541f297 bellard
}