Statistics
| Branch: | Revision:

root / hw / ppc.c @ 6ee093c9

History | View | Annotate | Download (37.8 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 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, get_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 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 inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
431
                                    int64_t *tb_offsetp, uint64_t value)
432
{
433
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec());
434
    LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
435
                __func__, value, *tb_offsetp);
436
}
437

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

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

    
449
static inline void _cpu_ppc_store_tbu(CPUState *env, uint32_t value)
450
{
451
    ppc_tb_t *tb_env = env->tb_env;
452
    uint64_t tb;
453

    
454
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
455
    tb &= 0x00000000FFFFFFFFULL;
456
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
457
                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
458
}
459

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

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

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

    
473
    return tb & 0xFFFFFFFF;
474
}
475

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

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

    
484
    return tb >> 32;
485
}
486

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

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

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

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

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

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

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

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

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

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

    
565
    return decr;
566
}
567

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

    
572
    return _cpu_ppc_load_decr(env, tb_env->decr_next);
573
}
574

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

    
579
    return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
580
}
581

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

    
587
    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
588

    
589
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, get_ticks_per_sec());
590
}
591

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

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

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

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

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

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

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

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

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

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

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

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

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

    
680
    tb_env->purr_load = value;
681
    tb_env->purr_start = qemu_get_clock(vm_clock);
682
}
683

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

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

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

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

    
718
    return &cpu_ppc_set_tb_clk;
719
}
720

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

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

    
734
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
735
{
736
    return _cpu_ppc_load_tbu(env);
737
}
738

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

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

    
749
/*****************************************************************************/
750
/* Embedded PowerPC timers */
751

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

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

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

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

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

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

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

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

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

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

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

    
932
target_ulong load_40x_pit (CPUState *env)
933
{
934
    return cpu_ppc_load_decr(env);
935
}
936

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

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

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

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

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

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

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

    
989
    return &ppc_emb_set_tb_clk;
990
}
991

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

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

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

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

    
1022
    return 0;
1023

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

    
1028
    return -1;
1029
}
1030

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

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

    
1042
    return 0;
1043

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

    
1048
    return -1;
1049
}
1050

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

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

    
1071
    return 0;
1072
}
1073

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

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

    
1084
    return 0;
1085
}
1086

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

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

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

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

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

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

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

    
1145
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1146
{
1147
    uint16_t tmp;
1148

    
1149
    tmp = nvram_read(nvram, addr) << 8;
1150
    tmp |= nvram_read(nvram, addr + 1);
1151

    
1152
    return tmp;
1153
}
1154

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

    
1163
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1164
{
1165
    uint32_t tmp;
1166

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

    
1172
    return tmp;
1173
}
1174

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

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

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

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

    
1198
    return i;
1199
}
1200

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

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

    
1213
    return tmp;
1214
}
1215

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

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

    
1231
    return crc;
1232
}
1233

    
1234
#define CMDLINE_ADDR 0x017ff000
1235

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

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

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

    
1275
    return 0;
1276
}