Statistics
| Branch: | Revision:

root / hw / ppc.c @ 8a84de23

History | View | Annotate | Download (36.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 "vl.h"
25
#include "m48t59.h"
26

    
27
//#define PPC_DEBUG_IRQ
28
//#define PPC_DEBUG_TB
29

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

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

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

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

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

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

    
282
void ppc970_irq_init (CPUState *env)
283
{
284
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
285
}
286

    
287
/* PowerPC 405 internal IRQ controller */
288
static void ppc405_set_irq (void *opaque, int pin, int level)
289
{
290
    CPUState *env = opaque;
291
    int cur_level;
292

    
293
#if defined(PPC_DEBUG_IRQ)
294
    if (loglevel & CPU_LOG_INT) {
295
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
296
                env, pin, level);
297
    }
298
#endif
299
    cur_level = (env->irq_input_state >> pin) & 1;
300
    /* Don't generate spurious events */
301
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
302
        switch (pin) {
303
        case PPC405_INPUT_RESET_SYS:
304
            if (level) {
305
#if defined(PPC_DEBUG_IRQ)
306
                if (loglevel & CPU_LOG_INT) {
307
                    fprintf(logfile, "%s: reset the PowerPC system\n",
308
                            __func__);
309
                }
310
#endif
311
                ppc40x_system_reset(env);
312
            }
313
            break;
314
        case PPC405_INPUT_RESET_CHIP:
315
            if (level) {
316
#if defined(PPC_DEBUG_IRQ)
317
                if (loglevel & CPU_LOG_INT) {
318
                    fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
319
                }
320
#endif
321
                ppc40x_chip_reset(env);
322
            }
323
            break;
324
            /* No break here */
325
        case PPC405_INPUT_RESET_CORE:
326
            /* XXX: TODO: update DBSR[MRR] */
327
            if (level) {
328
#if defined(PPC_DEBUG_IRQ)
329
                if (loglevel & CPU_LOG_INT) {
330
                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
331
                }
332
#endif
333
                ppc40x_core_reset(env);
334
            }
335
            break;
336
        case PPC405_INPUT_CINT:
337
            /* Level sensitive - active high */
338
#if defined(PPC_DEBUG_IRQ)
339
            if (loglevel & CPU_LOG_INT) {
340
                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
341
                        __func__, level);
342
            }
343
#endif
344
            /* XXX: TOFIX */
345
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
346
            break;
347
        case PPC405_INPUT_INT:
348
            /* Level sensitive - active high */
349
#if defined(PPC_DEBUG_IRQ)
350
            if (loglevel & CPU_LOG_INT) {
351
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
352
                        __func__, level);
353
            }
354
#endif
355
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
356
            break;
357
        case PPC405_INPUT_HALT:
358
            /* Level sensitive - active low */
359
            if (level) {
360
#if defined(PPC_DEBUG_IRQ)
361
                if (loglevel & CPU_LOG_INT) {
362
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
363
                }
364
#endif
365
                env->halted = 1;
366
            } else {
367
#if defined(PPC_DEBUG_IRQ)
368
                if (loglevel & CPU_LOG_INT) {
369
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
370
                }
371
#endif
372
                env->halted = 0;
373
            }
374
            break;
375
        case PPC405_INPUT_DEBUG:
376
            /* Level sensitive - active high */
377
#if defined(PPC_DEBUG_IRQ)
378
            if (loglevel & CPU_LOG_INT) {
379
                fprintf(logfile, "%s: set the debug pin state to %d\n",
380
                        __func__, level);
381
            }
382
#endif
383
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
384
            break;
385
        default:
386
            /* Unknown pin - do nothing */
387
#if defined(PPC_DEBUG_IRQ)
388
            if (loglevel & CPU_LOG_INT) {
389
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
390
            }
391
#endif
392
            return;
393
        }
394
        if (level)
395
            env->irq_input_state |= 1 << pin;
396
        else
397
            env->irq_input_state &= ~(1 << pin);
398
    }
399
}
400

    
401
void ppc405_irq_init (CPUState *env)
402
{
403
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc405_set_irq, env, 7);
404
}
405

    
406
/*****************************************************************************/
407
/* PowerPC time base and decrementer emulation */
408
struct ppc_tb_t {
409
    /* Time base management */
410
    int64_t  tb_offset;    /* Compensation               */
411
    int64_t  atb_offset;   /* Compensation               */
412
    uint32_t tb_freq;      /* TB frequency               */
413
    /* Decrementer management */
414
    uint64_t decr_next;    /* Tick for next decr interrupt  */
415
    struct QEMUTimer *decr_timer;
416
#if defined(TARGET_PPC64H)
417
    /* Hypervisor decrementer management */
418
    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
419
    struct QEMUTimer *hdecr_timer;
420
    uint64_t purr_load;
421
    uint64_t purr_start;
422
#endif
423
    void *opaque;
424
};
425

    
426
static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, int64_t tb_offset)
427
{
428
    /* TB time in tb periods */
429
    return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
430
                    tb_env->tb_freq, ticks_per_sec);
431
}
432

    
433
uint32_t cpu_ppc_load_tbl (CPUState *env)
434
{
435
    ppc_tb_t *tb_env = env->tb_env;
436
    uint64_t tb;
437

    
438
    tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset);
439
#if defined(PPC_DEBUG_TB)
440
    if (loglevel != 0) {
441
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
442
    }
443
#endif
444

    
445
    return tb & 0xFFFFFFFF;
446
}
447

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

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

    
460
    return tb >> 32;
461
}
462

    
463
uint32_t cpu_ppc_load_tbu (CPUState *env)
464
{
465
    return _cpu_ppc_load_tbu(env);
466
}
467

    
468
static inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, int64_t *tb_offsetp,
469
                                     uint64_t value)
470
{
471
    *tb_offsetp = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
472
        - qemu_get_clock(vm_clock);
473
#ifdef PPC_DEBUG_TB
474
    if (loglevel != 0) {
475
        fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
476
                *tb_offsetp);
477
    }
478
#endif
479
}
480

    
481
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
482
{
483
    ppc_tb_t *tb_env = env->tb_env;
484
    uint64_t tb;
485

    
486
    tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset);
487
    tb &= 0xFFFFFFFF00000000ULL;
488
    cpu_ppc_store_tb(tb_env, &tb_env->tb_offset, tb | (uint64_t)value);
489
}
490

    
491
static inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
492
{
493
    ppc_tb_t *tb_env = env->tb_env;
494
    uint64_t tb;
495

    
496
    tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset);
497
    tb &= 0x00000000FFFFFFFFULL;
498
    cpu_ppc_store_tb(tb_env, &tb_env->tb_offset,
499
                     ((uint64_t)value << 32) | tb);
500
}
501

    
502
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
503
{
504
    _cpu_ppc_store_tbu(env, value);
505
}
506

    
507
uint32_t cpu_ppc_load_atbl (CPUState *env)
508
{
509
    ppc_tb_t *tb_env = env->tb_env;
510
    uint64_t tb;
511

    
512
    tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset);
513
#if defined(PPC_DEBUG_TB)
514
    if (loglevel != 0) {
515
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
516
    }
517
#endif
518

    
519
    return tb & 0xFFFFFFFF;
520
}
521

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

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

    
534
    return tb >> 32;
535
}
536

    
537
void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
538
{
539
    ppc_tb_t *tb_env = env->tb_env;
540
    uint64_t tb;
541

    
542
    tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset);
543
    tb &= 0xFFFFFFFF00000000ULL;
544
    cpu_ppc_store_tb(tb_env, &tb_env->atb_offset, tb | (uint64_t)value);
545
}
546

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

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

    
558
static inline uint32_t _cpu_ppc_load_decr (CPUState *env, uint64_t *next)
559
{
560
    ppc_tb_t *tb_env = env->tb_env;
561
    uint32_t decr;
562
    int64_t diff;
563

    
564
    diff = tb_env->decr_next - qemu_get_clock(vm_clock);
565
    if (diff >= 0)
566
        decr = muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
567
    else
568
        decr = -muldiv64(-diff, tb_env->tb_freq, ticks_per_sec);
569
#if defined(PPC_DEBUG_TB)
570
    if (loglevel != 0) {
571
        fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
572
    }
573
#endif
574

    
575
    return decr;
576
}
577

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

    
582
    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
583
}
584

    
585
#if defined(TARGET_PPC64H)
586
uint32_t cpu_ppc_load_hdecr (CPUState *env)
587
{
588
    ppc_tb_t *tb_env = env->tb_env;
589

    
590
    return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
591
}
592

    
593
uint64_t cpu_ppc_load_purr (CPUState *env)
594
{
595
    ppc_tb_t *tb_env = env->tb_env;
596
    uint64_t diff;
597

    
598
    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
599
    
600
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
601
}
602
#endif /* defined(TARGET_PPC64H) */
603

    
604
/* When decrementer expires,
605
 * all we need to do is generate or queue a CPU exception
606
 */
607
static inline void cpu_ppc_decr_excp (CPUState *env)
608
{
609
    /* Raise it */
610
#ifdef PPC_DEBUG_TB
611
    if (loglevel != 0) {
612
        fprintf(logfile, "raise decrementer exception\n");
613
    }
614
#endif
615
    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
616
}
617

    
618
static inline void cpu_ppc_hdecr_excp (CPUState *env)
619
{
620
    /* Raise it */
621
#ifdef PPC_DEBUG_TB
622
    if (loglevel != 0) {
623
        fprintf(logfile, "raise decrementer exception\n");
624
    }
625
#endif
626
    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
627
}
628

    
629
static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
630
                                 struct QEMUTimer *timer,
631
                                 void (*raise_excp)(CPUState *),
632
                                 uint32_t decr, uint32_t value,
633
                                 int is_excp)
634
{
635
    ppc_tb_t *tb_env = env->tb_env;
636
    uint64_t now, next;
637

    
638
#ifdef PPC_DEBUG_TB
639
    if (loglevel != 0) {
640
        fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
641
    }
642
#endif
643
    now = qemu_get_clock(vm_clock);
644
    next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
645
    if (is_excp)
646
        next += *nextp - now;
647
    if (next == now)
648
        next++;
649
    *nextp = next;
650
    /* Adjust timer */
651
    qemu_mod_timer(timer, next);
652
    /* If we set a negative value and the decrementer was positive,
653
     * raise an exception.
654
     */
655
    if ((value & 0x80000000) && !(decr & 0x80000000))
656
        (*raise_excp)(env);
657
}
658

    
659

    
660
static inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
661
                                        uint32_t value, int is_excp)
662
{
663
    ppc_tb_t *tb_env = env->tb_env;
664

    
665
    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
666
                         &cpu_ppc_decr_excp, decr, value, is_excp);
667
}
668

    
669
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
670
{
671
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
672
}
673

    
674
static void cpu_ppc_decr_cb (void *opaque)
675
{
676
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
677
}
678

    
679
#if defined(TARGET_PPC64H)
680
static inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
681
                                        uint32_t value, int is_excp)
682
{
683
    ppc_tb_t *tb_env = env->tb_env;
684

    
685
    __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
686
                         &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
687
}
688

    
689
void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
690
{
691
    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
692
}
693

    
694
static void cpu_ppc_hdecr_cb (void *opaque)
695
{
696
    _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
697
}
698

    
699
void cpu_ppc_store_purr (CPUState *env, uint64_t value)
700
{
701
    ppc_tb_t *tb_env = env->tb_env;
702

    
703
    tb_env->purr_load = value;
704
    tb_env->purr_start = qemu_get_clock(vm_clock);
705
}
706
#endif /* defined(TARGET_PPC64H) */
707

    
708
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
709
{
710
    CPUState *env = opaque;
711
    ppc_tb_t *tb_env = env->tb_env;
712

    
713
    tb_env->tb_freq = freq;
714
    /* There is a bug in Linux 2.4 kernels:
715
     * if a decrementer exception is pending when it enables msr_ee at startup,
716
     * it's not ready to handle it...
717
     */
718
    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
719
#if defined(TARGET_PPC64H)
720
    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
721
    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
722
#endif /* defined(TARGET_PPC64H) */
723
}
724

    
725
/* Set up (once) timebase frequency (in Hz) */
726
clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
727
{
728
    ppc_tb_t *tb_env;
729

    
730
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
731
    if (tb_env == NULL)
732
        return NULL;
733
    env->tb_env = tb_env;
734
    /* Create new timer */
735
    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
736
#if defined(TARGET_PPC64H)
737
    tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
738
#endif /* defined(TARGET_PPC64H) */
739
    cpu_ppc_set_tb_clk(env, freq);
740

    
741
    return &cpu_ppc_set_tb_clk;
742
}
743

    
744
/* Specific helpers for POWER & PowerPC 601 RTC */
745
clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
746
{
747
    return cpu_ppc_tb_init(env, 7812500);
748
}
749

    
750
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
751
{
752
    _cpu_ppc_store_tbu(env, value);
753
}
754

    
755
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
756
{
757
    return _cpu_ppc_load_tbu(env);
758
}
759

    
760
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
761
{
762
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
763
}
764

    
765
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
766
{
767
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
768
}
769

    
770
/*****************************************************************************/
771
/* Embedded PowerPC timers */
772

    
773
/* PIT, FIT & WDT */
774
typedef struct ppcemb_timer_t ppcemb_timer_t;
775
struct ppcemb_timer_t {
776
    uint64_t pit_reload;  /* PIT auto-reload value        */
777
    uint64_t fit_next;    /* Tick for next FIT interrupt  */
778
    struct QEMUTimer *fit_timer;
779
    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
780
    struct QEMUTimer *wdt_timer;
781
};
782

    
783
/* Fixed interval timer */
784
static void cpu_4xx_fit_cb (void *opaque)
785
{
786
    CPUState *env;
787
    ppc_tb_t *tb_env;
788
    ppcemb_timer_t *ppcemb_timer;
789
    uint64_t now, next;
790

    
791
    env = opaque;
792
    tb_env = env->tb_env;
793
    ppcemb_timer = tb_env->opaque;
794
    now = qemu_get_clock(vm_clock);
795
    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
796
    case 0:
797
        next = 1 << 9;
798
        break;
799
    case 1:
800
        next = 1 << 13;
801
        break;
802
    case 2:
803
        next = 1 << 17;
804
        break;
805
    case 3:
806
        next = 1 << 21;
807
        break;
808
    default:
809
        /* Cannot occur, but makes gcc happy */
810
        return;
811
    }
812
    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
813
    if (next == now)
814
        next++;
815
    qemu_mod_timer(ppcemb_timer->fit_timer, next);
816
    env->spr[SPR_40x_TSR] |= 1 << 26;
817
    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
818
        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
819
#ifdef PPC_DEBUG_TB
820
    if (loglevel != 0) {
821
        fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
822
                (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
823
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
824
    }
825
#endif
826
}
827

    
828
/* Programmable interval timer */
829
static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
830
{
831
    ppcemb_timer_t *ppcemb_timer;
832
    uint64_t now, next;
833

    
834
    ppcemb_timer = tb_env->opaque;
835
    if (ppcemb_timer->pit_reload <= 1 ||
836
        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
837
        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
838
        /* Stop PIT */
839
#ifdef PPC_DEBUG_TB
840
        if (loglevel != 0) {
841
            fprintf(logfile, "%s: stop PIT\n", __func__);
842
        }
843
#endif
844
        qemu_del_timer(tb_env->decr_timer);
845
    } else {
846
#ifdef PPC_DEBUG_TB
847
        if (loglevel != 0) {
848
            fprintf(logfile, "%s: start PIT 0x" REGX "\n",
849
                    __func__, ppcemb_timer->pit_reload);
850
        }
851
#endif
852
        now = qemu_get_clock(vm_clock);
853
        next = now + muldiv64(ppcemb_timer->pit_reload,
854
                              ticks_per_sec, tb_env->tb_freq);
855
        if (is_excp)
856
            next += tb_env->decr_next - now;
857
        if (next == now)
858
            next++;
859
        qemu_mod_timer(tb_env->decr_timer, next);
860
        tb_env->decr_next = next;
861
    }
862
}
863

    
864
static void cpu_4xx_pit_cb (void *opaque)
865
{
866
    CPUState *env;
867
    ppc_tb_t *tb_env;
868
    ppcemb_timer_t *ppcemb_timer;
869

    
870
    env = opaque;
871
    tb_env = env->tb_env;
872
    ppcemb_timer = tb_env->opaque;
873
    env->spr[SPR_40x_TSR] |= 1 << 27;
874
    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
875
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
876
    start_stop_pit(env, tb_env, 1);
877
#ifdef PPC_DEBUG_TB
878
    if (loglevel != 0) {
879
        fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
880
                "%016" PRIx64 "\n", __func__,
881
                (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
882
                (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
883
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
884
                ppcemb_timer->pit_reload);
885
    }
886
#endif
887
}
888

    
889
/* Watchdog timer */
890
static void cpu_4xx_wdt_cb (void *opaque)
891
{
892
    CPUState *env;
893
    ppc_tb_t *tb_env;
894
    ppcemb_timer_t *ppcemb_timer;
895
    uint64_t now, next;
896

    
897
    env = opaque;
898
    tb_env = env->tb_env;
899
    ppcemb_timer = tb_env->opaque;
900
    now = qemu_get_clock(vm_clock);
901
    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
902
    case 0:
903
        next = 1 << 17;
904
        break;
905
    case 1:
906
        next = 1 << 21;
907
        break;
908
    case 2:
909
        next = 1 << 25;
910
        break;
911
    case 3:
912
        next = 1 << 29;
913
        break;
914
    default:
915
        /* Cannot occur, but makes gcc happy */
916
        return;
917
    }
918
    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
919
    if (next == now)
920
        next++;
921
#ifdef PPC_DEBUG_TB
922
    if (loglevel != 0) {
923
        fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
924
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
925
    }
926
#endif
927
    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
928
    case 0x0:
929
    case 0x1:
930
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
931
        ppcemb_timer->wdt_next = next;
932
        env->spr[SPR_40x_TSR] |= 1 << 31;
933
        break;
934
    case 0x2:
935
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
936
        ppcemb_timer->wdt_next = next;
937
        env->spr[SPR_40x_TSR] |= 1 << 30;
938
        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
939
            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
940
        break;
941
    case 0x3:
942
        env->spr[SPR_40x_TSR] &= ~0x30000000;
943
        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
944
        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
945
        case 0x0:
946
            /* No reset */
947
            break;
948
        case 0x1: /* Core reset */
949
            ppc40x_core_reset(env);
950
            break;
951
        case 0x2: /* Chip reset */
952
            ppc40x_chip_reset(env);
953
            break;
954
        case 0x3: /* System reset */
955
            ppc40x_system_reset(env);
956
            break;
957
        }
958
    }
959
}
960

    
961
void store_40x_pit (CPUState *env, target_ulong val)
962
{
963
    ppc_tb_t *tb_env;
964
    ppcemb_timer_t *ppcemb_timer;
965

    
966
    tb_env = env->tb_env;
967
    ppcemb_timer = tb_env->opaque;
968
#ifdef PPC_DEBUG_TB
969
    if (loglevel != 0) {
970
        fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
971
    }
972
#endif
973
    ppcemb_timer->pit_reload = val;
974
    start_stop_pit(env, tb_env, 0);
975
}
976

    
977
target_ulong load_40x_pit (CPUState *env)
978
{
979
    return cpu_ppc_load_decr(env);
980
}
981

    
982
void store_booke_tsr (CPUState *env, target_ulong val)
983
{
984
#ifdef PPC_DEBUG_TB
985
    if (loglevel != 0) {
986
        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
987
    }
988
#endif
989
    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
990
    if (val & 0x80000000)
991
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
992
}
993

    
994
void store_booke_tcr (CPUState *env, target_ulong val)
995
{
996
    ppc_tb_t *tb_env;
997

    
998
    tb_env = env->tb_env;
999
#ifdef PPC_DEBUG_TB
1000
    if (loglevel != 0) {
1001
        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1002
    }
1003
#endif
1004
    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1005
    start_stop_pit(env, tb_env, 1);
1006
    cpu_4xx_wdt_cb(env);
1007
}
1008

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

    
1014
#ifdef PPC_DEBUG_TB
1015
    if (loglevel != 0) {
1016
        fprintf(logfile, "%s set new frequency to %u\n", __func__, freq);
1017
    }
1018
#endif
1019
    tb_env->tb_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
{
1025
    ppc_tb_t *tb_env;
1026
    ppcemb_timer_t *ppcemb_timer;
1027

    
1028
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
1029
    if (tb_env == NULL) {
1030
        return NULL;
1031
    }
1032
    env->tb_env = tb_env;
1033
    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
1034
    tb_env->tb_freq = freq;
1035
    tb_env->opaque = ppcemb_timer;
1036
#ifdef PPC_DEBUG_TB
1037
    if (loglevel != 0) {
1038
        fprintf(logfile, "%s %p %p %p\n", __func__, tb_env, ppcemb_timer,
1039
                &ppc_emb_set_tb_clk);
1040
    }
1041
#endif
1042
    if (ppcemb_timer != NULL) {
1043
        /* We use decr timer for PIT */
1044
        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
1045
        ppcemb_timer->fit_timer =
1046
            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
1047
        ppcemb_timer->wdt_timer =
1048
            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
1049
    }
1050

    
1051
    return &ppc_emb_set_tb_clk;
1052
}
1053

    
1054
/*****************************************************************************/
1055
/* Embedded PowerPC Device Control Registers */
1056
typedef struct ppc_dcrn_t ppc_dcrn_t;
1057
struct ppc_dcrn_t {
1058
    dcr_read_cb dcr_read;
1059
    dcr_write_cb dcr_write;
1060
    void *opaque;
1061
};
1062

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

    
1073
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1074
{
1075
    ppc_dcrn_t *dcr;
1076

    
1077
    if (dcrn < 0 || dcrn >= DCRN_NB)
1078
        goto error;
1079
    dcr = &dcr_env->dcrn[dcrn];
1080
    if (dcr->dcr_read == NULL)
1081
        goto error;
1082
    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1083

    
1084
    return 0;
1085

    
1086
 error:
1087
    if (dcr_env->read_error != NULL)
1088
        return (*dcr_env->read_error)(dcrn);
1089

    
1090
    return -1;
1091
}
1092

    
1093
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1094
{
1095
    ppc_dcrn_t *dcr;
1096

    
1097
    if (dcrn < 0 || dcrn >= DCRN_NB)
1098
        goto error;
1099
    dcr = &dcr_env->dcrn[dcrn];
1100
    if (dcr->dcr_write == NULL)
1101
        goto error;
1102
    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1103

    
1104
    return 0;
1105

    
1106
 error:
1107
    if (dcr_env->write_error != NULL)
1108
        return (*dcr_env->write_error)(dcrn);
1109

    
1110
    return -1;
1111
}
1112

    
1113
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1114
                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1115
{
1116
    ppc_dcr_t *dcr_env;
1117
    ppc_dcrn_t *dcr;
1118

    
1119
    dcr_env = env->dcr_env;
1120
    if (dcr_env == NULL)
1121
        return -1;
1122
    if (dcrn < 0 || dcrn >= DCRN_NB)
1123
        return -1;
1124
    dcr = &dcr_env->dcrn[dcrn];
1125
    if (dcr->opaque != NULL ||
1126
        dcr->dcr_read != NULL ||
1127
        dcr->dcr_write != NULL)
1128
        return -1;
1129
    dcr->opaque = opaque;
1130
    dcr->dcr_read = dcr_read;
1131
    dcr->dcr_write = dcr_write;
1132

    
1133
    return 0;
1134
}
1135

    
1136
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1137
                  int (*write_error)(int dcrn))
1138
{
1139
    ppc_dcr_t *dcr_env;
1140

    
1141
    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1142
    if (dcr_env == NULL)
1143
        return -1;
1144
    dcr_env->read_error = read_error;
1145
    dcr_env->write_error = write_error;
1146
    env->dcr_env = dcr_env;
1147

    
1148
    return 0;
1149
}
1150

    
1151

    
1152
#if 0
1153
/*****************************************************************************/
1154
/* Handle system reset (for now, just stop emulation) */
1155
void cpu_ppc_reset (CPUState *env)
1156
{
1157
    printf("Reset asked... Stop emulation\n");
1158
    abort();
1159
}
1160
#endif
1161

    
1162
/*****************************************************************************/
1163
/* Debug port */
1164
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1165
{
1166
    addr &= 0xF;
1167
    switch (addr) {
1168
    case 0:
1169
        printf("%c", val);
1170
        break;
1171
    case 1:
1172
        printf("\n");
1173
        fflush(stdout);
1174
        break;
1175
    case 2:
1176
        printf("Set loglevel to %04x\n", val);
1177
        cpu_set_log(val | 0x100);
1178
        break;
1179
    }
1180
}
1181

    
1182
/*****************************************************************************/
1183
/* NVRAM helpers */
1184
void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
1185
{
1186
    m48t59_write(nvram, addr, value);
1187
}
1188

    
1189
uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
1190
{
1191
    return m48t59_read(nvram, addr);
1192
}
1193

    
1194
void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
1195
{
1196
    m48t59_write(nvram, addr, value >> 8);
1197
    m48t59_write(nvram, addr + 1, value & 0xFF);
1198
}
1199

    
1200
uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
1201
{
1202
    uint16_t tmp;
1203

    
1204
    tmp = m48t59_read(nvram, addr) << 8;
1205
    tmp |= m48t59_read(nvram, addr + 1);
1206
    return tmp;
1207
}
1208

    
1209
void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
1210
{
1211
    m48t59_write(nvram, addr, value >> 24);
1212
    m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
1213
    m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
1214
    m48t59_write(nvram, addr + 3, value & 0xFF);
1215
}
1216

    
1217
uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
1218
{
1219
    uint32_t tmp;
1220

    
1221
    tmp = m48t59_read(nvram, addr) << 24;
1222
    tmp |= m48t59_read(nvram, addr + 1) << 16;
1223
    tmp |= m48t59_read(nvram, addr + 2) << 8;
1224
    tmp |= m48t59_read(nvram, addr + 3);
1225

    
1226
    return tmp;
1227
}
1228

    
1229
void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
1230
                       const unsigned char *str, uint32_t max)
1231
{
1232
    int i;
1233

    
1234
    for (i = 0; i < max && str[i] != '\0'; i++) {
1235
        m48t59_write(nvram, addr + i, str[i]);
1236
    }
1237
    m48t59_write(nvram, addr + max - 1, '\0');
1238
}
1239

    
1240
int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
1241
{
1242
    int i;
1243

    
1244
    memset(dst, 0, max);
1245
    for (i = 0; i < max; i++) {
1246
        dst[i] = NVRAM_get_byte(nvram, addr + i);
1247
        if (dst[i] == '\0')
1248
            break;
1249
    }
1250

    
1251
    return i;
1252
}
1253

    
1254
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1255
{
1256
    uint16_t tmp;
1257
    uint16_t pd, pd1, pd2;
1258

    
1259
    tmp = prev >> 8;
1260
    pd = prev ^ value;
1261
    pd1 = pd & 0x000F;
1262
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1263
    tmp ^= (pd1 << 3) | (pd1 << 8);
1264
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1265

    
1266
    return tmp;
1267
}
1268

    
1269
uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
1270
{
1271
    uint32_t i;
1272
    uint16_t crc = 0xFFFF;
1273
    int odd;
1274

    
1275
    odd = count & 1;
1276
    count &= ~1;
1277
    for (i = 0; i != count; i++) {
1278
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1279
    }
1280
    if (odd) {
1281
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1282
    }
1283

    
1284
    return crc;
1285
}
1286

    
1287
#define CMDLINE_ADDR 0x017ff000
1288

    
1289
int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
1290
                          const unsigned char *arch,
1291
                          uint32_t RAM_size, int boot_device,
1292
                          uint32_t kernel_image, uint32_t kernel_size,
1293
                          const char *cmdline,
1294
                          uint32_t initrd_image, uint32_t initrd_size,
1295
                          uint32_t NVRAM_image,
1296
                          int width, int height, int depth)
1297
{
1298
    uint16_t crc;
1299

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

    
1322
    NVRAM_set_word(nvram,   0x54, width);
1323
    NVRAM_set_word(nvram,   0x56, height);
1324
    NVRAM_set_word(nvram,   0x58, depth);
1325
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1326
    NVRAM_set_word(nvram,  0xFC, crc);
1327

    
1328
    return 0;
1329
}