Statistics
| Branch: | Revision:

root / hw / ppc.c @ 3b3fb322

History | View | Annotate | Download (40.1 kB)

1
/*
2
 * QEMU generic PowerPC hardware System Emulator
3
 *
4
 * Copyright (c) 2003-2007 Jocelyn Mayer
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "hw.h"
25
#include "ppc.h"
26
#include "qemu-timer.h"
27
#include "sysemu.h"
28
#include "nvram.h"
29
#include "qemu-log.h"
30

    
31
//#define PPC_DEBUG_IRQ
32
//#define PPC_DEBUG_TB
33

    
34
static void cpu_ppc_tb_stop (CPUState *env);
35
static void cpu_ppc_tb_start (CPUState *env);
36

    
37
static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
38
{
39
    if (level) {
40
        env->pending_interrupts |= 1 << n_IRQ;
41
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
42
    } else {
43
        env->pending_interrupts &= ~(1 << n_IRQ);
44
        if (env->pending_interrupts == 0)
45
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
46
    }
47
#if defined(PPC_DEBUG_IRQ)
48
    if (loglevel & CPU_LOG_INT) {
49
        fprintf(logfile, "%s: %p n_IRQ %d level %d => pending %08" PRIx32
50
                "req %08x\n", __func__, env, n_IRQ, level,
51
                env->pending_interrupts, env->interrupt_request);
52
    }
53
#endif
54
}
55

    
56
/* PowerPC 6xx / 7xx internal IRQ controller */
57
static void ppc6xx_set_irq (void *opaque, int pin, int level)
58
{
59
    CPUState *env = opaque;
60
    int cur_level;
61

    
62
#if defined(PPC_DEBUG_IRQ)
63
    if (loglevel & CPU_LOG_INT) {
64
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
65
                env, pin, level);
66
    }
67
#endif
68
    cur_level = (env->irq_input_state >> pin) & 1;
69
    /* Don't generate spurious events */
70
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
71
        switch (pin) {
72
        case PPC6xx_INPUT_TBEN:
73
            /* Level sensitive - active high */
74
#if defined(PPC_DEBUG_IRQ)
75
            if (loglevel & CPU_LOG_INT) {
76
                fprintf(logfile, "%s: %s the time base\n",
77
                        __func__, level ? "start" : "stop");
78
            }
79
#endif
80
            if (level) {
81
                cpu_ppc_tb_start(env);
82
            } else {
83
                cpu_ppc_tb_stop(env);
84
            }
85
        case PPC6xx_INPUT_INT:
86
            /* Level sensitive - active high */
87
#if defined(PPC_DEBUG_IRQ)
88
            if (loglevel & CPU_LOG_INT) {
89
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
90
                        __func__, level);
91
            }
92
#endif
93
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
94
            break;
95
        case PPC6xx_INPUT_SMI:
96
            /* Level sensitive - active high */
97
#if defined(PPC_DEBUG_IRQ)
98
            if (loglevel & CPU_LOG_INT) {
99
                fprintf(logfile, "%s: set the SMI IRQ state to %d\n",
100
                        __func__, level);
101
            }
102
#endif
103
            ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
104
            break;
105
        case PPC6xx_INPUT_MCP:
106
            /* Negative edge sensitive */
107
            /* XXX: TODO: actual reaction may depends on HID0 status
108
             *            603/604/740/750: check HID0[EMCP]
109
             */
110
            if (cur_level == 1 && level == 0) {
111
#if defined(PPC_DEBUG_IRQ)
112
                if (loglevel & CPU_LOG_INT) {
113
                    fprintf(logfile, "%s: raise machine check state\n",
114
                            __func__);
115
                }
116
#endif
117
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
118
            }
119
            break;
120
        case PPC6xx_INPUT_CKSTP_IN:
121
            /* Level sensitive - active low */
122
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
123
            /* XXX: Note that the only way to restart the CPU is to reset it */
124
            if (level) {
125
#if defined(PPC_DEBUG_IRQ)
126
                if (loglevel & CPU_LOG_INT) {
127
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
128
                }
129
#endif
130
                env->halted = 1;
131
            }
132
            break;
133
        case PPC6xx_INPUT_HRESET:
134
            /* Level sensitive - active low */
135
            if (level) {
136
#if defined(PPC_DEBUG_IRQ)
137
                if (loglevel & CPU_LOG_INT) {
138
                    fprintf(logfile, "%s: reset the CPU\n", __func__);
139
                }
140
#endif
141
                env->interrupt_request |= CPU_INTERRUPT_EXITTB;
142
                /* XXX: TOFIX */
143
#if 0
144
                cpu_ppc_reset(env);
145
#else
146
                qemu_system_reset_request();
147
#endif
148
            }
149
            break;
150
        case PPC6xx_INPUT_SRESET:
151
#if defined(PPC_DEBUG_IRQ)
152
            if (loglevel & CPU_LOG_INT) {
153
                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
154
                        __func__, level);
155
            }
156
#endif
157
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
158
            break;
159
        default:
160
            /* Unknown pin - do nothing */
161
#if defined(PPC_DEBUG_IRQ)
162
            if (loglevel & CPU_LOG_INT) {
163
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
164
            }
165
#endif
166
            return;
167
        }
168
        if (level)
169
            env->irq_input_state |= 1 << pin;
170
        else
171
            env->irq_input_state &= ~(1 << pin);
172
    }
173
}
174

    
175
void ppc6xx_irq_init (CPUState *env)
176
{
177
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
178
                                                  PPC6xx_INPUT_NB);
179
}
180

    
181
#if defined(TARGET_PPC64)
182
/* PowerPC 970 internal IRQ controller */
183
static void ppc970_set_irq (void *opaque, int pin, int level)
184
{
185
    CPUState *env = opaque;
186
    int cur_level;
187

    
188
#if defined(PPC_DEBUG_IRQ)
189
    if (loglevel & CPU_LOG_INT) {
190
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
191
                env, pin, level);
192
    }
193
#endif
194
    cur_level = (env->irq_input_state >> pin) & 1;
195
    /* Don't generate spurious events */
196
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
197
        switch (pin) {
198
        case PPC970_INPUT_INT:
199
            /* Level sensitive - active high */
200
#if defined(PPC_DEBUG_IRQ)
201
            if (loglevel & CPU_LOG_INT) {
202
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
203
                        __func__, level);
204
            }
205
#endif
206
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
207
            break;
208
        case PPC970_INPUT_THINT:
209
            /* Level sensitive - active high */
210
#if defined(PPC_DEBUG_IRQ)
211
            if (loglevel & CPU_LOG_INT) {
212
                fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
213
                        level);
214
            }
215
#endif
216
            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
217
            break;
218
        case PPC970_INPUT_MCP:
219
            /* Negative edge sensitive */
220
            /* XXX: TODO: actual reaction may depends on HID0 status
221
             *            603/604/740/750: check HID0[EMCP]
222
             */
223
            if (cur_level == 1 && level == 0) {
224
#if defined(PPC_DEBUG_IRQ)
225
                if (loglevel & CPU_LOG_INT) {
226
                    fprintf(logfile, "%s: raise machine check state\n",
227
                            __func__);
228
                }
229
#endif
230
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
231
            }
232
            break;
233
        case PPC970_INPUT_CKSTP:
234
            /* Level sensitive - active low */
235
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
236
            if (level) {
237
#if defined(PPC_DEBUG_IRQ)
238
                if (loglevel & CPU_LOG_INT) {
239
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
240
                }
241
#endif
242
                env->halted = 1;
243
            } else {
244
#if defined(PPC_DEBUG_IRQ)
245
                if (loglevel & CPU_LOG_INT) {
246
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
247
                }
248
#endif
249
                env->halted = 0;
250
            }
251
            break;
252
        case PPC970_INPUT_HRESET:
253
            /* Level sensitive - active low */
254
            if (level) {
255
#if 0 // XXX: TOFIX
256
#if defined(PPC_DEBUG_IRQ)
257
                if (loglevel & CPU_LOG_INT) {
258
                    fprintf(logfile, "%s: reset the CPU\n", __func__);
259
                }
260
#endif
261
                cpu_reset(env);
262
#endif
263
            }
264
            break;
265
        case PPC970_INPUT_SRESET:
266
#if defined(PPC_DEBUG_IRQ)
267
            if (loglevel & CPU_LOG_INT) {
268
                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
269
                        __func__, level);
270
            }
271
#endif
272
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
273
            break;
274
        case PPC970_INPUT_TBEN:
275
#if defined(PPC_DEBUG_IRQ)
276
            if (loglevel & CPU_LOG_INT) {
277
                fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
278
                        level);
279
            }
280
#endif
281
            /* XXX: TODO */
282
            break;
283
        default:
284
            /* Unknown pin - do nothing */
285
#if defined(PPC_DEBUG_IRQ)
286
            if (loglevel & CPU_LOG_INT) {
287
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
288
            }
289
#endif
290
            return;
291
        }
292
        if (level)
293
            env->irq_input_state |= 1 << pin;
294
        else
295
            env->irq_input_state &= ~(1 << pin);
296
    }
297
}
298

    
299
void ppc970_irq_init (CPUState *env)
300
{
301
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
302
                                                  PPC970_INPUT_NB);
303
}
304
#endif /* defined(TARGET_PPC64) */
305

    
306
/* PowerPC 40x internal IRQ controller */
307
static void ppc40x_set_irq (void *opaque, int pin, int level)
308
{
309
    CPUState *env = opaque;
310
    int cur_level;
311

    
312
#if defined(PPC_DEBUG_IRQ)
313
    if (loglevel & CPU_LOG_INT) {
314
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
315
                env, pin, level);
316
    }
317
#endif
318
    cur_level = (env->irq_input_state >> pin) & 1;
319
    /* Don't generate spurious events */
320
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
321
        switch (pin) {
322
        case PPC40x_INPUT_RESET_SYS:
323
            if (level) {
324
#if defined(PPC_DEBUG_IRQ)
325
                if (loglevel & CPU_LOG_INT) {
326
                    fprintf(logfile, "%s: reset the PowerPC system\n",
327
                            __func__);
328
                }
329
#endif
330
                ppc40x_system_reset(env);
331
            }
332
            break;
333
        case PPC40x_INPUT_RESET_CHIP:
334
            if (level) {
335
#if defined(PPC_DEBUG_IRQ)
336
                if (loglevel & CPU_LOG_INT) {
337
                    fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
338
                }
339
#endif
340
                ppc40x_chip_reset(env);
341
            }
342
            break;
343
        case PPC40x_INPUT_RESET_CORE:
344
            /* XXX: TODO: update DBSR[MRR] */
345
            if (level) {
346
#if defined(PPC_DEBUG_IRQ)
347
                if (loglevel & CPU_LOG_INT) {
348
                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
349
                }
350
#endif
351
                ppc40x_core_reset(env);
352
            }
353
            break;
354
        case PPC40x_INPUT_CINT:
355
            /* Level sensitive - active high */
356
#if defined(PPC_DEBUG_IRQ)
357
            if (loglevel & CPU_LOG_INT) {
358
                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
359
                        __func__, level);
360
            }
361
#endif
362
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
363
            break;
364
        case PPC40x_INPUT_INT:
365
            /* Level sensitive - active high */
366
#if defined(PPC_DEBUG_IRQ)
367
            if (loglevel & CPU_LOG_INT) {
368
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
369
                        __func__, level);
370
            }
371
#endif
372
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
373
            break;
374
        case PPC40x_INPUT_HALT:
375
            /* Level sensitive - active low */
376
            if (level) {
377
#if defined(PPC_DEBUG_IRQ)
378
                if (loglevel & CPU_LOG_INT) {
379
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
380
                }
381
#endif
382
                env->halted = 1;
383
            } else {
384
#if defined(PPC_DEBUG_IRQ)
385
                if (loglevel & CPU_LOG_INT) {
386
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
387
                }
388
#endif
389
                env->halted = 0;
390
            }
391
            break;
392
        case PPC40x_INPUT_DEBUG:
393
            /* Level sensitive - active high */
394
#if defined(PPC_DEBUG_IRQ)
395
            if (loglevel & CPU_LOG_INT) {
396
                fprintf(logfile, "%s: set the debug pin state to %d\n",
397
                        __func__, level);
398
            }
399
#endif
400
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
401
            break;
402
        default:
403
            /* Unknown pin - do nothing */
404
#if defined(PPC_DEBUG_IRQ)
405
            if (loglevel & CPU_LOG_INT) {
406
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
407
            }
408
#endif
409
            return;
410
        }
411
        if (level)
412
            env->irq_input_state |= 1 << pin;
413
        else
414
            env->irq_input_state &= ~(1 << pin);
415
    }
416
}
417

    
418
void ppc40x_irq_init (CPUState *env)
419
{
420
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
421
                                                  env, PPC40x_INPUT_NB);
422
}
423

    
424
/*****************************************************************************/
425
/* PowerPC time base and decrementer emulation */
426
struct ppc_tb_t {
427
    /* Time base management */
428
    int64_t  tb_offset;    /* Compensation                    */
429
    int64_t  atb_offset;   /* Compensation                    */
430
    uint32_t tb_freq;      /* TB frequency                    */
431
    /* Decrementer management */
432
    uint64_t decr_next;    /* Tick for next decr interrupt    */
433
    uint32_t decr_freq;    /* decrementer frequency           */
434
    struct QEMUTimer *decr_timer;
435
    /* Hypervisor decrementer management */
436
    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
437
    struct QEMUTimer *hdecr_timer;
438
    uint64_t purr_load;
439
    uint64_t purr_start;
440
    void *opaque;
441
};
442

    
443
static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
444
                                              int64_t tb_offset)
445
{
446
    /* TB time in tb periods */
447
    return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
448
}
449

    
450
uint32_t cpu_ppc_load_tbl (CPUState *env)
451
{
452
    ppc_tb_t *tb_env = env->tb_env;
453
    uint64_t tb;
454

    
455
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
456
#if defined(PPC_DEBUG_TB)
457
    if (loglevel != 0) {
458
        fprintf(logfile, "%s: tb %016" PRIx64 "\n", __func__, tb);
459
    }
460
#endif
461

    
462
    return tb & 0xFFFFFFFF;
463
}
464

    
465
static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
466
{
467
    ppc_tb_t *tb_env = env->tb_env;
468
    uint64_t tb;
469

    
470
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
471
#if defined(PPC_DEBUG_TB)
472
    if (loglevel != 0) {
473
        fprintf(logfile, "%s: tb %016" PRIx64 "\n", __func__, tb);
474
    }
475
#endif
476

    
477
    return tb >> 32;
478
}
479

    
480
uint32_t cpu_ppc_load_tbu (CPUState *env)
481
{
482
    return _cpu_ppc_load_tbu(env);
483
}
484

    
485
static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
486
                                            int64_t *tb_offsetp,
487
                                            uint64_t value)
488
{
489
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
490
#ifdef PPC_DEBUG_TB
491
    if (loglevel != 0) {
492
        fprintf(logfile, "%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
493
                __func__, value, *tb_offsetp);
494
    }
495
#endif
496
}
497

    
498
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
499
{
500
    ppc_tb_t *tb_env = env->tb_env;
501
    uint64_t tb;
502

    
503
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
504
    tb &= 0xFFFFFFFF00000000ULL;
505
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
506
                     &tb_env->tb_offset, tb | (uint64_t)value);
507
}
508

    
509
static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
510
{
511
    ppc_tb_t *tb_env = env->tb_env;
512
    uint64_t tb;
513

    
514
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
515
    tb &= 0x00000000FFFFFFFFULL;
516
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
517
                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
518
}
519

    
520
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
521
{
522
    _cpu_ppc_store_tbu(env, value);
523
}
524

    
525
uint32_t cpu_ppc_load_atbl (CPUState *env)
526
{
527
    ppc_tb_t *tb_env = env->tb_env;
528
    uint64_t tb;
529

    
530
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
531
#if defined(PPC_DEBUG_TB)
532
    if (loglevel != 0) {
533
        fprintf(logfile, "%s: tb %016" PRIx64 "\n", __func__, tb);
534
    }
535
#endif
536

    
537
    return tb & 0xFFFFFFFF;
538
}
539

    
540
uint32_t cpu_ppc_load_atbu (CPUState *env)
541
{
542
    ppc_tb_t *tb_env = env->tb_env;
543
    uint64_t tb;
544

    
545
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
546
#if defined(PPC_DEBUG_TB)
547
    if (loglevel != 0) {
548
        fprintf(logfile, "%s: tb %016" PRIx64 "\n", __func__, tb);
549
    }
550
#endif
551

    
552
    return tb >> 32;
553
}
554

    
555
void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
556
{
557
    ppc_tb_t *tb_env = env->tb_env;
558
    uint64_t tb;
559

    
560
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
561
    tb &= 0xFFFFFFFF00000000ULL;
562
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
563
                     &tb_env->atb_offset, tb | (uint64_t)value);
564
}
565

    
566
void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
567
{
568
    ppc_tb_t *tb_env = env->tb_env;
569
    uint64_t tb;
570

    
571
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
572
    tb &= 0x00000000FFFFFFFFULL;
573
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
574
                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
575
}
576

    
577
static void cpu_ppc_tb_stop (CPUState *env)
578
{
579
    ppc_tb_t *tb_env = env->tb_env;
580
    uint64_t tb, atb, vmclk;
581

    
582
    /* If the time base is already frozen, do nothing */
583
    if (tb_env->tb_freq != 0) {
584
        vmclk = qemu_get_clock(vm_clock);
585
        /* Get the time base */
586
        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
587
        /* Get the alternate time base */
588
        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
589
        /* Store the time base value (ie compute the current offset) */
590
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
591
        /* Store the alternate time base value (compute the current offset) */
592
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
593
        /* Set the time base frequency to zero */
594
        tb_env->tb_freq = 0;
595
        /* Now, the time bases are frozen to tb_offset / atb_offset value */
596
    }
597
}
598

    
599
static void cpu_ppc_tb_start (CPUState *env)
600
{
601
    ppc_tb_t *tb_env = env->tb_env;
602
    uint64_t tb, atb, vmclk;
603

    
604
    /* If the time base is not frozen, do nothing */
605
    if (tb_env->tb_freq == 0) {
606
        vmclk = qemu_get_clock(vm_clock);
607
        /* Get the time base from tb_offset */
608
        tb = tb_env->tb_offset;
609
        /* Get the alternate time base from atb_offset */
610
        atb = tb_env->atb_offset;
611
        /* Restore the tb frequency from the decrementer frequency */
612
        tb_env->tb_freq = tb_env->decr_freq;
613
        /* Store the time base value */
614
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
615
        /* Store the alternate time base value */
616
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
617
    }
618
}
619

    
620
static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
621
                                                  uint64_t *next)
622
{
623
    ppc_tb_t *tb_env = env->tb_env;
624
    uint32_t decr;
625
    int64_t diff;
626

    
627
    diff = tb_env->decr_next - qemu_get_clock(vm_clock);
628
    if (diff >= 0)
629
        decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
630
    else
631
        decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
632
#if defined(PPC_DEBUG_TB)
633
    if (loglevel != 0) {
634
        fprintf(logfile, "%s: %08" PRIx32 "\n", __func__, decr);
635
    }
636
#endif
637

    
638
    return decr;
639
}
640

    
641
uint32_t cpu_ppc_load_decr (CPUState *env)
642
{
643
    ppc_tb_t *tb_env = env->tb_env;
644

    
645
    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
646
}
647

    
648
uint32_t cpu_ppc_load_hdecr (CPUState *env)
649
{
650
    ppc_tb_t *tb_env = env->tb_env;
651

    
652
    return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
653
}
654

    
655
uint64_t cpu_ppc_load_purr (CPUState *env)
656
{
657
    ppc_tb_t *tb_env = env->tb_env;
658
    uint64_t diff;
659

    
660
    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
661

    
662
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
663
}
664

    
665
/* When decrementer expires,
666
 * all we need to do is generate or queue a CPU exception
667
 */
668
static always_inline void cpu_ppc_decr_excp (CPUState *env)
669
{
670
    /* Raise it */
671
#ifdef PPC_DEBUG_TB
672
    if (loglevel != 0) {
673
        fprintf(logfile, "raise decrementer exception\n");
674
    }
675
#endif
676
    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
677
}
678

    
679
static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
680
{
681
    /* Raise it */
682
#ifdef PPC_DEBUG_TB
683
    if (loglevel != 0) {
684
        fprintf(logfile, "raise decrementer exception\n");
685
    }
686
#endif
687
    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
688
}
689

    
690
static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
691
                                  struct QEMUTimer *timer,
692
                                  void (*raise_excp)(CPUState *),
693
                                  uint32_t decr, uint32_t value,
694
                                  int is_excp)
695
{
696
    ppc_tb_t *tb_env = env->tb_env;
697
    uint64_t now, next;
698

    
699
#ifdef PPC_DEBUG_TB
700
    if (loglevel != 0) {
701
        fprintf(logfile, "%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
702
                decr, value);
703
    }
704
#endif
705
    now = qemu_get_clock(vm_clock);
706
    next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
707
    if (is_excp)
708
        next += *nextp - now;
709
    if (next == now)
710
        next++;
711
    *nextp = next;
712
    /* Adjust timer */
713
    qemu_mod_timer(timer, next);
714
    /* If we set a negative value and the decrementer was positive,
715
     * raise an exception.
716
     */
717
    if ((value & 0x80000000) && !(decr & 0x80000000))
718
        (*raise_excp)(env);
719
}
720

    
721
static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
722
                                               uint32_t value, int is_excp)
723
{
724
    ppc_tb_t *tb_env = env->tb_env;
725

    
726
    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
727
                         &cpu_ppc_decr_excp, decr, value, is_excp);
728
}
729

    
730
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
731
{
732
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
733
}
734

    
735
static void cpu_ppc_decr_cb (void *opaque)
736
{
737
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
738
}
739

    
740
static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
741
                                                uint32_t value, int is_excp)
742
{
743
    ppc_tb_t *tb_env = env->tb_env;
744

    
745
    if (tb_env->hdecr_timer != NULL) {
746
        __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
747
                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
748
    }
749
}
750

    
751
void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
752
{
753
    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
754
}
755

    
756
static void cpu_ppc_hdecr_cb (void *opaque)
757
{
758
    _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
759
}
760

    
761
void cpu_ppc_store_purr (CPUState *env, uint64_t value)
762
{
763
    ppc_tb_t *tb_env = env->tb_env;
764

    
765
    tb_env->purr_load = value;
766
    tb_env->purr_start = qemu_get_clock(vm_clock);
767
}
768

    
769
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
770
{
771
    CPUState *env = opaque;
772
    ppc_tb_t *tb_env = env->tb_env;
773

    
774
    tb_env->tb_freq = freq;
775
    tb_env->decr_freq = freq;
776
    /* There is a bug in Linux 2.4 kernels:
777
     * if a decrementer exception is pending when it enables msr_ee at startup,
778
     * it's not ready to handle it...
779
     */
780
    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
781
    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
782
    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
783
}
784

    
785
/* Set up (once) timebase frequency (in Hz) */
786
clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
787
{
788
    ppc_tb_t *tb_env;
789

    
790
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
791
    if (tb_env == NULL)
792
        return NULL;
793
    env->tb_env = tb_env;
794
    /* Create new timer */
795
    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
796
    if (0) {
797
        /* XXX: find a suitable condition to enable the hypervisor decrementer
798
         */
799
        tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
800
    } else {
801
        tb_env->hdecr_timer = NULL;
802
    }
803
    cpu_ppc_set_tb_clk(env, freq);
804

    
805
    return &cpu_ppc_set_tb_clk;
806
}
807

    
808
/* Specific helpers for POWER & PowerPC 601 RTC */
809
clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
810
{
811
    return cpu_ppc_tb_init(env, 7812500);
812
}
813

    
814
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
815
{
816
    _cpu_ppc_store_tbu(env, value);
817
}
818

    
819
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
820
{
821
    return _cpu_ppc_load_tbu(env);
822
}
823

    
824
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
825
{
826
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
827
}
828

    
829
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
830
{
831
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
832
}
833

    
834
/*****************************************************************************/
835
/* Embedded PowerPC timers */
836

    
837
/* PIT, FIT & WDT */
838
typedef struct ppcemb_timer_t ppcemb_timer_t;
839
struct ppcemb_timer_t {
840
    uint64_t pit_reload;  /* PIT auto-reload value        */
841
    uint64_t fit_next;    /* Tick for next FIT interrupt  */
842
    struct QEMUTimer *fit_timer;
843
    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
844
    struct QEMUTimer *wdt_timer;
845
};
846

    
847
/* Fixed interval timer */
848
static void cpu_4xx_fit_cb (void *opaque)
849
{
850
    CPUState *env;
851
    ppc_tb_t *tb_env;
852
    ppcemb_timer_t *ppcemb_timer;
853
    uint64_t now, next;
854

    
855
    env = opaque;
856
    tb_env = env->tb_env;
857
    ppcemb_timer = tb_env->opaque;
858
    now = qemu_get_clock(vm_clock);
859
    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
860
    case 0:
861
        next = 1 << 9;
862
        break;
863
    case 1:
864
        next = 1 << 13;
865
        break;
866
    case 2:
867
        next = 1 << 17;
868
        break;
869
    case 3:
870
        next = 1 << 21;
871
        break;
872
    default:
873
        /* Cannot occur, but makes gcc happy */
874
        return;
875
    }
876
    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
877
    if (next == now)
878
        next++;
879
    qemu_mod_timer(ppcemb_timer->fit_timer, next);
880
    env->spr[SPR_40x_TSR] |= 1 << 26;
881
    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
882
        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
883
#ifdef PPC_DEBUG_TB
884
    if (loglevel != 0) {
885
        fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
886
                (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
887
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
888
    }
889
#endif
890
}
891

    
892
/* Programmable interval timer */
893
static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
894
{
895
    ppcemb_timer_t *ppcemb_timer;
896
    uint64_t now, next;
897

    
898
    ppcemb_timer = tb_env->opaque;
899
    if (ppcemb_timer->pit_reload <= 1 ||
900
        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
901
        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
902
        /* Stop PIT */
903
#ifdef PPC_DEBUG_TB
904
        if (loglevel != 0) {
905
            fprintf(logfile, "%s: stop PIT\n", __func__);
906
        }
907
#endif
908
        qemu_del_timer(tb_env->decr_timer);
909
    } else {
910
#ifdef PPC_DEBUG_TB
911
        if (loglevel != 0) {
912
            fprintf(logfile, "%s: start PIT %016" PRIx64 "\n",
913
                    __func__, ppcemb_timer->pit_reload);
914
        }
915
#endif
916
        now = qemu_get_clock(vm_clock);
917
        next = now + muldiv64(ppcemb_timer->pit_reload,
918
                              ticks_per_sec, tb_env->decr_freq);
919
        if (is_excp)
920
            next += tb_env->decr_next - now;
921
        if (next == now)
922
            next++;
923
        qemu_mod_timer(tb_env->decr_timer, next);
924
        tb_env->decr_next = next;
925
    }
926
}
927

    
928
static void cpu_4xx_pit_cb (void *opaque)
929
{
930
    CPUState *env;
931
    ppc_tb_t *tb_env;
932
    ppcemb_timer_t *ppcemb_timer;
933

    
934
    env = opaque;
935
    tb_env = env->tb_env;
936
    ppcemb_timer = tb_env->opaque;
937
    env->spr[SPR_40x_TSR] |= 1 << 27;
938
    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
939
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
940
    start_stop_pit(env, tb_env, 1);
941
#ifdef PPC_DEBUG_TB
942
    if (loglevel != 0) {
943
        fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
944
                "%016" PRIx64 "\n", __func__,
945
                (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
946
                (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
947
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
948
                ppcemb_timer->pit_reload);
949
    }
950
#endif
951
}
952

    
953
/* Watchdog timer */
954
static void cpu_4xx_wdt_cb (void *opaque)
955
{
956
    CPUState *env;
957
    ppc_tb_t *tb_env;
958
    ppcemb_timer_t *ppcemb_timer;
959
    uint64_t now, next;
960

    
961
    env = opaque;
962
    tb_env = env->tb_env;
963
    ppcemb_timer = tb_env->opaque;
964
    now = qemu_get_clock(vm_clock);
965
    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
966
    case 0:
967
        next = 1 << 17;
968
        break;
969
    case 1:
970
        next = 1 << 21;
971
        break;
972
    case 2:
973
        next = 1 << 25;
974
        break;
975
    case 3:
976
        next = 1 << 29;
977
        break;
978
    default:
979
        /* Cannot occur, but makes gcc happy */
980
        return;
981
    }
982
    next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
983
    if (next == now)
984
        next++;
985
#ifdef PPC_DEBUG_TB
986
    if (loglevel != 0) {
987
        fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
988
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
989
    }
990
#endif
991
    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
992
    case 0x0:
993
    case 0x1:
994
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
995
        ppcemb_timer->wdt_next = next;
996
        env->spr[SPR_40x_TSR] |= 1 << 31;
997
        break;
998
    case 0x2:
999
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
1000
        ppcemb_timer->wdt_next = next;
1001
        env->spr[SPR_40x_TSR] |= 1 << 30;
1002
        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
1003
            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
1004
        break;
1005
    case 0x3:
1006
        env->spr[SPR_40x_TSR] &= ~0x30000000;
1007
        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
1008
        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
1009
        case 0x0:
1010
            /* No reset */
1011
            break;
1012
        case 0x1: /* Core reset */
1013
            ppc40x_core_reset(env);
1014
            break;
1015
        case 0x2: /* Chip reset */
1016
            ppc40x_chip_reset(env);
1017
            break;
1018
        case 0x3: /* System reset */
1019
            ppc40x_system_reset(env);
1020
            break;
1021
        }
1022
    }
1023
}
1024

    
1025
void store_40x_pit (CPUState *env, target_ulong val)
1026
{
1027
    ppc_tb_t *tb_env;
1028
    ppcemb_timer_t *ppcemb_timer;
1029

    
1030
    tb_env = env->tb_env;
1031
    ppcemb_timer = tb_env->opaque;
1032
#ifdef PPC_DEBUG_TB
1033
    if (loglevel != 0) {
1034
        fprintf(logfile, "%s val" ADDRX "\n", __func__, val);
1035
    }
1036
#endif
1037
    ppcemb_timer->pit_reload = val;
1038
    start_stop_pit(env, tb_env, 0);
1039
}
1040

    
1041
target_ulong load_40x_pit (CPUState *env)
1042
{
1043
    return cpu_ppc_load_decr(env);
1044
}
1045

    
1046
void store_booke_tsr (CPUState *env, target_ulong val)
1047
{
1048
#ifdef PPC_DEBUG_TB
1049
    if (loglevel != 0) {
1050
        fprintf(logfile, "%s: val " ADDRX "\n", __func__, val);
1051
    }
1052
#endif
1053
    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
1054
    if (val & 0x80000000)
1055
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
1056
}
1057

    
1058
void store_booke_tcr (CPUState *env, target_ulong val)
1059
{
1060
    ppc_tb_t *tb_env;
1061

    
1062
    tb_env = env->tb_env;
1063
#ifdef PPC_DEBUG_TB
1064
    if (loglevel != 0) {
1065
        fprintf(logfile, "%s: val " ADDRX "\n", __func__, val);
1066
    }
1067
#endif
1068
    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1069
    start_stop_pit(env, tb_env, 1);
1070
    cpu_4xx_wdt_cb(env);
1071
}
1072

    
1073
static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1074
{
1075
    CPUState *env = opaque;
1076
    ppc_tb_t *tb_env = env->tb_env;
1077

    
1078
#ifdef PPC_DEBUG_TB
1079
    if (loglevel != 0) {
1080
        fprintf(logfile, "%s set new frequency to %" PRIu32 "\n", __func__,
1081
                freq);
1082
    }
1083
#endif
1084
    tb_env->tb_freq = freq;
1085
    tb_env->decr_freq = freq;
1086
    /* XXX: we should also update all timers */
1087
}
1088

    
1089
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
1090
{
1091
    ppc_tb_t *tb_env;
1092
    ppcemb_timer_t *ppcemb_timer;
1093

    
1094
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
1095
    if (tb_env == NULL) {
1096
        return NULL;
1097
    }
1098
    env->tb_env = tb_env;
1099
    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
1100
    tb_env->tb_freq = freq;
1101
    tb_env->decr_freq = freq;
1102
    tb_env->opaque = ppcemb_timer;
1103
#ifdef PPC_DEBUG_TB
1104
    if (loglevel != 0) {
1105
        fprintf(logfile, "%s freq %" PRIu32 "\n", __func__, freq);
1106
    }
1107
#endif
1108
    if (ppcemb_timer != NULL) {
1109
        /* We use decr timer for PIT */
1110
        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
1111
        ppcemb_timer->fit_timer =
1112
            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
1113
        ppcemb_timer->wdt_timer =
1114
            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
1115
    }
1116

    
1117
    return &ppc_emb_set_tb_clk;
1118
}
1119

    
1120
/*****************************************************************************/
1121
/* Embedded PowerPC Device Control Registers */
1122
typedef struct ppc_dcrn_t ppc_dcrn_t;
1123
struct ppc_dcrn_t {
1124
    dcr_read_cb dcr_read;
1125
    dcr_write_cb dcr_write;
1126
    void *opaque;
1127
};
1128

    
1129
/* XXX: on 460, DCR addresses are 32 bits wide,
1130
 *      using DCRIPR to get the 22 upper bits of the DCR address
1131
 */
1132
#define DCRN_NB 1024
1133
struct ppc_dcr_t {
1134
    ppc_dcrn_t dcrn[DCRN_NB];
1135
    int (*read_error)(int dcrn);
1136
    int (*write_error)(int dcrn);
1137
};
1138

    
1139
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1140
{
1141
    ppc_dcrn_t *dcr;
1142

    
1143
    if (dcrn < 0 || dcrn >= DCRN_NB)
1144
        goto error;
1145
    dcr = &dcr_env->dcrn[dcrn];
1146
    if (dcr->dcr_read == NULL)
1147
        goto error;
1148
    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1149

    
1150
    return 0;
1151

    
1152
 error:
1153
    if (dcr_env->read_error != NULL)
1154
        return (*dcr_env->read_error)(dcrn);
1155

    
1156
    return -1;
1157
}
1158

    
1159
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1160
{
1161
    ppc_dcrn_t *dcr;
1162

    
1163
    if (dcrn < 0 || dcrn >= DCRN_NB)
1164
        goto error;
1165
    dcr = &dcr_env->dcrn[dcrn];
1166
    if (dcr->dcr_write == NULL)
1167
        goto error;
1168
    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1169

    
1170
    return 0;
1171

    
1172
 error:
1173
    if (dcr_env->write_error != NULL)
1174
        return (*dcr_env->write_error)(dcrn);
1175

    
1176
    return -1;
1177
}
1178

    
1179
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1180
                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1181
{
1182
    ppc_dcr_t *dcr_env;
1183
    ppc_dcrn_t *dcr;
1184

    
1185
    dcr_env = env->dcr_env;
1186
    if (dcr_env == NULL)
1187
        return -1;
1188
    if (dcrn < 0 || dcrn >= DCRN_NB)
1189
        return -1;
1190
    dcr = &dcr_env->dcrn[dcrn];
1191
    if (dcr->opaque != NULL ||
1192
        dcr->dcr_read != NULL ||
1193
        dcr->dcr_write != NULL)
1194
        return -1;
1195
    dcr->opaque = opaque;
1196
    dcr->dcr_read = dcr_read;
1197
    dcr->dcr_write = dcr_write;
1198

    
1199
    return 0;
1200
}
1201

    
1202
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1203
                  int (*write_error)(int dcrn))
1204
{
1205
    ppc_dcr_t *dcr_env;
1206

    
1207
    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1208
    if (dcr_env == NULL)
1209
        return -1;
1210
    dcr_env->read_error = read_error;
1211
    dcr_env->write_error = write_error;
1212
    env->dcr_env = dcr_env;
1213

    
1214
    return 0;
1215
}
1216

    
1217
#if 0
1218
/*****************************************************************************/
1219
/* Handle system reset (for now, just stop emulation) */
1220
void cpu_ppc_reset (CPUState *env)
1221
{
1222
    printf("Reset asked... Stop emulation\n");
1223
    abort();
1224
}
1225
#endif
1226

    
1227
/*****************************************************************************/
1228
/* Debug port */
1229
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1230
{
1231
    addr &= 0xF;
1232
    switch (addr) {
1233
    case 0:
1234
        printf("%c", val);
1235
        break;
1236
    case 1:
1237
        printf("\n");
1238
        fflush(stdout);
1239
        break;
1240
    case 2:
1241
        printf("Set loglevel to %04" PRIx32 "\n", val);
1242
        cpu_set_log(val | 0x100);
1243
        break;
1244
    }
1245
}
1246

    
1247
/*****************************************************************************/
1248
/* NVRAM helpers */
1249
static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
1250
{
1251
    return (*nvram->read_fn)(nvram->opaque, addr);;
1252
}
1253

    
1254
static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1255
{
1256
    (*nvram->write_fn)(nvram->opaque, addr, val);
1257
}
1258

    
1259
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1260
{
1261
    nvram_write(nvram, addr, value);
1262
}
1263

    
1264
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1265
{
1266
    return nvram_read(nvram, addr);
1267
}
1268

    
1269
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
1270
{
1271
    nvram_write(nvram, addr, value >> 8);
1272
    nvram_write(nvram, addr + 1, value & 0xFF);
1273
}
1274

    
1275
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1276
{
1277
    uint16_t tmp;
1278

    
1279
    tmp = nvram_read(nvram, addr) << 8;
1280
    tmp |= nvram_read(nvram, addr + 1);
1281

    
1282
    return tmp;
1283
}
1284

    
1285
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
1286
{
1287
    nvram_write(nvram, addr, value >> 24);
1288
    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
1289
    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
1290
    nvram_write(nvram, addr + 3, value & 0xFF);
1291
}
1292

    
1293
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1294
{
1295
    uint32_t tmp;
1296

    
1297
    tmp = nvram_read(nvram, addr) << 24;
1298
    tmp |= nvram_read(nvram, addr + 1) << 16;
1299
    tmp |= nvram_read(nvram, addr + 2) << 8;
1300
    tmp |= nvram_read(nvram, addr + 3);
1301

    
1302
    return tmp;
1303
}
1304

    
1305
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1306
                       const char *str, uint32_t max)
1307
{
1308
    int i;
1309

    
1310
    for (i = 0; i < max && str[i] != '\0'; i++) {
1311
        nvram_write(nvram, addr + i, str[i]);
1312
    }
1313
    nvram_write(nvram, addr + i, str[i]);
1314
    nvram_write(nvram, addr + max - 1, '\0');
1315
}
1316

    
1317
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1318
{
1319
    int i;
1320

    
1321
    memset(dst, 0, max);
1322
    for (i = 0; i < max; i++) {
1323
        dst[i] = NVRAM_get_byte(nvram, addr + i);
1324
        if (dst[i] == '\0')
1325
            break;
1326
    }
1327

    
1328
    return i;
1329
}
1330

    
1331
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1332
{
1333
    uint16_t tmp;
1334
    uint16_t pd, pd1, pd2;
1335

    
1336
    tmp = prev >> 8;
1337
    pd = prev ^ value;
1338
    pd1 = pd & 0x000F;
1339
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1340
    tmp ^= (pd1 << 3) | (pd1 << 8);
1341
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1342

    
1343
    return tmp;
1344
}
1345

    
1346
uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1347
{
1348
    uint32_t i;
1349
    uint16_t crc = 0xFFFF;
1350
    int odd;
1351

    
1352
    odd = count & 1;
1353
    count &= ~1;
1354
    for (i = 0; i != count; i++) {
1355
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1356
    }
1357
    if (odd) {
1358
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1359
    }
1360

    
1361
    return crc;
1362
}
1363

    
1364
#define CMDLINE_ADDR 0x017ff000
1365

    
1366
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
1367
                          const char *arch,
1368
                          uint32_t RAM_size, int boot_device,
1369
                          uint32_t kernel_image, uint32_t kernel_size,
1370
                          const char *cmdline,
1371
                          uint32_t initrd_image, uint32_t initrd_size,
1372
                          uint32_t NVRAM_image,
1373
                          int width, int height, int depth)
1374
{
1375
    uint16_t crc;
1376

    
1377
    /* Set parameters for Open Hack'Ware BIOS */
1378
    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1379
    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
1380
    NVRAM_set_word(nvram,   0x14, NVRAM_size);
1381
    NVRAM_set_string(nvram, 0x20, arch, 16);
1382
    NVRAM_set_lword(nvram,  0x30, RAM_size);
1383
    NVRAM_set_byte(nvram,   0x34, boot_device);
1384
    NVRAM_set_lword(nvram,  0x38, kernel_image);
1385
    NVRAM_set_lword(nvram,  0x3C, kernel_size);
1386
    if (cmdline) {
1387
        /* XXX: put the cmdline in NVRAM too ? */
1388
        strcpy((char *)(phys_ram_base + CMDLINE_ADDR), cmdline);
1389
        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
1390
        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
1391
    } else {
1392
        NVRAM_set_lword(nvram,  0x40, 0);
1393
        NVRAM_set_lword(nvram,  0x44, 0);
1394
    }
1395
    NVRAM_set_lword(nvram,  0x48, initrd_image);
1396
    NVRAM_set_lword(nvram,  0x4C, initrd_size);
1397
    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
1398

    
1399
    NVRAM_set_word(nvram,   0x54, width);
1400
    NVRAM_set_word(nvram,   0x56, height);
1401
    NVRAM_set_word(nvram,   0x58, depth);
1402
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1403
    NVRAM_set_word(nvram,   0xFC, crc);
1404

    
1405
    return 0;
1406
}