Statistics
| Branch: | Revision:

root / hw / ppc.c @ 4b71051e

History | View | Annotate | Download (39.1 kB)

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

    
34
//#define PPC_DEBUG_IRQ
35
//#define PPC_DEBUG_TB
36

    
37
#ifdef PPC_DEBUG_IRQ
38
#  define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
39
#else
40
#  define LOG_IRQ(...) do { } while (0)
41
#endif
42

    
43

    
44
#ifdef PPC_DEBUG_TB
45
#  define LOG_TB(...) qemu_log(__VA_ARGS__)
46
#else
47
#  define LOG_TB(...) do { } while (0)
48
#endif
49

    
50
static void cpu_ppc_tb_stop (CPUState *env);
51
static void cpu_ppc_tb_start (CPUState *env);
52

    
53
static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
54
{
55
    unsigned int old_pending = env->pending_interrupts;
56

    
57
    if (level) {
58
        env->pending_interrupts |= 1 << n_IRQ;
59
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
60
    } else {
61
        env->pending_interrupts &= ~(1 << n_IRQ);
62
        if (env->pending_interrupts == 0)
63
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
64
    }
65

    
66
    if (old_pending != env->pending_interrupts) {
67
#ifdef CONFIG_KVM
68
        kvmppc_set_interrupt(env, n_IRQ, level);
69
#endif
70
    }
71

    
72
    LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
73
                "req %08x\n", __func__, env, n_IRQ, level,
74
                env->pending_interrupts, env->interrupt_request);
75
}
76

    
77
/* PowerPC 6xx / 7xx internal IRQ controller */
78
static void ppc6xx_set_irq (void *opaque, int pin, int level)
79
{
80
    CPUState *env = opaque;
81
    int cur_level;
82

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

    
160
void ppc6xx_irq_init (CPUState *env)
161
{
162
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
163
                                                  PPC6xx_INPUT_NB);
164
}
165

    
166
#if defined(TARGET_PPC64)
167
/* PowerPC 970 internal IRQ controller */
168
static void ppc970_set_irq (void *opaque, int pin, int level)
169
{
170
    CPUState *env = opaque;
171
    int cur_level;
172

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

    
245
void ppc970_irq_init (CPUState *env)
246
{
247
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
248
                                                  PPC970_INPUT_NB);
249
}
250

    
251
/* POWER7 internal IRQ controller */
252
static void power7_set_irq (void *opaque, int pin, int level)
253
{
254
    CPUState *env = opaque;
255

    
256
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
257
                env, pin, level);
258

    
259
    switch (pin) {
260
    case POWER7_INPUT_INT:
261
        /* Level sensitive - active high */
262
        LOG_IRQ("%s: set the external IRQ state to %d\n",
263
                __func__, level);
264
        ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
265
        break;
266
    default:
267
        /* Unknown pin - do nothing */
268
        LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
269
        return;
270
    }
271
    if (level) {
272
        env->irq_input_state |= 1 << pin;
273
    } else {
274
        env->irq_input_state &= ~(1 << pin);
275
    }
276
}
277

    
278
void ppcPOWER7_irq_init (CPUState *env)
279
{
280
    env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, env,
281
                                                  POWER7_INPUT_NB);
282
}
283
#endif /* defined(TARGET_PPC64) */
284

    
285
/* PowerPC 40x internal IRQ controller */
286
static void ppc40x_set_irq (void *opaque, int pin, int level)
287
{
288
    CPUState *env = opaque;
289
    int cur_level;
290

    
291
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
292
                env, pin, level);
293
    cur_level = (env->irq_input_state >> pin) & 1;
294
    /* Don't generate spurious events */
295
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
296
        switch (pin) {
297
        case PPC40x_INPUT_RESET_SYS:
298
            if (level) {
299
                LOG_IRQ("%s: reset the PowerPC system\n",
300
                            __func__);
301
                ppc40x_system_reset(env);
302
            }
303
            break;
304
        case PPC40x_INPUT_RESET_CHIP:
305
            if (level) {
306
                LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
307
                ppc40x_chip_reset(env);
308
            }
309
            break;
310
        case PPC40x_INPUT_RESET_CORE:
311
            /* XXX: TODO: update DBSR[MRR] */
312
            if (level) {
313
                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
314
                ppc40x_core_reset(env);
315
            }
316
            break;
317
        case PPC40x_INPUT_CINT:
318
            /* Level sensitive - active high */
319
            LOG_IRQ("%s: set the critical IRQ state to %d\n",
320
                        __func__, level);
321
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
322
            break;
323
        case PPC40x_INPUT_INT:
324
            /* Level sensitive - active high */
325
            LOG_IRQ("%s: set the external IRQ state to %d\n",
326
                        __func__, level);
327
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
328
            break;
329
        case PPC40x_INPUT_HALT:
330
            /* Level sensitive - active low */
331
            if (level) {
332
                LOG_IRQ("%s: stop the CPU\n", __func__);
333
                env->halted = 1;
334
            } else {
335
                LOG_IRQ("%s: restart the CPU\n", __func__);
336
                env->halted = 0;
337
                qemu_cpu_kick(env);
338
            }
339
            break;
340
        case PPC40x_INPUT_DEBUG:
341
            /* Level sensitive - active high */
342
            LOG_IRQ("%s: set the debug pin state to %d\n",
343
                        __func__, level);
344
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
345
            break;
346
        default:
347
            /* Unknown pin - do nothing */
348
            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
349
            return;
350
        }
351
        if (level)
352
            env->irq_input_state |= 1 << pin;
353
        else
354
            env->irq_input_state &= ~(1 << pin);
355
    }
356
}
357

    
358
void ppc40x_irq_init (CPUState *env)
359
{
360
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
361
                                                  env, PPC40x_INPUT_NB);
362
}
363

    
364
/* PowerPC E500 internal IRQ controller */
365
static void ppce500_set_irq (void *opaque, int pin, int level)
366
{
367
    CPUState *env = opaque;
368
    int cur_level;
369

    
370
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
371
                env, pin, level);
372
    cur_level = (env->irq_input_state >> pin) & 1;
373
    /* Don't generate spurious events */
374
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
375
        switch (pin) {
376
        case PPCE500_INPUT_MCK:
377
            if (level) {
378
                LOG_IRQ("%s: reset the PowerPC system\n",
379
                            __func__);
380
                qemu_system_reset_request();
381
            }
382
            break;
383
        case PPCE500_INPUT_RESET_CORE:
384
            if (level) {
385
                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
386
                ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
387
            }
388
            break;
389
        case PPCE500_INPUT_CINT:
390
            /* Level sensitive - active high */
391
            LOG_IRQ("%s: set the critical IRQ state to %d\n",
392
                        __func__, level);
393
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
394
            break;
395
        case PPCE500_INPUT_INT:
396
            /* Level sensitive - active high */
397
            LOG_IRQ("%s: set the core IRQ state to %d\n",
398
                        __func__, level);
399
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
400
            break;
401
        case PPCE500_INPUT_DEBUG:
402
            /* Level sensitive - active high */
403
            LOG_IRQ("%s: set the debug pin state to %d\n",
404
                        __func__, level);
405
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
406
            break;
407
        default:
408
            /* Unknown pin - do nothing */
409
            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
410
            return;
411
        }
412
        if (level)
413
            env->irq_input_state |= 1 << pin;
414
        else
415
            env->irq_input_state &= ~(1 << pin);
416
    }
417
}
418

    
419
void ppce500_irq_init (CPUState *env)
420
{
421
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
422
                                        env, PPCE500_INPUT_NB);
423
}
424
/*****************************************************************************/
425
/* PowerPC time base and decrementer emulation */
426
struct ppc_tb_t {
427
    /* Time base management */
428
    int64_t  tb_offset;    /* Compensation                    */
429
    int64_t  atb_offset;   /* Compensation                    */
430
    uint32_t tb_freq;      /* TB frequency                    */
431
    /* Decrementer management */
432
    uint64_t decr_next;    /* Tick for next decr interrupt    */
433
    uint32_t decr_freq;    /* decrementer frequency           */
434
    struct QEMUTimer *decr_timer;
435
    /* Hypervisor decrementer management */
436
    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
437
    struct QEMUTimer *hdecr_timer;
438
    uint64_t purr_load;
439
    uint64_t purr_start;
440
    void *opaque;
441
};
442

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

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

    
455
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
456
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
457

    
458
    return tb;
459
}
460

    
461
static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
462
{
463
    ppc_tb_t *tb_env = env->tb_env;
464
    uint64_t tb;
465

    
466
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
467
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
468

    
469
    return tb >> 32;
470
}
471

    
472
uint32_t cpu_ppc_load_tbu (CPUState *env)
473
{
474
    return _cpu_ppc_load_tbu(env);
475
}
476

    
477
static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
478
                                    int64_t *tb_offsetp, uint64_t value)
479
{
480
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec());
481
    LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
482
                __func__, value, *tb_offsetp);
483
}
484

    
485
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
486
{
487
    ppc_tb_t *tb_env = env->tb_env;
488
    uint64_t tb;
489

    
490
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
491
    tb &= 0xFFFFFFFF00000000ULL;
492
    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
493
                     &tb_env->tb_offset, tb | (uint64_t)value);
494
}
495

    
496
static inline void _cpu_ppc_store_tbu(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_ns(vm_clock), tb_env->tb_offset);
502
    tb &= 0x00000000FFFFFFFFULL;
503
    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
504
                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
505
}
506

    
507
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
508
{
509
    _cpu_ppc_store_tbu(env, value);
510
}
511

    
512
uint64_t cpu_ppc_load_atbl (CPUState *env)
513
{
514
    ppc_tb_t *tb_env = env->tb_env;
515
    uint64_t tb;
516

    
517
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
518
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
519

    
520
    return tb;
521
}
522

    
523
uint32_t cpu_ppc_load_atbu (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_ns(vm_clock), tb_env->atb_offset);
529
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
530

    
531
    return tb >> 32;
532
}
533

    
534
void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
535
{
536
    ppc_tb_t *tb_env = env->tb_env;
537
    uint64_t tb;
538

    
539
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
540
    tb &= 0xFFFFFFFF00000000ULL;
541
    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
542
                     &tb_env->atb_offset, tb | (uint64_t)value);
543
}
544

    
545
void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
546
{
547
    ppc_tb_t *tb_env = env->tb_env;
548
    uint64_t tb;
549

    
550
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
551
    tb &= 0x00000000FFFFFFFFULL;
552
    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
553
                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
554
}
555

    
556
static void cpu_ppc_tb_stop (CPUState *env)
557
{
558
    ppc_tb_t *tb_env = env->tb_env;
559
    uint64_t tb, atb, vmclk;
560

    
561
    /* If the time base is already frozen, do nothing */
562
    if (tb_env->tb_freq != 0) {
563
        vmclk = qemu_get_clock_ns(vm_clock);
564
        /* Get the time base */
565
        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
566
        /* Get the alternate time base */
567
        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
568
        /* Store the time base value (ie compute the current offset) */
569
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
570
        /* Store the alternate time base value (compute the current offset) */
571
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
572
        /* Set the time base frequency to zero */
573
        tb_env->tb_freq = 0;
574
        /* Now, the time bases are frozen to tb_offset / atb_offset value */
575
    }
576
}
577

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

    
583
    /* If the time base is not frozen, do nothing */
584
    if (tb_env->tb_freq == 0) {
585
        vmclk = qemu_get_clock_ns(vm_clock);
586
        /* Get the time base from tb_offset */
587
        tb = tb_env->tb_offset;
588
        /* Get the alternate time base from atb_offset */
589
        atb = tb_env->atb_offset;
590
        /* Restore the tb frequency from the decrementer frequency */
591
        tb_env->tb_freq = tb_env->decr_freq;
592
        /* Store the time base value */
593
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
594
        /* Store the alternate time base value */
595
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
596
    }
597
}
598

    
599
static inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next)
600
{
601
    ppc_tb_t *tb_env = env->tb_env;
602
    uint32_t decr;
603
    int64_t diff;
604

    
605
    diff = next - qemu_get_clock_ns(vm_clock);
606
    if (diff >= 0)
607
        decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
608
    else
609
        decr = -muldiv64(-diff, tb_env->decr_freq, get_ticks_per_sec());
610
    LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
611

    
612
    return decr;
613
}
614

    
615
uint32_t cpu_ppc_load_decr (CPUState *env)
616
{
617
    ppc_tb_t *tb_env = env->tb_env;
618

    
619
    return _cpu_ppc_load_decr(env, tb_env->decr_next);
620
}
621

    
622
uint32_t cpu_ppc_load_hdecr (CPUState *env)
623
{
624
    ppc_tb_t *tb_env = env->tb_env;
625

    
626
    return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
627
}
628

    
629
uint64_t cpu_ppc_load_purr (CPUState *env)
630
{
631
    ppc_tb_t *tb_env = env->tb_env;
632
    uint64_t diff;
633

    
634
    diff = qemu_get_clock_ns(vm_clock) - tb_env->purr_start;
635

    
636
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, get_ticks_per_sec());
637
}
638

    
639
/* When decrementer expires,
640
 * all we need to do is generate or queue a CPU exception
641
 */
642
static inline void cpu_ppc_decr_excp(CPUState *env)
643
{
644
    /* Raise it */
645
    LOG_TB("raise decrementer exception\n");
646
    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
647
}
648

    
649
static inline void cpu_ppc_hdecr_excp(CPUState *env)
650
{
651
    /* Raise it */
652
    LOG_TB("raise decrementer exception\n");
653
    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
654
}
655

    
656
static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
657
                                  struct QEMUTimer *timer,
658
                                  void (*raise_excp)(CPUState *),
659
                                  uint32_t decr, uint32_t value,
660
                                  int is_excp)
661
{
662
    ppc_tb_t *tb_env = env->tb_env;
663
    uint64_t now, next;
664

    
665
    LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
666
                decr, value);
667
    now = qemu_get_clock_ns(vm_clock);
668
    next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
669
    if (is_excp)
670
        next += *nextp - now;
671
    if (next == now)
672
        next++;
673
    *nextp = next;
674
    /* Adjust timer */
675
    qemu_mod_timer(timer, next);
676
    /* If we set a negative value and the decrementer was positive,
677
     * raise an exception.
678
     */
679
    if ((value & 0x80000000) && !(decr & 0x80000000))
680
        (*raise_excp)(env);
681
}
682

    
683
static inline void _cpu_ppc_store_decr(CPUState *env, uint32_t decr,
684
                                       uint32_t value, int is_excp)
685
{
686
    ppc_tb_t *tb_env = env->tb_env;
687

    
688
    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
689
                         &cpu_ppc_decr_excp, decr, value, is_excp);
690
}
691

    
692
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
693
{
694
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
695
}
696

    
697
static void cpu_ppc_decr_cb (void *opaque)
698
{
699
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
700
}
701

    
702
static inline void _cpu_ppc_store_hdecr(CPUState *env, uint32_t hdecr,
703
                                        uint32_t value, int is_excp)
704
{
705
    ppc_tb_t *tb_env = env->tb_env;
706

    
707
    if (tb_env->hdecr_timer != NULL) {
708
        __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
709
                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
710
    }
711
}
712

    
713
void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
714
{
715
    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
716
}
717

    
718
static void cpu_ppc_hdecr_cb (void *opaque)
719
{
720
    _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
721
}
722

    
723
void cpu_ppc_store_purr (CPUState *env, uint64_t value)
724
{
725
    ppc_tb_t *tb_env = env->tb_env;
726

    
727
    tb_env->purr_load = value;
728
    tb_env->purr_start = qemu_get_clock_ns(vm_clock);
729
}
730

    
731
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
732
{
733
    CPUState *env = opaque;
734
    ppc_tb_t *tb_env = env->tb_env;
735

    
736
    tb_env->tb_freq = freq;
737
    tb_env->decr_freq = freq;
738
    /* There is a bug in Linux 2.4 kernels:
739
     * if a decrementer exception is pending when it enables msr_ee at startup,
740
     * it's not ready to handle it...
741
     */
742
    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
743
    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
744
    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
745
}
746

    
747
/* Set up (once) timebase frequency (in Hz) */
748
clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
749
{
750
    ppc_tb_t *tb_env;
751

    
752
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
753
    env->tb_env = tb_env;
754
    /* Create new timer */
755
    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, env);
756
    if (0) {
757
        /* XXX: find a suitable condition to enable the hypervisor decrementer
758
         */
759
        tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb, env);
760
    } else {
761
        tb_env->hdecr_timer = NULL;
762
    }
763
    cpu_ppc_set_tb_clk(env, freq);
764

    
765
    return &cpu_ppc_set_tb_clk;
766
}
767

    
768
/* Specific helpers for POWER & PowerPC 601 RTC */
769
#if 0
770
static clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
771
{
772
    return cpu_ppc_tb_init(env, 7812500);
773
}
774
#endif
775

    
776
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
777
{
778
    _cpu_ppc_store_tbu(env, value);
779
}
780

    
781
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
782
{
783
    return _cpu_ppc_load_tbu(env);
784
}
785

    
786
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
787
{
788
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
789
}
790

    
791
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
792
{
793
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
794
}
795

    
796
/*****************************************************************************/
797
/* Embedded PowerPC timers */
798

    
799
/* PIT, FIT & WDT */
800
typedef struct ppcemb_timer_t ppcemb_timer_t;
801
struct ppcemb_timer_t {
802
    uint64_t pit_reload;  /* PIT auto-reload value        */
803
    uint64_t fit_next;    /* Tick for next FIT interrupt  */
804
    struct QEMUTimer *fit_timer;
805
    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
806
    struct QEMUTimer *wdt_timer;
807

    
808
    /* 405 have the PIT, 440 have a DECR.  */
809
    unsigned int decr_excp;
810
};
811

    
812
/* Fixed interval timer */
813
static void cpu_4xx_fit_cb (void *opaque)
814
{
815
    CPUState *env;
816
    ppc_tb_t *tb_env;
817
    ppcemb_timer_t *ppcemb_timer;
818
    uint64_t now, next;
819

    
820
    env = opaque;
821
    tb_env = env->tb_env;
822
    ppcemb_timer = tb_env->opaque;
823
    now = qemu_get_clock_ns(vm_clock);
824
    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
825
    case 0:
826
        next = 1 << 9;
827
        break;
828
    case 1:
829
        next = 1 << 13;
830
        break;
831
    case 2:
832
        next = 1 << 17;
833
        break;
834
    case 3:
835
        next = 1 << 21;
836
        break;
837
    default:
838
        /* Cannot occur, but makes gcc happy */
839
        return;
840
    }
841
    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
842
    if (next == now)
843
        next++;
844
    qemu_mod_timer(ppcemb_timer->fit_timer, next);
845
    env->spr[SPR_40x_TSR] |= 1 << 26;
846
    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
847
        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
848
    LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
849
           (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
850
           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
851
}
852

    
853
/* Programmable interval timer */
854
static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
855
{
856
    ppcemb_timer_t *ppcemb_timer;
857
    uint64_t now, next;
858

    
859
    ppcemb_timer = tb_env->opaque;
860
    if (ppcemb_timer->pit_reload <= 1 ||
861
        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
862
        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
863
        /* Stop PIT */
864
        LOG_TB("%s: stop PIT\n", __func__);
865
        qemu_del_timer(tb_env->decr_timer);
866
    } else {
867
        LOG_TB("%s: start PIT %016" PRIx64 "\n",
868
                    __func__, ppcemb_timer->pit_reload);
869
        now = qemu_get_clock_ns(vm_clock);
870
        next = now + muldiv64(ppcemb_timer->pit_reload,
871
                              get_ticks_per_sec(), tb_env->decr_freq);
872
        if (is_excp)
873
            next += tb_env->decr_next - now;
874
        if (next == now)
875
            next++;
876
        qemu_mod_timer(tb_env->decr_timer, next);
877
        tb_env->decr_next = next;
878
    }
879
}
880

    
881
static void cpu_4xx_pit_cb (void *opaque)
882
{
883
    CPUState *env;
884
    ppc_tb_t *tb_env;
885
    ppcemb_timer_t *ppcemb_timer;
886

    
887
    env = opaque;
888
    tb_env = env->tb_env;
889
    ppcemb_timer = tb_env->opaque;
890
    env->spr[SPR_40x_TSR] |= 1 << 27;
891
    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
892
        ppc_set_irq(env, ppcemb_timer->decr_excp, 1);
893
    start_stop_pit(env, tb_env, 1);
894
    LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
895
           "%016" PRIx64 "\n", __func__,
896
           (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
897
           (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
898
           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
899
           ppcemb_timer->pit_reload);
900
}
901

    
902
/* Watchdog timer */
903
static void cpu_4xx_wdt_cb (void *opaque)
904
{
905
    CPUState *env;
906
    ppc_tb_t *tb_env;
907
    ppcemb_timer_t *ppcemb_timer;
908
    uint64_t now, next;
909

    
910
    env = opaque;
911
    tb_env = env->tb_env;
912
    ppcemb_timer = tb_env->opaque;
913
    now = qemu_get_clock_ns(vm_clock);
914
    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
915
    case 0:
916
        next = 1 << 17;
917
        break;
918
    case 1:
919
        next = 1 << 21;
920
        break;
921
    case 2:
922
        next = 1 << 25;
923
        break;
924
    case 3:
925
        next = 1 << 29;
926
        break;
927
    default:
928
        /* Cannot occur, but makes gcc happy */
929
        return;
930
    }
931
    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->decr_freq);
932
    if (next == now)
933
        next++;
934
    LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
935
           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
936
    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
937
    case 0x0:
938
    case 0x1:
939
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
940
        ppcemb_timer->wdt_next = next;
941
        env->spr[SPR_40x_TSR] |= 1 << 31;
942
        break;
943
    case 0x2:
944
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
945
        ppcemb_timer->wdt_next = next;
946
        env->spr[SPR_40x_TSR] |= 1 << 30;
947
        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
948
            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
949
        break;
950
    case 0x3:
951
        env->spr[SPR_40x_TSR] &= ~0x30000000;
952
        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
953
        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
954
        case 0x0:
955
            /* No reset */
956
            break;
957
        case 0x1: /* Core reset */
958
            ppc40x_core_reset(env);
959
            break;
960
        case 0x2: /* Chip reset */
961
            ppc40x_chip_reset(env);
962
            break;
963
        case 0x3: /* System reset */
964
            ppc40x_system_reset(env);
965
            break;
966
        }
967
    }
968
}
969

    
970
void store_40x_pit (CPUState *env, target_ulong val)
971
{
972
    ppc_tb_t *tb_env;
973
    ppcemb_timer_t *ppcemb_timer;
974

    
975
    tb_env = env->tb_env;
976
    ppcemb_timer = tb_env->opaque;
977
    LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
978
    ppcemb_timer->pit_reload = val;
979
    start_stop_pit(env, tb_env, 0);
980
}
981

    
982
target_ulong load_40x_pit (CPUState *env)
983
{
984
    return cpu_ppc_load_decr(env);
985
}
986

    
987
void store_booke_tsr (CPUState *env, target_ulong val)
988
{
989
    ppc_tb_t *tb_env = env->tb_env;
990
    ppcemb_timer_t *ppcemb_timer;
991

    
992
    ppcemb_timer = tb_env->opaque;
993

    
994
    LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
995
    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
996
    if (val & 0x80000000)
997
        ppc_set_irq(env, ppcemb_timer->decr_excp, 0);
998
}
999

    
1000
void store_booke_tcr (CPUState *env, target_ulong val)
1001
{
1002
    ppc_tb_t *tb_env;
1003

    
1004
    tb_env = env->tb_env;
1005
    LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
1006
    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1007
    start_stop_pit(env, tb_env, 1);
1008
    cpu_4xx_wdt_cb(env);
1009
}
1010

    
1011
static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1012
{
1013
    CPUState *env = opaque;
1014
    ppc_tb_t *tb_env = env->tb_env;
1015

    
1016
    LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
1017
                freq);
1018
    tb_env->tb_freq = freq;
1019
    tb_env->decr_freq = freq;
1020
    /* XXX: we should also update all timers */
1021
}
1022

    
1023
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq,
1024
                                  unsigned int decr_excp)
1025
{
1026
    ppc_tb_t *tb_env;
1027
    ppcemb_timer_t *ppcemb_timer;
1028

    
1029
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
1030
    env->tb_env = tb_env;
1031
    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
1032
    tb_env->tb_freq = freq;
1033
    tb_env->decr_freq = freq;
1034
    tb_env->opaque = ppcemb_timer;
1035
    LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
1036
    if (ppcemb_timer != NULL) {
1037
        /* We use decr timer for PIT */
1038
        tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
1039
        ppcemb_timer->fit_timer =
1040
            qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
1041
        ppcemb_timer->wdt_timer =
1042
            qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
1043
        ppcemb_timer->decr_excp = decr_excp;
1044
    }
1045

    
1046
    return &ppc_emb_set_tb_clk;
1047
}
1048

    
1049
/*****************************************************************************/
1050
/* Embedded PowerPC Device Control Registers */
1051
typedef struct ppc_dcrn_t ppc_dcrn_t;
1052
struct ppc_dcrn_t {
1053
    dcr_read_cb dcr_read;
1054
    dcr_write_cb dcr_write;
1055
    void *opaque;
1056
};
1057

    
1058
/* XXX: on 460, DCR addresses are 32 bits wide,
1059
 *      using DCRIPR to get the 22 upper bits of the DCR address
1060
 */
1061
#define DCRN_NB 1024
1062
struct ppc_dcr_t {
1063
    ppc_dcrn_t dcrn[DCRN_NB];
1064
    int (*read_error)(int dcrn);
1065
    int (*write_error)(int dcrn);
1066
};
1067

    
1068
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
1069
{
1070
    ppc_dcrn_t *dcr;
1071

    
1072
    if (dcrn < 0 || dcrn >= DCRN_NB)
1073
        goto error;
1074
    dcr = &dcr_env->dcrn[dcrn];
1075
    if (dcr->dcr_read == NULL)
1076
        goto error;
1077
    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1078

    
1079
    return 0;
1080

    
1081
 error:
1082
    if (dcr_env->read_error != NULL)
1083
        return (*dcr_env->read_error)(dcrn);
1084

    
1085
    return -1;
1086
}
1087

    
1088
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
1089
{
1090
    ppc_dcrn_t *dcr;
1091

    
1092
    if (dcrn < 0 || dcrn >= DCRN_NB)
1093
        goto error;
1094
    dcr = &dcr_env->dcrn[dcrn];
1095
    if (dcr->dcr_write == NULL)
1096
        goto error;
1097
    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1098

    
1099
    return 0;
1100

    
1101
 error:
1102
    if (dcr_env->write_error != NULL)
1103
        return (*dcr_env->write_error)(dcrn);
1104

    
1105
    return -1;
1106
}
1107

    
1108
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1109
                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1110
{
1111
    ppc_dcr_t *dcr_env;
1112
    ppc_dcrn_t *dcr;
1113

    
1114
    dcr_env = env->dcr_env;
1115
    if (dcr_env == NULL)
1116
        return -1;
1117
    if (dcrn < 0 || dcrn >= DCRN_NB)
1118
        return -1;
1119
    dcr = &dcr_env->dcrn[dcrn];
1120
    if (dcr->opaque != NULL ||
1121
        dcr->dcr_read != NULL ||
1122
        dcr->dcr_write != NULL)
1123
        return -1;
1124
    dcr->opaque = opaque;
1125
    dcr->dcr_read = dcr_read;
1126
    dcr->dcr_write = dcr_write;
1127

    
1128
    return 0;
1129
}
1130

    
1131
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1132
                  int (*write_error)(int dcrn))
1133
{
1134
    ppc_dcr_t *dcr_env;
1135

    
1136
    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1137
    dcr_env->read_error = read_error;
1138
    dcr_env->write_error = write_error;
1139
    env->dcr_env = dcr_env;
1140

    
1141
    return 0;
1142
}
1143

    
1144
/*****************************************************************************/
1145
/* Debug port */
1146
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1147
{
1148
    addr &= 0xF;
1149
    switch (addr) {
1150
    case 0:
1151
        printf("%c", val);
1152
        break;
1153
    case 1:
1154
        printf("\n");
1155
        fflush(stdout);
1156
        break;
1157
    case 2:
1158
        printf("Set loglevel to %04" PRIx32 "\n", val);
1159
        cpu_set_log(val | 0x100);
1160
        break;
1161
    }
1162
}
1163

    
1164
/*****************************************************************************/
1165
/* NVRAM helpers */
1166
static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
1167
{
1168
    return (*nvram->read_fn)(nvram->opaque, addr);;
1169
}
1170

    
1171
static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1172
{
1173
    (*nvram->write_fn)(nvram->opaque, addr, val);
1174
}
1175

    
1176
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1177
{
1178
    nvram_write(nvram, addr, value);
1179
}
1180

    
1181
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1182
{
1183
    return nvram_read(nvram, addr);
1184
}
1185

    
1186
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
1187
{
1188
    nvram_write(nvram, addr, value >> 8);
1189
    nvram_write(nvram, addr + 1, value & 0xFF);
1190
}
1191

    
1192
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1193
{
1194
    uint16_t tmp;
1195

    
1196
    tmp = nvram_read(nvram, addr) << 8;
1197
    tmp |= nvram_read(nvram, addr + 1);
1198

    
1199
    return tmp;
1200
}
1201

    
1202
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
1203
{
1204
    nvram_write(nvram, addr, value >> 24);
1205
    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
1206
    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
1207
    nvram_write(nvram, addr + 3, value & 0xFF);
1208
}
1209

    
1210
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1211
{
1212
    uint32_t tmp;
1213

    
1214
    tmp = nvram_read(nvram, addr) << 24;
1215
    tmp |= nvram_read(nvram, addr + 1) << 16;
1216
    tmp |= nvram_read(nvram, addr + 2) << 8;
1217
    tmp |= nvram_read(nvram, addr + 3);
1218

    
1219
    return tmp;
1220
}
1221

    
1222
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1223
                       const char *str, uint32_t max)
1224
{
1225
    int i;
1226

    
1227
    for (i = 0; i < max && str[i] != '\0'; i++) {
1228
        nvram_write(nvram, addr + i, str[i]);
1229
    }
1230
    nvram_write(nvram, addr + i, str[i]);
1231
    nvram_write(nvram, addr + max - 1, '\0');
1232
}
1233

    
1234
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1235
{
1236
    int i;
1237

    
1238
    memset(dst, 0, max);
1239
    for (i = 0; i < max; i++) {
1240
        dst[i] = NVRAM_get_byte(nvram, addr + i);
1241
        if (dst[i] == '\0')
1242
            break;
1243
    }
1244

    
1245
    return i;
1246
}
1247

    
1248
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1249
{
1250
    uint16_t tmp;
1251
    uint16_t pd, pd1, pd2;
1252

    
1253
    tmp = prev >> 8;
1254
    pd = prev ^ value;
1255
    pd1 = pd & 0x000F;
1256
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1257
    tmp ^= (pd1 << 3) | (pd1 << 8);
1258
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1259

    
1260
    return tmp;
1261
}
1262

    
1263
static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1264
{
1265
    uint32_t i;
1266
    uint16_t crc = 0xFFFF;
1267
    int odd;
1268

    
1269
    odd = count & 1;
1270
    count &= ~1;
1271
    for (i = 0; i != count; i++) {
1272
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1273
    }
1274
    if (odd) {
1275
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1276
    }
1277

    
1278
    return crc;
1279
}
1280

    
1281
#define CMDLINE_ADDR 0x017ff000
1282

    
1283
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
1284
                          const char *arch,
1285
                          uint32_t RAM_size, int boot_device,
1286
                          uint32_t kernel_image, uint32_t kernel_size,
1287
                          const char *cmdline,
1288
                          uint32_t initrd_image, uint32_t initrd_size,
1289
                          uint32_t NVRAM_image,
1290
                          int width, int height, int depth)
1291
{
1292
    uint16_t crc;
1293

    
1294
    /* Set parameters for Open Hack'Ware BIOS */
1295
    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1296
    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
1297
    NVRAM_set_word(nvram,   0x14, NVRAM_size);
1298
    NVRAM_set_string(nvram, 0x20, arch, 16);
1299
    NVRAM_set_lword(nvram,  0x30, RAM_size);
1300
    NVRAM_set_byte(nvram,   0x34, boot_device);
1301
    NVRAM_set_lword(nvram,  0x38, kernel_image);
1302
    NVRAM_set_lword(nvram,  0x3C, kernel_size);
1303
    if (cmdline) {
1304
        /* XXX: put the cmdline in NVRAM too ? */
1305
        pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR, cmdline);
1306
        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
1307
        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
1308
    } else {
1309
        NVRAM_set_lword(nvram,  0x40, 0);
1310
        NVRAM_set_lword(nvram,  0x44, 0);
1311
    }
1312
    NVRAM_set_lword(nvram,  0x48, initrd_image);
1313
    NVRAM_set_lword(nvram,  0x4C, initrd_size);
1314
    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
1315

    
1316
    NVRAM_set_word(nvram,   0x54, width);
1317
    NVRAM_set_word(nvram,   0x56, height);
1318
    NVRAM_set_word(nvram,   0x58, depth);
1319
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1320
    NVRAM_set_word(nvram,   0xFC, crc);
1321

    
1322
    return 0;
1323
}