Statistics
| Branch: | Revision:

root / hw / ppc.c @ d84bda46

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
#include "loader.h"
31

    
32
//#define PPC_DEBUG_IRQ
33
//#define PPC_DEBUG_TB
34

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

    
41

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
412
    return tb & 0xFFFFFFFF;
413
}
414

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

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

    
423
    return tb >> 32;
424
}
425

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

    
431
static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
432
                                    int64_t *tb_offsetp, uint64_t value)
433
{
434
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_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 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 inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next)
554
{
555
    ppc_tb_t *tb_env = env->tb_env;
556
    uint32_t decr;
557
    int64_t diff;
558

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

    
566
    return decr;
567
}
568

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
719
    return &cpu_ppc_set_tb_clk;
720
}
721

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

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

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

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

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

    
750
/*****************************************************************************/
751
/* Embedded PowerPC timers */
752

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
990
    return &ppc_emb_set_tb_clk;
991
}
992

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

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

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

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

    
1023
    return 0;
1024

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

    
1029
    return -1;
1030
}
1031

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

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

    
1043
    return 0;
1044

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

    
1049
    return -1;
1050
}
1051

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

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

    
1072
    return 0;
1073
}
1074

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

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

    
1085
    return 0;
1086
}
1087

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

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

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

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

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

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

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

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

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

    
1153
    return tmp;
1154
}
1155

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

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

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

    
1173
    return tmp;
1174
}
1175

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

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

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

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

    
1199
    return i;
1200
}
1201

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

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

    
1214
    return tmp;
1215
}
1216

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

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

    
1232
    return crc;
1233
}
1234

    
1235
#define CMDLINE_ADDR 0x017ff000
1236

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

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

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

    
1276
    return 0;
1277
}