Statistics
| Branch: | Revision:

root / hw / ppc.c @ 9fdc60bf

History | View | Annotate | Download (37.9 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
#ifdef PPC_DEBUG_IRQ
35
#  define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
36
#else
37
#  define LOG_IRQ(...) do { } while (0)
38
#endif
39

    
40

    
41
#ifdef PPC_DEBUG_TB
42
#  define LOG_TB(...) qemu_log(__VA_ARGS__)
43
#else
44
#  define LOG_TB(...) do { } while (0)
45
#endif
46

    
47
static void cpu_ppc_tb_stop (CPUState *env);
48
static void cpu_ppc_tb_start (CPUState *env);
49

    
50
static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
51
{
52
    if (level) {
53
        env->pending_interrupts |= 1 << n_IRQ;
54
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
55
    } else {
56
        env->pending_interrupts &= ~(1 << n_IRQ);
57
        if (env->pending_interrupts == 0)
58
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
59
    }
60
    LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
61
                "req %08x\n", __func__, env, n_IRQ, level,
62
                env->pending_interrupts, env->interrupt_request);
63
}
64

    
65
/* PowerPC 6xx / 7xx internal IRQ controller */
66
static void ppc6xx_set_irq (void *opaque, int pin, int level)
67
{
68
    CPUState *env = opaque;
69
    int cur_level;
70

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

    
148
void ppc6xx_irq_init (CPUState *env)
149
{
150
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
151
                                                  PPC6xx_INPUT_NB);
152
}
153

    
154
#if defined(TARGET_PPC64)
155
/* PowerPC 970 internal IRQ controller */
156
static void ppc970_set_irq (void *opaque, int pin, int level)
157
{
158
    CPUState *env = opaque;
159
    int cur_level;
160

    
161
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
162
                env, pin, level);
163
    cur_level = (env->irq_input_state >> pin) & 1;
164
    /* Don't generate spurious events */
165
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
166
        switch (pin) {
167
        case PPC970_INPUT_INT:
168
            /* Level sensitive - active high */
169
            LOG_IRQ("%s: set the external IRQ state to %d\n",
170
                        __func__, level);
171
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
172
            break;
173
        case PPC970_INPUT_THINT:
174
            /* Level sensitive - active high */
175
            LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
176
                        level);
177
            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
178
            break;
179
        case PPC970_INPUT_MCP:
180
            /* Negative edge sensitive */
181
            /* XXX: TODO: actual reaction may depends on HID0 status
182
             *            603/604/740/750: check HID0[EMCP]
183
             */
184
            if (cur_level == 1 && level == 0) {
185
                LOG_IRQ("%s: raise machine check state\n",
186
                            __func__);
187
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
188
            }
189
            break;
190
        case PPC970_INPUT_CKSTP:
191
            /* Level sensitive - active low */
192
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
193
            if (level) {
194
                LOG_IRQ("%s: stop the CPU\n", __func__);
195
                env->halted = 1;
196
            } else {
197
                LOG_IRQ("%s: restart the CPU\n", __func__);
198
                env->halted = 0;
199
            }
200
            break;
201
        case PPC970_INPUT_HRESET:
202
            /* Level sensitive - active low */
203
            if (level) {
204
#if 0 // XXX: TOFIX
205
                LOG_IRQ("%s: reset the CPU\n", __func__);
206
                cpu_reset(env);
207
#endif
208
            }
209
            break;
210
        case PPC970_INPUT_SRESET:
211
            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
212
                        __func__, level);
213
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
214
            break;
215
        case PPC970_INPUT_TBEN:
216
            LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
217
                        level);
218
            /* XXX: TODO */
219
            break;
220
        default:
221
            /* Unknown pin - do nothing */
222
            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
223
            return;
224
        }
225
        if (level)
226
            env->irq_input_state |= 1 << pin;
227
        else
228
            env->irq_input_state &= ~(1 << pin);
229
    }
230
}
231

    
232
void ppc970_irq_init (CPUState *env)
233
{
234
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
235
                                                  PPC970_INPUT_NB);
236
}
237
#endif /* defined(TARGET_PPC64) */
238

    
239
/* PowerPC 40x internal IRQ controller */
240
static void ppc40x_set_irq (void *opaque, int pin, int level)
241
{
242
    CPUState *env = opaque;
243
    int cur_level;
244

    
245
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
246
                env, pin, level);
247
    cur_level = (env->irq_input_state >> pin) & 1;
248
    /* Don't generate spurious events */
249
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
250
        switch (pin) {
251
        case PPC40x_INPUT_RESET_SYS:
252
            if (level) {
253
                LOG_IRQ("%s: reset the PowerPC system\n",
254
                            __func__);
255
                ppc40x_system_reset(env);
256
            }
257
            break;
258
        case PPC40x_INPUT_RESET_CHIP:
259
            if (level) {
260
                LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
261
                ppc40x_chip_reset(env);
262
            }
263
            break;
264
        case PPC40x_INPUT_RESET_CORE:
265
            /* XXX: TODO: update DBSR[MRR] */
266
            if (level) {
267
                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
268
                ppc40x_core_reset(env);
269
            }
270
            break;
271
        case PPC40x_INPUT_CINT:
272
            /* Level sensitive - active high */
273
            LOG_IRQ("%s: set the critical IRQ state to %d\n",
274
                        __func__, level);
275
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
276
            break;
277
        case PPC40x_INPUT_INT:
278
            /* Level sensitive - active high */
279
            LOG_IRQ("%s: set the external IRQ state to %d\n",
280
                        __func__, level);
281
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
282
            break;
283
        case PPC40x_INPUT_HALT:
284
            /* Level sensitive - active low */
285
            if (level) {
286
                LOG_IRQ("%s: stop the CPU\n", __func__);
287
                env->halted = 1;
288
            } else {
289
                LOG_IRQ("%s: restart the CPU\n", __func__);
290
                env->halted = 0;
291
            }
292
            break;
293
        case PPC40x_INPUT_DEBUG:
294
            /* Level sensitive - active high */
295
            LOG_IRQ("%s: set the debug pin state to %d\n",
296
                        __func__, level);
297
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
298
            break;
299
        default:
300
            /* Unknown pin - do nothing */
301
            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
302
            return;
303
        }
304
        if (level)
305
            env->irq_input_state |= 1 << pin;
306
        else
307
            env->irq_input_state &= ~(1 << pin);
308
    }
309
}
310

    
311
void ppc40x_irq_init (CPUState *env)
312
{
313
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
314
                                                  env, PPC40x_INPUT_NB);
315
}
316

    
317
/* PowerPC E500 internal IRQ controller */
318
static void ppce500_set_irq (void *opaque, int pin, int level)
319
{
320
    CPUState *env = opaque;
321
    int cur_level;
322

    
323
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
324
                env, pin, level);
325
    cur_level = (env->irq_input_state >> pin) & 1;
326
    /* Don't generate spurious events */
327
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
328
        switch (pin) {
329
        case PPCE500_INPUT_MCK:
330
            if (level) {
331
                LOG_IRQ("%s: reset the PowerPC system\n",
332
                            __func__);
333
                qemu_system_reset_request();
334
            }
335
            break;
336
        case PPCE500_INPUT_RESET_CORE:
337
            if (level) {
338
                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
339
                ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
340
            }
341
            break;
342
        case PPCE500_INPUT_CINT:
343
            /* Level sensitive - active high */
344
            LOG_IRQ("%s: set the critical IRQ state to %d\n",
345
                        __func__, level);
346
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
347
            break;
348
        case PPCE500_INPUT_INT:
349
            /* Level sensitive - active high */
350
            LOG_IRQ("%s: set the core IRQ state to %d\n",
351
                        __func__, level);
352
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
353
            break;
354
        case PPCE500_INPUT_DEBUG:
355
            /* Level sensitive - active high */
356
            LOG_IRQ("%s: set the debug pin state to %d\n",
357
                        __func__, level);
358
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
359
            break;
360
        default:
361
            /* Unknown pin - do nothing */
362
            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
363
            return;
364
        }
365
        if (level)
366
            env->irq_input_state |= 1 << pin;
367
        else
368
            env->irq_input_state &= ~(1 << pin);
369
    }
370
}
371

    
372
void ppce500_irq_init (CPUState *env)
373
{
374
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
375
                                        env, PPCE500_INPUT_NB);
376
}
377
/*****************************************************************************/
378
/* PowerPC time base and decrementer emulation */
379
struct ppc_tb_t {
380
    /* Time base management */
381
    int64_t  tb_offset;    /* Compensation                    */
382
    int64_t  atb_offset;   /* Compensation                    */
383
    uint32_t tb_freq;      /* TB frequency                    */
384
    /* Decrementer management */
385
    uint64_t decr_next;    /* Tick for next decr interrupt    */
386
    uint32_t decr_freq;    /* decrementer frequency           */
387
    struct QEMUTimer *decr_timer;
388
    /* Hypervisor decrementer management */
389
    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
390
    struct QEMUTimer *hdecr_timer;
391
    uint64_t purr_load;
392
    uint64_t purr_start;
393
    void *opaque;
394
};
395

    
396
static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
397
                                              int64_t tb_offset)
398
{
399
    /* TB time in tb periods */
400
    return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
401
}
402

    
403
uint32_t cpu_ppc_load_tbl (CPUState *env)
404
{
405
    ppc_tb_t *tb_env = env->tb_env;
406
    uint64_t tb;
407

    
408
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
409
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
410

    
411
    return tb & 0xFFFFFFFF;
412
}
413

    
414
static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
415
{
416
    ppc_tb_t *tb_env = env->tb_env;
417
    uint64_t tb;
418

    
419
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
420
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
421

    
422
    return tb >> 32;
423
}
424

    
425
uint32_t cpu_ppc_load_tbu (CPUState *env)
426
{
427
    return _cpu_ppc_load_tbu(env);
428
}
429

    
430
static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
431
                                            int64_t *tb_offsetp,
432
                                            uint64_t value)
433
{
434
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
435
    LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
436
                __func__, value, *tb_offsetp);
437
}
438

    
439
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
440
{
441
    ppc_tb_t *tb_env = env->tb_env;
442
    uint64_t tb;
443

    
444
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
445
    tb &= 0xFFFFFFFF00000000ULL;
446
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
447
                     &tb_env->tb_offset, tb | (uint64_t)value);
448
}
449

    
450
static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
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
    tb &= 0x00000000FFFFFFFFULL;
457
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
458
                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
459
}
460

    
461
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
462
{
463
    _cpu_ppc_store_tbu(env, value);
464
}
465

    
466
uint32_t cpu_ppc_load_atbl (CPUState *env)
467
{
468
    ppc_tb_t *tb_env = env->tb_env;
469
    uint64_t tb;
470

    
471
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
472
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
473

    
474
    return tb & 0xFFFFFFFF;
475
}
476

    
477
uint32_t cpu_ppc_load_atbu (CPUState *env)
478
{
479
    ppc_tb_t *tb_env = env->tb_env;
480
    uint64_t tb;
481

    
482
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
483
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
484

    
485
    return tb >> 32;
486
}
487

    
488
void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
489
{
490
    ppc_tb_t *tb_env = env->tb_env;
491
    uint64_t tb;
492

    
493
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
494
    tb &= 0xFFFFFFFF00000000ULL;
495
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
496
                     &tb_env->atb_offset, tb | (uint64_t)value);
497
}
498

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

    
504
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
505
    tb &= 0x00000000FFFFFFFFULL;
506
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
507
                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
508
}
509

    
510
static void cpu_ppc_tb_stop (CPUState *env)
511
{
512
    ppc_tb_t *tb_env = env->tb_env;
513
    uint64_t tb, atb, vmclk;
514

    
515
    /* If the time base is already frozen, do nothing */
516
    if (tb_env->tb_freq != 0) {
517
        vmclk = qemu_get_clock(vm_clock);
518
        /* Get the time base */
519
        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
520
        /* Get the alternate time base */
521
        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
522
        /* Store the time base value (ie compute the current offset) */
523
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
524
        /* Store the alternate time base value (compute the current offset) */
525
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
526
        /* Set the time base frequency to zero */
527
        tb_env->tb_freq = 0;
528
        /* Now, the time bases are frozen to tb_offset / atb_offset value */
529
    }
530
}
531

    
532
static void cpu_ppc_tb_start (CPUState *env)
533
{
534
    ppc_tb_t *tb_env = env->tb_env;
535
    uint64_t tb, atb, vmclk;
536

    
537
    /* If the time base is not frozen, do nothing */
538
    if (tb_env->tb_freq == 0) {
539
        vmclk = qemu_get_clock(vm_clock);
540
        /* Get the time base from tb_offset */
541
        tb = tb_env->tb_offset;
542
        /* Get the alternate time base from atb_offset */
543
        atb = tb_env->atb_offset;
544
        /* Restore the tb frequency from the decrementer frequency */
545
        tb_env->tb_freq = tb_env->decr_freq;
546
        /* Store the time base value */
547
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
548
        /* Store the alternate time base value */
549
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
550
    }
551
}
552

    
553
static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
554
                                                  uint64_t *next)
555
{
556
    ppc_tb_t *tb_env = env->tb_env;
557
    uint32_t decr;
558
    int64_t diff;
559

    
560
    diff = tb_env->decr_next - qemu_get_clock(vm_clock);
561
    if (diff >= 0)
562
        decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
563
    else
564
        decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
565
    LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
566

    
567
    return decr;
568
}
569

    
570
uint32_t cpu_ppc_load_decr (CPUState *env)
571
{
572
    ppc_tb_t *tb_env = env->tb_env;
573

    
574
    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
575
}
576

    
577
uint32_t cpu_ppc_load_hdecr (CPUState *env)
578
{
579
    ppc_tb_t *tb_env = env->tb_env;
580

    
581
    return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
582
}
583

    
584
uint64_t cpu_ppc_load_purr (CPUState *env)
585
{
586
    ppc_tb_t *tb_env = env->tb_env;
587
    uint64_t diff;
588

    
589
    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
590

    
591
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
592
}
593

    
594
/* When decrementer expires,
595
 * all we need to do is generate or queue a CPU exception
596
 */
597
static always_inline void cpu_ppc_decr_excp (CPUState *env)
598
{
599
    /* Raise it */
600
    LOG_TB("raise decrementer exception\n");
601
    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
602
}
603

    
604
static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
605
{
606
    /* Raise it */
607
    LOG_TB("raise decrementer exception\n");
608
    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
609
}
610

    
611
static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
612
                                  struct QEMUTimer *timer,
613
                                  void (*raise_excp)(CPUState *),
614
                                  uint32_t decr, uint32_t value,
615
                                  int is_excp)
616
{
617
    ppc_tb_t *tb_env = env->tb_env;
618
    uint64_t now, next;
619

    
620
    LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
621
                decr, value);
622
    now = qemu_get_clock(vm_clock);
623
    next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
624
    if (is_excp)
625
        next += *nextp - now;
626
    if (next == now)
627
        next++;
628
    *nextp = next;
629
    /* Adjust timer */
630
    qemu_mod_timer(timer, next);
631
    /* If we set a negative value and the decrementer was positive,
632
     * raise an exception.
633
     */
634
    if ((value & 0x80000000) && !(decr & 0x80000000))
635
        (*raise_excp)(env);
636
}
637

    
638
static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
639
                                               uint32_t value, int is_excp)
640
{
641
    ppc_tb_t *tb_env = env->tb_env;
642

    
643
    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
644
                         &cpu_ppc_decr_excp, decr, value, is_excp);
645
}
646

    
647
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
648
{
649
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
650
}
651

    
652
static void cpu_ppc_decr_cb (void *opaque)
653
{
654
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
655
}
656

    
657
static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
658
                                                uint32_t value, int is_excp)
659
{
660
    ppc_tb_t *tb_env = env->tb_env;
661

    
662
    if (tb_env->hdecr_timer != NULL) {
663
        __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
664
                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
665
    }
666
}
667

    
668
void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
669
{
670
    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
671
}
672

    
673
static void cpu_ppc_hdecr_cb (void *opaque)
674
{
675
    _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
676
}
677

    
678
void cpu_ppc_store_purr (CPUState *env, uint64_t value)
679
{
680
    ppc_tb_t *tb_env = env->tb_env;
681

    
682
    tb_env->purr_load = value;
683
    tb_env->purr_start = qemu_get_clock(vm_clock);
684
}
685

    
686
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
687
{
688
    CPUState *env = opaque;
689
    ppc_tb_t *tb_env = env->tb_env;
690

    
691
    tb_env->tb_freq = freq;
692
    tb_env->decr_freq = freq;
693
    /* There is a bug in Linux 2.4 kernels:
694
     * if a decrementer exception is pending when it enables msr_ee at startup,
695
     * it's not ready to handle it...
696
     */
697
    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
698
    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
699
    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
700
}
701

    
702
/* Set up (once) timebase frequency (in Hz) */
703
clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
704
{
705
    ppc_tb_t *tb_env;
706

    
707
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
708
    env->tb_env = tb_env;
709
    /* Create new timer */
710
    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
711
    if (0) {
712
        /* XXX: find a suitable condition to enable the hypervisor decrementer
713
         */
714
        tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
715
    } else {
716
        tb_env->hdecr_timer = NULL;
717
    }
718
    cpu_ppc_set_tb_clk(env, freq);
719

    
720
    return &cpu_ppc_set_tb_clk;
721
}
722

    
723
/* Specific helpers for POWER & PowerPC 601 RTC */
724
#if 0
725
static clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
726
{
727
    return cpu_ppc_tb_init(env, 7812500);
728
}
729
#endif
730

    
731
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
732
{
733
    _cpu_ppc_store_tbu(env, value);
734
}
735

    
736
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
737
{
738
    return _cpu_ppc_load_tbu(env);
739
}
740

    
741
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
742
{
743
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
744
}
745

    
746
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
747
{
748
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
749
}
750

    
751
/*****************************************************************************/
752
/* Embedded PowerPC timers */
753

    
754
/* PIT, FIT & WDT */
755
typedef struct ppcemb_timer_t ppcemb_timer_t;
756
struct ppcemb_timer_t {
757
    uint64_t pit_reload;  /* PIT auto-reload value        */
758
    uint64_t fit_next;    /* Tick for next FIT interrupt  */
759
    struct QEMUTimer *fit_timer;
760
    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
761
    struct QEMUTimer *wdt_timer;
762
};
763

    
764
/* Fixed interval timer */
765
static void cpu_4xx_fit_cb (void *opaque)
766
{
767
    CPUState *env;
768
    ppc_tb_t *tb_env;
769
    ppcemb_timer_t *ppcemb_timer;
770
    uint64_t now, next;
771

    
772
    env = opaque;
773
    tb_env = env->tb_env;
774
    ppcemb_timer = tb_env->opaque;
775
    now = qemu_get_clock(vm_clock);
776
    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
777
    case 0:
778
        next = 1 << 9;
779
        break;
780
    case 1:
781
        next = 1 << 13;
782
        break;
783
    case 2:
784
        next = 1 << 17;
785
        break;
786
    case 3:
787
        next = 1 << 21;
788
        break;
789
    default:
790
        /* Cannot occur, but makes gcc happy */
791
        return;
792
    }
793
    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
794
    if (next == now)
795
        next++;
796
    qemu_mod_timer(ppcemb_timer->fit_timer, next);
797
    env->spr[SPR_40x_TSR] |= 1 << 26;
798
    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
799
        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
800
    LOG_TB("%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
801
                (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
802
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
803
}
804

    
805
/* Programmable interval timer */
806
static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
807
{
808
    ppcemb_timer_t *ppcemb_timer;
809
    uint64_t now, next;
810

    
811
    ppcemb_timer = tb_env->opaque;
812
    if (ppcemb_timer->pit_reload <= 1 ||
813
        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
814
        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
815
        /* Stop PIT */
816
        LOG_TB("%s: stop PIT\n", __func__);
817
        qemu_del_timer(tb_env->decr_timer);
818
    } else {
819
        LOG_TB("%s: start PIT %016" PRIx64 "\n",
820
                    __func__, ppcemb_timer->pit_reload);
821
        now = qemu_get_clock(vm_clock);
822
        next = now + muldiv64(ppcemb_timer->pit_reload,
823
                              ticks_per_sec, tb_env->decr_freq);
824
        if (is_excp)
825
            next += tb_env->decr_next - now;
826
        if (next == now)
827
            next++;
828
        qemu_mod_timer(tb_env->decr_timer, next);
829
        tb_env->decr_next = next;
830
    }
831
}
832

    
833
static void cpu_4xx_pit_cb (void *opaque)
834
{
835
    CPUState *env;
836
    ppc_tb_t *tb_env;
837
    ppcemb_timer_t *ppcemb_timer;
838

    
839
    env = opaque;
840
    tb_env = env->tb_env;
841
    ppcemb_timer = tb_env->opaque;
842
    env->spr[SPR_40x_TSR] |= 1 << 27;
843
    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
844
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
845
    start_stop_pit(env, tb_env, 1);
846
    LOG_TB("%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
847
                "%016" PRIx64 "\n", __func__,
848
                (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
849
                (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
850
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
851
                ppcemb_timer->pit_reload);
852
}
853

    
854
/* Watchdog timer */
855
static void cpu_4xx_wdt_cb (void *opaque)
856
{
857
    CPUState *env;
858
    ppc_tb_t *tb_env;
859
    ppcemb_timer_t *ppcemb_timer;
860
    uint64_t now, next;
861

    
862
    env = opaque;
863
    tb_env = env->tb_env;
864
    ppcemb_timer = tb_env->opaque;
865
    now = qemu_get_clock(vm_clock);
866
    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
867
    case 0:
868
        next = 1 << 17;
869
        break;
870
    case 1:
871
        next = 1 << 21;
872
        break;
873
    case 2:
874
        next = 1 << 25;
875
        break;
876
    case 3:
877
        next = 1 << 29;
878
        break;
879
    default:
880
        /* Cannot occur, but makes gcc happy */
881
        return;
882
    }
883
    next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
884
    if (next == now)
885
        next++;
886
    LOG_TB("%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
887
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
888
    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
889
    case 0x0:
890
    case 0x1:
891
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
892
        ppcemb_timer->wdt_next = next;
893
        env->spr[SPR_40x_TSR] |= 1 << 31;
894
        break;
895
    case 0x2:
896
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
897
        ppcemb_timer->wdt_next = next;
898
        env->spr[SPR_40x_TSR] |= 1 << 30;
899
        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
900
            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
901
        break;
902
    case 0x3:
903
        env->spr[SPR_40x_TSR] &= ~0x30000000;
904
        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
905
        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
906
        case 0x0:
907
            /* No reset */
908
            break;
909
        case 0x1: /* Core reset */
910
            ppc40x_core_reset(env);
911
            break;
912
        case 0x2: /* Chip reset */
913
            ppc40x_chip_reset(env);
914
            break;
915
        case 0x3: /* System reset */
916
            ppc40x_system_reset(env);
917
            break;
918
        }
919
    }
920
}
921

    
922
void store_40x_pit (CPUState *env, target_ulong val)
923
{
924
    ppc_tb_t *tb_env;
925
    ppcemb_timer_t *ppcemb_timer;
926

    
927
    tb_env = env->tb_env;
928
    ppcemb_timer = tb_env->opaque;
929
    LOG_TB("%s val" ADDRX "\n", __func__, val);
930
    ppcemb_timer->pit_reload = val;
931
    start_stop_pit(env, tb_env, 0);
932
}
933

    
934
target_ulong load_40x_pit (CPUState *env)
935
{
936
    return cpu_ppc_load_decr(env);
937
}
938

    
939
void store_booke_tsr (CPUState *env, target_ulong val)
940
{
941
    LOG_TB("%s: val " ADDRX "\n", __func__, val);
942
    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
943
    if (val & 0x80000000)
944
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
945
}
946

    
947
void store_booke_tcr (CPUState *env, target_ulong val)
948
{
949
    ppc_tb_t *tb_env;
950

    
951
    tb_env = env->tb_env;
952
    LOG_TB("%s: val " ADDRX "\n", __func__, val);
953
    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
954
    start_stop_pit(env, tb_env, 1);
955
    cpu_4xx_wdt_cb(env);
956
}
957

    
958
static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
959
{
960
    CPUState *env = opaque;
961
    ppc_tb_t *tb_env = env->tb_env;
962

    
963
    LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
964
                freq);
965
    tb_env->tb_freq = freq;
966
    tb_env->decr_freq = freq;
967
    /* XXX: we should also update all timers */
968
}
969

    
970
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
971
{
972
    ppc_tb_t *tb_env;
973
    ppcemb_timer_t *ppcemb_timer;
974

    
975
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
976
    env->tb_env = tb_env;
977
    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
978
    tb_env->tb_freq = freq;
979
    tb_env->decr_freq = freq;
980
    tb_env->opaque = ppcemb_timer;
981
    LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
982
    if (ppcemb_timer != NULL) {
983
        /* We use decr timer for PIT */
984
        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
985
        ppcemb_timer->fit_timer =
986
            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
987
        ppcemb_timer->wdt_timer =
988
            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
989
    }
990

    
991
    return &ppc_emb_set_tb_clk;
992
}
993

    
994
/*****************************************************************************/
995
/* Embedded PowerPC Device Control Registers */
996
typedef struct ppc_dcrn_t ppc_dcrn_t;
997
struct ppc_dcrn_t {
998
    dcr_read_cb dcr_read;
999
    dcr_write_cb dcr_write;
1000
    void *opaque;
1001
};
1002

    
1003
/* XXX: on 460, DCR addresses are 32 bits wide,
1004
 *      using DCRIPR to get the 22 upper bits of the DCR address
1005
 */
1006
#define DCRN_NB 1024
1007
struct ppc_dcr_t {
1008
    ppc_dcrn_t dcrn[DCRN_NB];
1009
    int (*read_error)(int dcrn);
1010
    int (*write_error)(int dcrn);
1011
};
1012

    
1013
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1014
{
1015
    ppc_dcrn_t *dcr;
1016

    
1017
    if (dcrn < 0 || dcrn >= DCRN_NB)
1018
        goto error;
1019
    dcr = &dcr_env->dcrn[dcrn];
1020
    if (dcr->dcr_read == NULL)
1021
        goto error;
1022
    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1023

    
1024
    return 0;
1025

    
1026
 error:
1027
    if (dcr_env->read_error != NULL)
1028
        return (*dcr_env->read_error)(dcrn);
1029

    
1030
    return -1;
1031
}
1032

    
1033
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1034
{
1035
    ppc_dcrn_t *dcr;
1036

    
1037
    if (dcrn < 0 || dcrn >= DCRN_NB)
1038
        goto error;
1039
    dcr = &dcr_env->dcrn[dcrn];
1040
    if (dcr->dcr_write == NULL)
1041
        goto error;
1042
    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1043

    
1044
    return 0;
1045

    
1046
 error:
1047
    if (dcr_env->write_error != NULL)
1048
        return (*dcr_env->write_error)(dcrn);
1049

    
1050
    return -1;
1051
}
1052

    
1053
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1054
                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1055
{
1056
    ppc_dcr_t *dcr_env;
1057
    ppc_dcrn_t *dcr;
1058

    
1059
    dcr_env = env->dcr_env;
1060
    if (dcr_env == NULL)
1061
        return -1;
1062
    if (dcrn < 0 || dcrn >= DCRN_NB)
1063
        return -1;
1064
    dcr = &dcr_env->dcrn[dcrn];
1065
    if (dcr->opaque != NULL ||
1066
        dcr->dcr_read != NULL ||
1067
        dcr->dcr_write != NULL)
1068
        return -1;
1069
    dcr->opaque = opaque;
1070
    dcr->dcr_read = dcr_read;
1071
    dcr->dcr_write = dcr_write;
1072

    
1073
    return 0;
1074
}
1075

    
1076
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1077
                  int (*write_error)(int dcrn))
1078
{
1079
    ppc_dcr_t *dcr_env;
1080

    
1081
    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1082
    dcr_env->read_error = read_error;
1083
    dcr_env->write_error = write_error;
1084
    env->dcr_env = dcr_env;
1085

    
1086
    return 0;
1087
}
1088

    
1089
#if 0
1090
/*****************************************************************************/
1091
/* Handle system reset (for now, just stop emulation) */
1092
void cpu_ppc_reset (CPUState *env)
1093
{
1094
    printf("Reset asked... Stop emulation\n");
1095
    abort();
1096
}
1097
#endif
1098

    
1099
/*****************************************************************************/
1100
/* Debug port */
1101
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1102
{
1103
    addr &= 0xF;
1104
    switch (addr) {
1105
    case 0:
1106
        printf("%c", val);
1107
        break;
1108
    case 1:
1109
        printf("\n");
1110
        fflush(stdout);
1111
        break;
1112
    case 2:
1113
        printf("Set loglevel to %04" PRIx32 "\n", val);
1114
        cpu_set_log(val | 0x100);
1115
        break;
1116
    }
1117
}
1118

    
1119
/*****************************************************************************/
1120
/* NVRAM helpers */
1121
static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
1122
{
1123
    return (*nvram->read_fn)(nvram->opaque, addr);;
1124
}
1125

    
1126
static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1127
{
1128
    (*nvram->write_fn)(nvram->opaque, addr, val);
1129
}
1130

    
1131
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1132
{
1133
    nvram_write(nvram, addr, value);
1134
}
1135

    
1136
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1137
{
1138
    return nvram_read(nvram, addr);
1139
}
1140

    
1141
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
1142
{
1143
    nvram_write(nvram, addr, value >> 8);
1144
    nvram_write(nvram, addr + 1, value & 0xFF);
1145
}
1146

    
1147
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1148
{
1149
    uint16_t tmp;
1150

    
1151
    tmp = nvram_read(nvram, addr) << 8;
1152
    tmp |= nvram_read(nvram, addr + 1);
1153

    
1154
    return tmp;
1155
}
1156

    
1157
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
1158
{
1159
    nvram_write(nvram, addr, value >> 24);
1160
    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
1161
    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
1162
    nvram_write(nvram, addr + 3, value & 0xFF);
1163
}
1164

    
1165
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1166
{
1167
    uint32_t tmp;
1168

    
1169
    tmp = nvram_read(nvram, addr) << 24;
1170
    tmp |= nvram_read(nvram, addr + 1) << 16;
1171
    tmp |= nvram_read(nvram, addr + 2) << 8;
1172
    tmp |= nvram_read(nvram, addr + 3);
1173

    
1174
    return tmp;
1175
}
1176

    
1177
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1178
                       const char *str, uint32_t max)
1179
{
1180
    int i;
1181

    
1182
    for (i = 0; i < max && str[i] != '\0'; i++) {
1183
        nvram_write(nvram, addr + i, str[i]);
1184
    }
1185
    nvram_write(nvram, addr + i, str[i]);
1186
    nvram_write(nvram, addr + max - 1, '\0');
1187
}
1188

    
1189
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1190
{
1191
    int i;
1192

    
1193
    memset(dst, 0, max);
1194
    for (i = 0; i < max; i++) {
1195
        dst[i] = NVRAM_get_byte(nvram, addr + i);
1196
        if (dst[i] == '\0')
1197
            break;
1198
    }
1199

    
1200
    return i;
1201
}
1202

    
1203
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1204
{
1205
    uint16_t tmp;
1206
    uint16_t pd, pd1, pd2;
1207

    
1208
    tmp = prev >> 8;
1209
    pd = prev ^ value;
1210
    pd1 = pd & 0x000F;
1211
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1212
    tmp ^= (pd1 << 3) | (pd1 << 8);
1213
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1214

    
1215
    return tmp;
1216
}
1217

    
1218
static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1219
{
1220
    uint32_t i;
1221
    uint16_t crc = 0xFFFF;
1222
    int odd;
1223

    
1224
    odd = count & 1;
1225
    count &= ~1;
1226
    for (i = 0; i != count; i++) {
1227
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1228
    }
1229
    if (odd) {
1230
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1231
    }
1232

    
1233
    return crc;
1234
}
1235

    
1236
#define CMDLINE_ADDR 0x017ff000
1237

    
1238
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
1239
                          const char *arch,
1240
                          uint32_t RAM_size, int boot_device,
1241
                          uint32_t kernel_image, uint32_t kernel_size,
1242
                          const char *cmdline,
1243
                          uint32_t initrd_image, uint32_t initrd_size,
1244
                          uint32_t NVRAM_image,
1245
                          int width, int height, int depth)
1246
{
1247
    uint16_t crc;
1248

    
1249
    /* Set parameters for Open Hack'Ware BIOS */
1250
    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1251
    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
1252
    NVRAM_set_word(nvram,   0x14, NVRAM_size);
1253
    NVRAM_set_string(nvram, 0x20, arch, 16);
1254
    NVRAM_set_lword(nvram,  0x30, RAM_size);
1255
    NVRAM_set_byte(nvram,   0x34, boot_device);
1256
    NVRAM_set_lword(nvram,  0x38, kernel_image);
1257
    NVRAM_set_lword(nvram,  0x3C, kernel_size);
1258
    if (cmdline) {
1259
        /* XXX: put the cmdline in NVRAM too ? */
1260
        strcpy((char *)(phys_ram_base + CMDLINE_ADDR), cmdline);
1261
        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
1262
        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
1263
    } else {
1264
        NVRAM_set_lword(nvram,  0x40, 0);
1265
        NVRAM_set_lword(nvram,  0x44, 0);
1266
    }
1267
    NVRAM_set_lword(nvram,  0x48, initrd_image);
1268
    NVRAM_set_lword(nvram,  0x4C, initrd_size);
1269
    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
1270

    
1271
    NVRAM_set_word(nvram,   0x54, width);
1272
    NVRAM_set_word(nvram,   0x56, height);
1273
    NVRAM_set_word(nvram,   0x58, depth);
1274
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1275
    NVRAM_set_word(nvram,   0xFC, crc);
1276

    
1277
    return 0;
1278
}