Statistics
| Branch: | Revision:

root / hw / ppc.c @ 7bfe5777

History | View | Annotate | Download (40 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 "vl.h"
25

    
26
//#define PPC_DEBUG_IRQ
27
//#define PPC_DEBUG_TB
28

    
29
extern FILE *logfile;
30
extern int loglevel;
31

    
32
static void cpu_ppc_tb_stop (CPUState *env);
33
static void cpu_ppc_tb_start (CPUState *env);
34

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

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

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

    
173
void ppc6xx_irq_init (CPUState *env)
174
{
175
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
176
}
177

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

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

    
296
void ppc970_irq_init (CPUState *env)
297
{
298
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
299
}
300
#endif /* defined(TARGET_PPC64) */
301

    
302
/* PowerPC 40x internal IRQ controller */
303
static void ppc40x_set_irq (void *opaque, int pin, int level)
304
{
305
    CPUState *env = opaque;
306
    int cur_level;
307

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

    
414
void ppc40x_irq_init (CPUState *env)
415
{
416
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
417
                                                  env, PPC40x_INPUT_NB);
418
}
419

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

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

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

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

    
460
    return tb & 0xFFFFFFFF;
461
}
462

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

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

    
475
    return tb >> 32;
476
}
477

    
478
uint32_t cpu_ppc_load_tbu (CPUState *env)
479
{
480
    return _cpu_ppc_load_tbu(env);
481
}
482

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

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

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

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

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

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

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

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

    
535
    return tb & 0xFFFFFFFF;
536
}
537

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

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

    
550
    return tb >> 32;
551
}
552

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

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

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

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

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

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

    
597
static void cpu_ppc_tb_start (CPUState *env)
598
{
599
    ppc_tb_t *tb_env = env->tb_env;
600
    uint64_t tb, atb, vmclk;
601
    
602
    /* If the time base is not frozen, do nothing */
603
    if (tb_env->tb_freq == 0) {
604
        vmclk = qemu_get_clock(vm_clock);
605
        /* Get the time base from tb_offset */
606
        tb = tb_env->tb_offset;
607
        /* Get the alternate time base from atb_offset */
608
        atb = tb_env->atb_offset;
609
        /* Restore the tb frequency from the decrementer frequency */
610
        tb_env->tb_freq = tb_env->decr_freq;
611
        /* Store the time base value */
612
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
613
        /* Store the alternate time base value */
614
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
615
    }
616
}
617

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

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

    
636
    return decr;
637
}
638

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

    
643
    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
644
}
645

    
646
#if defined(TARGET_PPC64H)
647
uint32_t cpu_ppc_load_hdecr (CPUState *env)
648
{
649
    ppc_tb_t *tb_env = env->tb_env;
650

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

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

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

    
661
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
662
}
663
#endif /* defined(TARGET_PPC64H) */
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: 0x%08x => 0x%08x\n", __func__, decr, value);
702
    }
703
#endif
704
    now = qemu_get_clock(vm_clock);
705
    next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
706
    if (is_excp)
707
        next += *nextp - now;
708
    if (next == now)
709
        next++;
710
    *nextp = next;
711
    /* Adjust timer */
712
    qemu_mod_timer(timer, next);
713
    /* If we set a negative value and the decrementer was positive,
714
     * raise an exception.
715
     */
716
    if ((value & 0x80000000) && !(decr & 0x80000000))
717
        (*raise_excp)(env);
718
}
719

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

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

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

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

    
739
#if defined(TARGET_PPC64H)
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
    __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
746
                         &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
747
}
748

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

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

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

    
763
    tb_env->purr_load = value;
764
    tb_env->purr_start = qemu_get_clock(vm_clock);
765
}
766
#endif /* defined(TARGET_PPC64H) */
767

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

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

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

    
791
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
792
    if (tb_env == NULL)
793
        return NULL;
794
    env->tb_env = tb_env;
795
    /* Create new timer */
796
    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
797
#if defined(TARGET_PPC64H)
798
    tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
799
#endif /* defined(TARGET_PPC64H) */
800
    cpu_ppc_set_tb_clk(env, freq);
801

    
802
    return &cpu_ppc_set_tb_clk;
803
}
804

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

    
811
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
812
{
813
    _cpu_ppc_store_tbu(env, value);
814
}
815

    
816
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
817
{
818
    return _cpu_ppc_load_tbu(env);
819
}
820

    
821
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
822
{
823
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
824
}
825

    
826
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
827
{
828
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
829
}
830

    
831
/*****************************************************************************/
832
/* Embedded PowerPC timers */
833

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

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

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

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

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

    
925
static void cpu_4xx_pit_cb (void *opaque)
926
{
927
    CPUState *env;
928
    ppc_tb_t *tb_env;
929
    ppcemb_timer_t *ppcemb_timer;
930

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

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

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

    
1022
void store_40x_pit (CPUState *env, target_ulong val)
1023
{
1024
    ppc_tb_t *tb_env;
1025
    ppcemb_timer_t *ppcemb_timer;
1026

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

    
1038
target_ulong load_40x_pit (CPUState *env)
1039
{
1040
    return cpu_ppc_load_decr(env);
1041
}
1042

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

    
1055
void store_booke_tcr (CPUState *env, target_ulong val)
1056
{
1057
    ppc_tb_t *tb_env;
1058

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

    
1070
static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1071
{
1072
    CPUState *env = opaque;
1073
    ppc_tb_t *tb_env = env->tb_env;
1074

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

    
1085
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
1086
{
1087
    ppc_tb_t *tb_env;
1088
    ppcemb_timer_t *ppcemb_timer;
1089

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

    
1114
    return &ppc_emb_set_tb_clk;
1115
}
1116

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

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

    
1136
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1137
{
1138
    ppc_dcrn_t *dcr;
1139

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

    
1147
    return 0;
1148

    
1149
 error:
1150
    if (dcr_env->read_error != NULL)
1151
        return (*dcr_env->read_error)(dcrn);
1152

    
1153
    return -1;
1154
}
1155

    
1156
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1157
{
1158
    ppc_dcrn_t *dcr;
1159

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

    
1167
    return 0;
1168

    
1169
 error:
1170
    if (dcr_env->write_error != NULL)
1171
        return (*dcr_env->write_error)(dcrn);
1172

    
1173
    return -1;
1174
}
1175

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

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

    
1196
    return 0;
1197
}
1198

    
1199
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1200
                  int (*write_error)(int dcrn))
1201
{
1202
    ppc_dcr_t *dcr_env;
1203

    
1204
    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1205
    if (dcr_env == NULL)
1206
        return -1;
1207
    dcr_env->read_error = read_error;
1208
    dcr_env->write_error = write_error;
1209
    env->dcr_env = dcr_env;
1210

    
1211
    return 0;
1212
}
1213

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

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

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

    
1251
static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1252
{
1253
    (*nvram->write_fn)(nvram->opaque, addr, val);
1254
}
1255

    
1256
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1257
{
1258
    nvram_write(nvram, addr, value);
1259
}
1260

    
1261
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1262
{
1263
    return nvram_read(nvram, addr);
1264
}
1265

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

    
1272
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1273
{
1274
    uint16_t tmp;
1275

    
1276
    tmp = nvram_read(nvram, addr) << 8;
1277
    tmp |= nvram_read(nvram, addr + 1);
1278

    
1279
    return tmp;
1280
}
1281

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

    
1290
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1291
{
1292
    uint32_t tmp;
1293

    
1294
    tmp = nvram_read(nvram, addr) << 24;
1295
    tmp |= nvram_read(nvram, addr + 1) << 16;
1296
    tmp |= nvram_read(nvram, addr + 2) << 8;
1297
    tmp |= nvram_read(nvram, addr + 3);
1298

    
1299
    return tmp;
1300
}
1301

    
1302
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1303
                       const unsigned char *str, uint32_t max)
1304
{
1305
    int i;
1306

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

    
1314
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1315
{
1316
    int i;
1317

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

    
1325
    return i;
1326
}
1327

    
1328
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1329
{
1330
    uint16_t tmp;
1331
    uint16_t pd, pd1, pd2;
1332

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

    
1340
    return tmp;
1341
}
1342

    
1343
uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1344
{
1345
    uint32_t i;
1346
    uint16_t crc = 0xFFFF;
1347
    int odd;
1348

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

    
1358
    return crc;
1359
}
1360

    
1361
#define CMDLINE_ADDR 0x017ff000
1362

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

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

    
1396
    NVRAM_set_word(nvram,   0x54, width);
1397
    NVRAM_set_word(nvram,   0x56, height);
1398
    NVRAM_set_word(nvram,   0x58, depth);
1399
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1400
    NVRAM_set_word(nvram,   0xFC, crc);
1401

    
1402
    return 0;
1403
}