a25a3607f31a872df2a27c6f04a05f0abc428574
[qemu] / hw / ppc.c
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
26 //#define PPC_DEBUG_IRQ
27 //#define PPC_DEBUG_TB
28
29 extern FILE *logfile;
30 extern int loglevel;
31
32 static void cpu_ppc_tb_stop (CPUState *env);
33 static void cpu_ppc_tb_start (CPUState *env);
34
35 static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
36 {
37     if (level) {
38         env->pending_interrupts |= 1 << n_IRQ;
39         cpu_interrupt(env, CPU_INTERRUPT_HARD);
40     } else {
41         env->pending_interrupts &= ~(1 << n_IRQ);
42         if (env->pending_interrupts == 0)
43             cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
44     }
45 #if defined(PPC_DEBUG_IRQ)
46     if (loglevel & CPU_LOG_INT) {
47         fprintf(logfile, "%s: %p n_IRQ %d level %d => pending %08x req %08x\n",
48                 __func__, env, n_IRQ, level,
49                 env->pending_interrupts, env->interrupt_request);
50     }
51 #endif
52 }
53
54 /* PowerPC 6xx / 7xx internal IRQ controller */
55 static void ppc6xx_set_irq (void *opaque, int pin, int level)
56 {
57     CPUState *env = opaque;
58     int cur_level;
59
60 #if defined(PPC_DEBUG_IRQ)
61     if (loglevel & CPU_LOG_INT) {
62         fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
63                 env, pin, level);
64     }
65 #endif
66     cur_level = (env->irq_input_state >> pin) & 1;
67     /* Don't generate spurious events */
68     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
69         switch (pin) {
70         case PPC6xx_INPUT_TBEN:
71             /* Level sensitive - active high */
72 #if defined(PPC_DEBUG_IRQ)
73             if (loglevel & CPU_LOG_INT) {
74                 fprintf(logfile, "%s: %s the time base\n",
75                         __func__, level ? "start" : "stop");
76             }
77 #endif
78             if (level) {
79                 cpu_ppc_tb_start(env);
80             } else {
81                 cpu_ppc_tb_stop(env);
82             }
83         case PPC6xx_INPUT_INT:
84             /* Level sensitive - active high */
85 #if defined(PPC_DEBUG_IRQ)
86             if (loglevel & CPU_LOG_INT) {
87                 fprintf(logfile, "%s: set the external IRQ state to %d\n",
88                         __func__, level);
89             }
90 #endif
91             ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
92             break;
93         case PPC6xx_INPUT_SMI:
94             /* Level sensitive - active high */
95 #if defined(PPC_DEBUG_IRQ)
96             if (loglevel & CPU_LOG_INT) {
97                 fprintf(logfile, "%s: set the SMI IRQ state to %d\n",
98                         __func__, level);
99             }
100 #endif
101             ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
102             break;
103         case PPC6xx_INPUT_MCP:
104             /* Negative edge sensitive */
105             /* XXX: TODO: actual reaction may depends on HID0 status
106              *            603/604/740/750: check HID0[EMCP]
107              */
108             if (cur_level == 1 && level == 0) {
109 #if defined(PPC_DEBUG_IRQ)
110                 if (loglevel & CPU_LOG_INT) {
111                     fprintf(logfile, "%s: raise machine check state\n",
112                             __func__);
113                 }
114 #endif
115                 ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
116             }
117             break;
118         case PPC6xx_INPUT_CKSTP_IN:
119             /* Level sensitive - active low */
120             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
121             /* XXX: Note that the only way to restart the CPU is to reset it */
122             if (level) {
123 #if defined(PPC_DEBUG_IRQ)
124                 if (loglevel & CPU_LOG_INT) {
125                     fprintf(logfile, "%s: stop the CPU\n", __func__);
126                 }
127 #endif
128                 env->halted = 1;
129             }
130             break;
131         case PPC6xx_INPUT_HRESET:
132             /* Level sensitive - active low */
133             if (level) {
134 #if defined(PPC_DEBUG_IRQ)
135                 if (loglevel & CPU_LOG_INT) {
136                     fprintf(logfile, "%s: reset the CPU\n", __func__);
137                 }
138 #endif
139                 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
140                 /* XXX: TOFIX */
141 #if 0
142                 cpu_ppc_reset(env);
143 #else
144                 qemu_system_reset_request();
145 #endif
146             }
147             break;
148         case PPC6xx_INPUT_SRESET:
149 #if defined(PPC_DEBUG_IRQ)
150             if (loglevel & CPU_LOG_INT) {
151                 fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
152                         __func__, level);
153             }
154 #endif
155             ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
156             break;
157         default:
158             /* Unknown pin - do nothing */
159 #if defined(PPC_DEBUG_IRQ)
160             if (loglevel & CPU_LOG_INT) {
161                 fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
162             }
163 #endif
164             return;
165         }
166         if (level)
167             env->irq_input_state |= 1 << pin;
168         else
169             env->irq_input_state &= ~(1 << pin);
170     }
171 }
172
173 void ppc6xx_irq_init (CPUState *env)
174 {
175     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
176                                                   PPC6xx_INPUT_NB);
177 }
178
179 #if defined(TARGET_PPC64)
180 /* PowerPC 970 internal IRQ controller */
181 static void ppc970_set_irq (void *opaque, int pin, int level)
182 {
183     CPUState *env = opaque;
184     int cur_level;
185
186 #if defined(PPC_DEBUG_IRQ)
187     if (loglevel & CPU_LOG_INT) {
188         fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
189                 env, pin, level);
190     }
191 #endif
192     cur_level = (env->irq_input_state >> pin) & 1;
193     /* Don't generate spurious events */
194     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
195         switch (pin) {
196         case PPC970_INPUT_INT:
197             /* Level sensitive - active high */
198 #if defined(PPC_DEBUG_IRQ)
199             if (loglevel & CPU_LOG_INT) {
200                 fprintf(logfile, "%s: set the external IRQ state to %d\n",
201                         __func__, level);
202             }
203 #endif
204             ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
205             break;
206         case PPC970_INPUT_THINT:
207             /* Level sensitive - active high */
208 #if defined(PPC_DEBUG_IRQ)
209             if (loglevel & CPU_LOG_INT) {
210                 fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
211                         level);
212             }
213 #endif
214             ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
215             break;
216         case PPC970_INPUT_MCP:
217             /* Negative edge sensitive */
218             /* XXX: TODO: actual reaction may depends on HID0 status
219              *            603/604/740/750: check HID0[EMCP]
220              */
221             if (cur_level == 1 && level == 0) {
222 #if defined(PPC_DEBUG_IRQ)
223                 if (loglevel & CPU_LOG_INT) {
224                     fprintf(logfile, "%s: raise machine check state\n",
225                             __func__);
226                 }
227 #endif
228                 ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
229             }
230             break;
231         case PPC970_INPUT_CKSTP:
232             /* Level sensitive - active low */
233             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
234             if (level) {
235 #if defined(PPC_DEBUG_IRQ)
236                 if (loglevel & CPU_LOG_INT) {
237                     fprintf(logfile, "%s: stop the CPU\n", __func__);
238                 }
239 #endif
240                 env->halted = 1;
241             } else {
242 #if defined(PPC_DEBUG_IRQ)
243                 if (loglevel & CPU_LOG_INT) {
244                     fprintf(logfile, "%s: restart the CPU\n", __func__);
245                 }
246 #endif
247                 env->halted = 0;
248             }
249             break;
250         case PPC970_INPUT_HRESET:
251             /* Level sensitive - active low */
252             if (level) {
253 #if 0 // XXX: TOFIX
254 #if defined(PPC_DEBUG_IRQ)
255                 if (loglevel & CPU_LOG_INT) {
256                     fprintf(logfile, "%s: reset the CPU\n", __func__);
257                 }
258 #endif
259                 cpu_reset(env);
260 #endif
261             }
262             break;
263         case PPC970_INPUT_SRESET:
264 #if defined(PPC_DEBUG_IRQ)
265             if (loglevel & CPU_LOG_INT) {
266                 fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
267                         __func__, level);
268             }
269 #endif
270             ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
271             break;
272         case PPC970_INPUT_TBEN:
273 #if defined(PPC_DEBUG_IRQ)
274             if (loglevel & CPU_LOG_INT) {
275                 fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
276                         level);
277             }
278 #endif
279             /* XXX: TODO */
280             break;
281         default:
282             /* Unknown pin - do nothing */
283 #if defined(PPC_DEBUG_IRQ)
284             if (loglevel & CPU_LOG_INT) {
285                 fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
286             }
287 #endif
288             return;
289         }
290         if (level)
291             env->irq_input_state |= 1 << pin;
292         else
293             env->irq_input_state &= ~(1 << pin);
294     }
295 }
296
297 void ppc970_irq_init (CPUState *env)
298 {
299     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
300                                                   PPC970_INPUT_NB);
301 }
302 #endif /* defined(TARGET_PPC64) */
303
304 /* PowerPC 40x internal IRQ controller */
305 static void ppc40x_set_irq (void *opaque, int pin, int level)
306 {
307     CPUState *env = opaque;
308     int cur_level;
309
310 #if defined(PPC_DEBUG_IRQ)
311     if (loglevel & CPU_LOG_INT) {
312         fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
313                 env, pin, level);
314     }
315 #endif
316     cur_level = (env->irq_input_state >> pin) & 1;
317     /* Don't generate spurious events */
318     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
319         switch (pin) {
320         case PPC40x_INPUT_RESET_SYS:
321             if (level) {
322 #if defined(PPC_DEBUG_IRQ)
323                 if (loglevel & CPU_LOG_INT) {
324                     fprintf(logfile, "%s: reset the PowerPC system\n",
325                             __func__);
326                 }
327 #endif
328                 ppc40x_system_reset(env);
329             }
330             break;
331         case PPC40x_INPUT_RESET_CHIP:
332             if (level) {
333 #if defined(PPC_DEBUG_IRQ)
334                 if (loglevel & CPU_LOG_INT) {
335                     fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
336                 }
337 #endif
338                 ppc40x_chip_reset(env);
339             }
340             break;
341         case PPC40x_INPUT_RESET_CORE:
342             /* XXX: TODO: update DBSR[MRR] */
343             if (level) {
344 #if defined(PPC_DEBUG_IRQ)
345                 if (loglevel & CPU_LOG_INT) {
346                     fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
347                 }
348 #endif
349                 ppc40x_core_reset(env);
350             }
351             break;
352         case PPC40x_INPUT_CINT:
353             /* Level sensitive - active high */
354 #if defined(PPC_DEBUG_IRQ)
355             if (loglevel & CPU_LOG_INT) {
356                 fprintf(logfile, "%s: set the critical IRQ state to %d\n",
357                         __func__, level);
358             }
359 #endif
360             ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
361             break;
362         case PPC40x_INPUT_INT:
363             /* Level sensitive - active high */
364 #if defined(PPC_DEBUG_IRQ)
365             if (loglevel & CPU_LOG_INT) {
366                 fprintf(logfile, "%s: set the external IRQ state to %d\n",
367                         __func__, level);
368             }
369 #endif
370             ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
371             break;
372         case PPC40x_INPUT_HALT:
373             /* Level sensitive - active low */
374             if (level) {
375 #if defined(PPC_DEBUG_IRQ)
376                 if (loglevel & CPU_LOG_INT) {
377                     fprintf(logfile, "%s: stop the CPU\n", __func__);
378                 }
379 #endif
380                 env->halted = 1;
381             } else {
382 #if defined(PPC_DEBUG_IRQ)
383                 if (loglevel & CPU_LOG_INT) {
384                     fprintf(logfile, "%s: restart the CPU\n", __func__);
385                 }
386 #endif
387                 env->halted = 0;
388             }
389             break;
390         case PPC40x_INPUT_DEBUG:
391             /* Level sensitive - active high */
392 #if defined(PPC_DEBUG_IRQ)
393             if (loglevel & CPU_LOG_INT) {
394                 fprintf(logfile, "%s: set the debug pin state to %d\n",
395                         __func__, level);
396             }
397 #endif
398             ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
399             break;
400         default:
401             /* Unknown pin - do nothing */
402 #if defined(PPC_DEBUG_IRQ)
403             if (loglevel & CPU_LOG_INT) {
404                 fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
405             }
406 #endif
407             return;
408         }
409         if (level)
410             env->irq_input_state |= 1 << pin;
411         else
412             env->irq_input_state &= ~(1 << pin);
413     }
414 }
415
416 void ppc40x_irq_init (CPUState *env)
417 {
418     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
419                                                   env, PPC40x_INPUT_NB);
420 }
421
422 /*****************************************************************************/
423 /* PowerPC time base and decrementer emulation */
424 struct ppc_tb_t {
425     /* Time base management */
426     int64_t  tb_offset;    /* Compensation                    */
427     int64_t  atb_offset;   /* Compensation                    */
428     uint32_t tb_freq;      /* TB frequency                    */
429     /* Decrementer management */
430     uint64_t decr_next;    /* Tick for next decr interrupt    */
431     uint32_t decr_freq;    /* decrementer frequency           */
432     struct QEMUTimer *decr_timer;
433     /* Hypervisor decrementer management */
434     uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
435     struct QEMUTimer *hdecr_timer;
436     uint64_t purr_load;
437     uint64_t purr_start;
438     void *opaque;
439 };
440
441 static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
442                                               int64_t tb_offset)
443 {
444     /* TB time in tb periods */
445     return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
446 }
447
448 uint32_t cpu_ppc_load_tbl (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, qemu_get_clock(vm_clock), 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 & 0xFFFFFFFF;
461 }
462
463 static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
464 {
465     ppc_tb_t *tb_env = env->tb_env;
466     uint64_t tb;
467
468     tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
469 #if defined(PPC_DEBUG_TB)
470     if (loglevel != 0) {
471         fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
472     }
473 #endif
474
475     return tb >> 32;
476 }
477
478 uint32_t cpu_ppc_load_tbu (CPUState *env)
479 {
480     return _cpu_ppc_load_tbu(env);
481 }
482
483 static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
484                                             int64_t *tb_offsetp,
485                                             uint64_t value)
486 {
487     *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
488 #ifdef PPC_DEBUG_TB
489     if (loglevel != 0) {
490         fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
491                 *tb_offsetp);
492     }
493 #endif
494 }
495
496 void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
497 {
498     ppc_tb_t *tb_env = env->tb_env;
499     uint64_t tb;
500
501     tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
502     tb &= 0xFFFFFFFF00000000ULL;
503     cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
504                      &tb_env->tb_offset, tb | (uint64_t)value);
505 }
506
507 static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
508 {
509     ppc_tb_t *tb_env = env->tb_env;
510     uint64_t tb;
511
512     tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
513     tb &= 0x00000000FFFFFFFFULL;
514     cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
515                      &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
516 }
517
518 void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
519 {
520     _cpu_ppc_store_tbu(env, value);
521 }
522
523 uint32_t cpu_ppc_load_atbl (CPUState *env)
524 {
525     ppc_tb_t *tb_env = env->tb_env;
526     uint64_t tb;
527
528     tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
529 #if defined(PPC_DEBUG_TB)
530     if (loglevel != 0) {
531         fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
532     }
533 #endif
534
535     return tb & 0xFFFFFFFF;
536 }
537
538 uint32_t cpu_ppc_load_atbu (CPUState *env)
539 {
540     ppc_tb_t *tb_env = env->tb_env;
541     uint64_t tb;
542
543     tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
544 #if defined(PPC_DEBUG_TB)
545     if (loglevel != 0) {
546         fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
547     }
548 #endif
549
550     return tb >> 32;
551 }
552
553 void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
554 {
555     ppc_tb_t *tb_env = env->tb_env;
556     uint64_t tb;
557
558     tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
559     tb &= 0xFFFFFFFF00000000ULL;
560     cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
561                      &tb_env->atb_offset, tb | (uint64_t)value);
562 }
563
564 void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
565 {
566     ppc_tb_t *tb_env = env->tb_env;
567     uint64_t tb;
568
569     tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
570     tb &= 0x00000000FFFFFFFFULL;
571     cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
572                      &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
573 }
574
575 static void cpu_ppc_tb_stop (CPUState *env)
576 {
577     ppc_tb_t *tb_env = env->tb_env;
578     uint64_t tb, atb, vmclk;
579
580     /* If the time base is already frozen, do nothing */
581     if (tb_env->tb_freq != 0) {
582         vmclk = qemu_get_clock(vm_clock);
583         /* Get the time base */
584         tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
585         /* Get the alternate time base */
586         atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
587         /* Store the time base value (ie compute the current offset) */
588         cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
589         /* Store the alternate time base value (compute the current offset) */
590         cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
591         /* Set the time base frequency to zero */
592         tb_env->tb_freq = 0;
593         /* Now, the time bases are frozen to tb_offset / atb_offset value */
594     }
595 }
596
597 static void cpu_ppc_tb_start (CPUState *env)
598 {
599     ppc_tb_t *tb_env = env->tb_env;
600     uint64_t tb, atb, vmclk;
601     
602     /* If the time base is not frozen, do nothing */
603     if (tb_env->tb_freq == 0) {
604         vmclk = qemu_get_clock(vm_clock);
605         /* Get the time base from tb_offset */
606         tb = tb_env->tb_offset;
607         /* Get the alternate time base from atb_offset */
608         atb = tb_env->atb_offset;
609         /* Restore the tb frequency from the decrementer frequency */
610         tb_env->tb_freq = tb_env->decr_freq;
611         /* Store the time base value */
612         cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
613         /* Store the alternate time base value */
614         cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
615     }
616 }
617
618 static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
619                                                   uint64_t *next)
620 {
621     ppc_tb_t *tb_env = env->tb_env;
622     uint32_t decr;
623     int64_t diff;
624
625     diff = tb_env->decr_next - qemu_get_clock(vm_clock);
626     if (diff >= 0)
627         decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
628     else
629         decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
630 #if defined(PPC_DEBUG_TB)
631     if (loglevel != 0) {
632         fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
633     }
634 #endif
635
636     return decr;
637 }
638
639 uint32_t cpu_ppc_load_decr (CPUState *env)
640 {
641     ppc_tb_t *tb_env = env->tb_env;
642
643     return _cpu_ppc_load_decr(env, &tb_env->decr_next);
644 }
645
646 uint32_t cpu_ppc_load_hdecr (CPUState *env)
647 {
648     ppc_tb_t *tb_env = env->tb_env;
649
650     return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
651 }
652
653 uint64_t cpu_ppc_load_purr (CPUState *env)
654 {
655     ppc_tb_t *tb_env = env->tb_env;
656     uint64_t diff;
657
658     diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
659
660     return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
661 }
662
663 /* When decrementer expires,
664  * all we need to do is generate or queue a CPU exception
665  */
666 static always_inline void cpu_ppc_decr_excp (CPUState *env)
667 {
668     /* Raise it */
669 #ifdef PPC_DEBUG_TB
670     if (loglevel != 0) {
671         fprintf(logfile, "raise decrementer exception\n");
672     }
673 #endif
674     ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
675 }
676
677 static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
678 {
679     /* Raise it */
680 #ifdef PPC_DEBUG_TB
681     if (loglevel != 0) {
682         fprintf(logfile, "raise decrementer exception\n");
683     }
684 #endif
685     ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
686 }
687
688 static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
689                                   struct QEMUTimer *timer,
690                                   void (*raise_excp)(CPUState *),
691                                   uint32_t decr, uint32_t value,
692                                   int is_excp)
693 {
694     ppc_tb_t *tb_env = env->tb_env;
695     uint64_t now, next;
696
697 #ifdef PPC_DEBUG_TB
698     if (loglevel != 0) {
699         fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
700     }
701 #endif
702     now = qemu_get_clock(vm_clock);
703     next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
704     if (is_excp)
705         next += *nextp - now;
706     if (next == now)
707         next++;
708     *nextp = next;
709     /* Adjust timer */
710     qemu_mod_timer(timer, next);
711     /* If we set a negative value and the decrementer was positive,
712      * raise an exception.
713      */
714     if ((value & 0x80000000) && !(decr & 0x80000000))
715         (*raise_excp)(env);
716 }
717
718 static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
719                                                uint32_t value, int is_excp)
720 {
721     ppc_tb_t *tb_env = env->tb_env;
722
723     __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
724                          &cpu_ppc_decr_excp, decr, value, is_excp);
725 }
726
727 void cpu_ppc_store_decr (CPUState *env, uint32_t value)
728 {
729     _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
730 }
731
732 static void cpu_ppc_decr_cb (void *opaque)
733 {
734     _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
735 }
736
737 static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
738                                                 uint32_t value, int is_excp)
739 {
740     ppc_tb_t *tb_env = env->tb_env;
741
742     if (tb_env->hdecr_timer != NULL) {
743         __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
744                              &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
745     }
746 }
747
748 void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
749 {
750     _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
751 }
752
753 static void cpu_ppc_hdecr_cb (void *opaque)
754 {
755     _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
756 }
757
758 void cpu_ppc_store_purr (CPUState *env, uint64_t value)
759 {
760     ppc_tb_t *tb_env = env->tb_env;
761
762     tb_env->purr_load = value;
763     tb_env->purr_start = qemu_get_clock(vm_clock);
764 }
765
766 static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
767 {
768     CPUState *env = opaque;
769     ppc_tb_t *tb_env = env->tb_env;
770
771     tb_env->tb_freq = freq;
772     tb_env->decr_freq = freq;
773     /* There is a bug in Linux 2.4 kernels:
774      * if a decrementer exception is pending when it enables msr_ee at startup,
775      * it's not ready to handle it...
776      */
777     _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
778     _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
779     cpu_ppc_store_purr(env, 0x0000000000000000ULL);
780 }
781
782 /* Set up (once) timebase frequency (in Hz) */
783 clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
784 {
785     ppc_tb_t *tb_env;
786
787     tb_env = qemu_mallocz(sizeof(ppc_tb_t));
788     if (tb_env == NULL)
789         return NULL;
790     env->tb_env = tb_env;
791     /* Create new timer */
792     tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
793     if (0) {
794         /* XXX: find a suitable condition to enable the hypervisor decrementer
795          */
796         tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
797     } else {
798         tb_env->hdecr_timer = NULL;
799     }
800     cpu_ppc_set_tb_clk(env, freq);
801
802     return &cpu_ppc_set_tb_clk;
803 }
804
805 /* Specific helpers for POWER & PowerPC 601 RTC */
806 clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
807 {
808     return cpu_ppc_tb_init(env, 7812500);
809 }
810
811 void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
812 {
813     _cpu_ppc_store_tbu(env, value);
814 }
815
816 uint32_t cpu_ppc601_load_rtcu (CPUState *env)
817 {
818     return _cpu_ppc_load_tbu(env);
819 }
820
821 void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
822 {
823     cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
824 }
825
826 uint32_t cpu_ppc601_load_rtcl (CPUState *env)
827 {
828     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
829 }
830
831 /*****************************************************************************/
832 /* Embedded PowerPC timers */
833
834 /* PIT, FIT & WDT */
835 typedef struct ppcemb_timer_t ppcemb_timer_t;
836 struct ppcemb_timer_t {
837     uint64_t pit_reload;  /* PIT auto-reload value        */
838     uint64_t fit_next;    /* Tick for next FIT interrupt  */
839     struct QEMUTimer *fit_timer;
840     uint64_t wdt_next;    /* Tick for next WDT interrupt  */
841     struct QEMUTimer *wdt_timer;
842 };
843
844 /* Fixed interval timer */
845 static void cpu_4xx_fit_cb (void *opaque)
846 {
847     CPUState *env;
848     ppc_tb_t *tb_env;
849     ppcemb_timer_t *ppcemb_timer;
850     uint64_t now, next;
851
852     env = opaque;
853     tb_env = env->tb_env;
854     ppcemb_timer = tb_env->opaque;
855     now = qemu_get_clock(vm_clock);
856     switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
857     case 0:
858         next = 1 << 9;
859         break;
860     case 1:
861         next = 1 << 13;
862         break;
863     case 2:
864         next = 1 << 17;
865         break;
866     case 3:
867         next = 1 << 21;
868         break;
869     default:
870         /* Cannot occur, but makes gcc happy */
871         return;
872     }
873     next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
874     if (next == now)
875         next++;
876     qemu_mod_timer(ppcemb_timer->fit_timer, next);
877     env->spr[SPR_40x_TSR] |= 1 << 26;
878     if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
879         ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
880 #ifdef PPC_DEBUG_TB
881     if (loglevel != 0) {
882         fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
883                 (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
884                 env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
885     }
886 #endif
887 }
888
889 /* Programmable interval timer */
890 static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
891 {
892     ppcemb_timer_t *ppcemb_timer;
893     uint64_t now, next;
894
895     ppcemb_timer = tb_env->opaque;
896     if (ppcemb_timer->pit_reload <= 1 ||
897         !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
898         (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
899         /* Stop PIT */
900 #ifdef PPC_DEBUG_TB
901         if (loglevel != 0) {
902             fprintf(logfile, "%s: stop PIT\n", __func__);
903         }
904 #endif
905         qemu_del_timer(tb_env->decr_timer);
906     } else {
907 #ifdef PPC_DEBUG_TB
908         if (loglevel != 0) {
909             fprintf(logfile, "%s: start PIT 0x" REGX "\n",
910                     __func__, ppcemb_timer->pit_reload);
911         }
912 #endif
913         now = qemu_get_clock(vm_clock);
914         next = now + muldiv64(ppcemb_timer->pit_reload,
915                               ticks_per_sec, tb_env->decr_freq);
916         if (is_excp)
917             next += tb_env->decr_next - now;
918         if (next == now)
919             next++;
920         qemu_mod_timer(tb_env->decr_timer, next);
921         tb_env->decr_next = next;
922     }
923 }
924
925 static void cpu_4xx_pit_cb (void *opaque)
926 {
927     CPUState *env;
928     ppc_tb_t *tb_env;
929     ppcemb_timer_t *ppcemb_timer;
930
931     env = opaque;
932     tb_env = env->tb_env;
933     ppcemb_timer = tb_env->opaque;
934     env->spr[SPR_40x_TSR] |= 1 << 27;
935     if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
936         ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
937     start_stop_pit(env, tb_env, 1);
938 #ifdef PPC_DEBUG_TB
939     if (loglevel != 0) {
940         fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
941                 "%016" PRIx64 "\n", __func__,
942                 (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
943                 (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
944                 env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
945                 ppcemb_timer->pit_reload);
946     }
947 #endif
948 }
949
950 /* Watchdog timer */
951 static void cpu_4xx_wdt_cb (void *opaque)
952 {
953     CPUState *env;
954     ppc_tb_t *tb_env;
955     ppcemb_timer_t *ppcemb_timer;
956     uint64_t now, next;
957
958     env = opaque;
959     tb_env = env->tb_env;
960     ppcemb_timer = tb_env->opaque;
961     now = qemu_get_clock(vm_clock);
962     switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
963     case 0:
964         next = 1 << 17;
965         break;
966     case 1:
967         next = 1 << 21;
968         break;
969     case 2:
970         next = 1 << 25;
971         break;
972     case 3:
973         next = 1 << 29;
974         break;
975     default:
976         /* Cannot occur, but makes gcc happy */
977         return;
978     }
979     next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
980     if (next == now)
981         next++;
982 #ifdef PPC_DEBUG_TB
983     if (loglevel != 0) {
984         fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
985                 env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
986     }
987 #endif
988     switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
989     case 0x0:
990     case 0x1:
991         qemu_mod_timer(ppcemb_timer->wdt_timer, next);
992         ppcemb_timer->wdt_next = next;
993         env->spr[SPR_40x_TSR] |= 1 << 31;
994         break;
995     case 0x2:
996         qemu_mod_timer(ppcemb_timer->wdt_timer, next);
997         ppcemb_timer->wdt_next = next;
998         env->spr[SPR_40x_TSR] |= 1 << 30;
999         if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
1000             ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
1001         break;
1002     case 0x3:
1003         env->spr[SPR_40x_TSR] &= ~0x30000000;
1004         env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
1005         switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
1006         case 0x0:
1007             /* No reset */
1008             break;
1009         case 0x1: /* Core reset */
1010             ppc40x_core_reset(env);
1011             break;
1012         case 0x2: /* Chip reset */
1013             ppc40x_chip_reset(env);
1014             break;
1015         case 0x3: /* System reset */
1016             ppc40x_system_reset(env);
1017             break;
1018         }
1019     }
1020 }
1021
1022 void store_40x_pit (CPUState *env, target_ulong val)
1023 {
1024     ppc_tb_t *tb_env;
1025     ppcemb_timer_t *ppcemb_timer;
1026
1027     tb_env = env->tb_env;
1028     ppcemb_timer = tb_env->opaque;
1029 #ifdef PPC_DEBUG_TB
1030     if (loglevel != 0) {
1031         fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
1032     }
1033 #endif
1034     ppcemb_timer->pit_reload = val;
1035     start_stop_pit(env, tb_env, 0);
1036 }
1037
1038 target_ulong load_40x_pit (CPUState *env)
1039 {
1040     return cpu_ppc_load_decr(env);
1041 }
1042
1043 void store_booke_tsr (CPUState *env, target_ulong val)
1044 {
1045 #ifdef PPC_DEBUG_TB
1046     if (loglevel != 0) {
1047         fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1048     }
1049 #endif
1050     env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
1051     if (val & 0x80000000)
1052         ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
1053 }
1054
1055 void store_booke_tcr (CPUState *env, target_ulong val)
1056 {
1057     ppc_tb_t *tb_env;
1058
1059     tb_env = env->tb_env;
1060 #ifdef PPC_DEBUG_TB
1061     if (loglevel != 0) {
1062         fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1063     }
1064 #endif
1065     env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1066     start_stop_pit(env, tb_env, 1);
1067     cpu_4xx_wdt_cb(env);
1068 }
1069
1070 static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1071 {
1072     CPUState *env = opaque;
1073     ppc_tb_t *tb_env = env->tb_env;
1074
1075 #ifdef PPC_DEBUG_TB
1076     if (loglevel != 0) {
1077         fprintf(logfile, "%s set new frequency to %u\n", __func__, freq);
1078     }
1079 #endif
1080     tb_env->tb_freq = freq;
1081     tb_env->decr_freq = freq;
1082     /* XXX: we should also update all timers */
1083 }
1084
1085 clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
1086 {
1087     ppc_tb_t *tb_env;
1088     ppcemb_timer_t *ppcemb_timer;
1089
1090     tb_env = qemu_mallocz(sizeof(ppc_tb_t));
1091     if (tb_env == NULL) {
1092         return NULL;
1093     }
1094     env->tb_env = tb_env;
1095     ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
1096     tb_env->tb_freq = freq;
1097     tb_env->decr_freq = freq;
1098     tb_env->opaque = ppcemb_timer;
1099 #ifdef PPC_DEBUG_TB
1100     if (loglevel != 0) {
1101         fprintf(logfile, "%s %p %p %p\n", __func__, tb_env, ppcemb_timer,
1102                 &ppc_emb_set_tb_clk);
1103     }
1104 #endif
1105     if (ppcemb_timer != NULL) {
1106         /* We use decr timer for PIT */
1107         tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
1108         ppcemb_timer->fit_timer =
1109             qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
1110         ppcemb_timer->wdt_timer =
1111             qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
1112     }
1113
1114     return &ppc_emb_set_tb_clk;
1115 }
1116
1117 /*****************************************************************************/
1118 /* Embedded PowerPC Device Control Registers */
1119 typedef struct ppc_dcrn_t ppc_dcrn_t;
1120 struct ppc_dcrn_t {
1121     dcr_read_cb dcr_read;
1122     dcr_write_cb dcr_write;
1123     void *opaque;
1124 };
1125
1126 /* XXX: on 460, DCR addresses are 32 bits wide,
1127  *      using DCRIPR to get the 22 upper bits of the DCR address
1128  */
1129 #define DCRN_NB 1024
1130 struct ppc_dcr_t {
1131     ppc_dcrn_t dcrn[DCRN_NB];
1132     int (*read_error)(int dcrn);
1133     int (*write_error)(int dcrn);
1134 };
1135
1136 int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1137 {
1138     ppc_dcrn_t *dcr;
1139
1140     if (dcrn < 0 || dcrn >= DCRN_NB)
1141         goto error;
1142     dcr = &dcr_env->dcrn[dcrn];
1143     if (dcr->dcr_read == NULL)
1144         goto error;
1145     *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1146
1147     return 0;
1148
1149  error:
1150     if (dcr_env->read_error != NULL)
1151         return (*dcr_env->read_error)(dcrn);
1152
1153     return -1;
1154 }
1155
1156 int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1157 {
1158     ppc_dcrn_t *dcr;
1159
1160     if (dcrn < 0 || dcrn >= DCRN_NB)
1161         goto error;
1162     dcr = &dcr_env->dcrn[dcrn];
1163     if (dcr->dcr_write == NULL)
1164         goto error;
1165     (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1166
1167     return 0;
1168
1169  error:
1170     if (dcr_env->write_error != NULL)
1171         return (*dcr_env->write_error)(dcrn);
1172
1173     return -1;
1174 }
1175
1176 int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1177                       dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1178 {
1179     ppc_dcr_t *dcr_env;
1180     ppc_dcrn_t *dcr;
1181
1182     dcr_env = env->dcr_env;
1183     if (dcr_env == NULL)
1184         return -1;
1185     if (dcrn < 0 || dcrn >= DCRN_NB)
1186         return -1;
1187     dcr = &dcr_env->dcrn[dcrn];
1188     if (dcr->opaque != NULL ||
1189         dcr->dcr_read != NULL ||
1190         dcr->dcr_write != NULL)
1191         return -1;
1192     dcr->opaque = opaque;
1193     dcr->dcr_read = dcr_read;
1194     dcr->dcr_write = dcr_write;
1195
1196     return 0;
1197 }
1198
1199 int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1200                   int (*write_error)(int dcrn))
1201 {
1202     ppc_dcr_t *dcr_env;
1203
1204     dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1205     if (dcr_env == NULL)
1206         return -1;
1207     dcr_env->read_error = read_error;
1208     dcr_env->write_error = write_error;
1209     env->dcr_env = dcr_env;
1210
1211     return 0;
1212 }
1213
1214 #if 0
1215 /*****************************************************************************/
1216 /* Handle system reset (for now, just stop emulation) */
1217 void cpu_ppc_reset (CPUState *env)
1218 {
1219     printf("Reset asked... Stop emulation\n");
1220     abort();
1221 }
1222 #endif
1223
1224 /*****************************************************************************/
1225 /* Debug port */
1226 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1227 {
1228     addr &= 0xF;
1229     switch (addr) {
1230     case 0:
1231         printf("%c", val);
1232         break;
1233     case 1:
1234         printf("\n");
1235         fflush(stdout);
1236         break;
1237     case 2:
1238         printf("Set loglevel to %04x\n", val);
1239         cpu_set_log(val | 0x100);
1240         break;
1241     }
1242 }
1243
1244 /*****************************************************************************/
1245 /* NVRAM helpers */
1246 static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
1247 {
1248     return (*nvram->read_fn)(nvram->opaque, addr);;
1249 }
1250
1251 static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1252 {
1253     (*nvram->write_fn)(nvram->opaque, addr, val);
1254 }
1255
1256 void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1257 {
1258     nvram_write(nvram, addr, value);
1259 }
1260
1261 uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1262 {
1263     return nvram_read(nvram, addr);
1264 }
1265
1266 void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
1267 {
1268     nvram_write(nvram, addr, value >> 8);
1269     nvram_write(nvram, addr + 1, value & 0xFF);
1270 }
1271
1272 uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1273 {
1274     uint16_t tmp;
1275
1276     tmp = nvram_read(nvram, addr) << 8;
1277     tmp |= nvram_read(nvram, addr + 1);
1278
1279     return tmp;
1280 }
1281
1282 void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
1283 {
1284     nvram_write(nvram, addr, value >> 24);
1285     nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
1286     nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
1287     nvram_write(nvram, addr + 3, value & 0xFF);
1288 }
1289
1290 uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1291 {
1292     uint32_t tmp;
1293
1294     tmp = nvram_read(nvram, addr) << 24;
1295     tmp |= nvram_read(nvram, addr + 1) << 16;
1296     tmp |= nvram_read(nvram, addr + 2) << 8;
1297     tmp |= nvram_read(nvram, addr + 3);
1298
1299     return tmp;
1300 }
1301
1302 void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1303                        const unsigned char *str, uint32_t max)
1304 {
1305     int i;
1306
1307     for (i = 0; i < max && str[i] != '\0'; i++) {
1308         nvram_write(nvram, addr + i, str[i]);
1309     }
1310     nvram_write(nvram, addr + i, str[i]);
1311     nvram_write(nvram, addr + max - 1, '\0');
1312 }
1313
1314 int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1315 {
1316     int i;
1317
1318     memset(dst, 0, max);
1319     for (i = 0; i < max; i++) {
1320         dst[i] = NVRAM_get_byte(nvram, addr + i);
1321         if (dst[i] == '\0')
1322             break;
1323     }
1324
1325     return i;
1326 }
1327
1328 static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1329 {
1330     uint16_t tmp;
1331     uint16_t pd, pd1, pd2;
1332
1333     tmp = prev >> 8;
1334     pd = prev ^ value;
1335     pd1 = pd & 0x000F;
1336     pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1337     tmp ^= (pd1 << 3) | (pd1 << 8);
1338     tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1339
1340     return tmp;
1341 }
1342
1343 uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1344 {
1345     uint32_t i;
1346     uint16_t crc = 0xFFFF;
1347     int odd;
1348
1349     odd = count & 1;
1350     count &= ~1;
1351     for (i = 0; i != count; i++) {
1352         crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1353     }
1354     if (odd) {
1355         crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1356     }
1357
1358     return crc;
1359 }
1360
1361 #define CMDLINE_ADDR 0x017ff000
1362
1363 int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
1364                           const unsigned char *arch,
1365                           uint32_t RAM_size, int boot_device,
1366                           uint32_t kernel_image, uint32_t kernel_size,
1367                           const char *cmdline,
1368                           uint32_t initrd_image, uint32_t initrd_size,
1369                           uint32_t NVRAM_image,
1370                           int width, int height, int depth)
1371 {
1372     uint16_t crc;
1373
1374     /* Set parameters for Open Hack'Ware BIOS */
1375     NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1376     NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
1377     NVRAM_set_word(nvram,   0x14, NVRAM_size);
1378     NVRAM_set_string(nvram, 0x20, arch, 16);
1379     NVRAM_set_lword(nvram,  0x30, RAM_size);
1380     NVRAM_set_byte(nvram,   0x34, boot_device);
1381     NVRAM_set_lword(nvram,  0x38, kernel_image);
1382     NVRAM_set_lword(nvram,  0x3C, kernel_size);
1383     if (cmdline) {
1384         /* XXX: put the cmdline in NVRAM too ? */
1385         strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
1386         NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
1387         NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
1388     } else {
1389         NVRAM_set_lword(nvram,  0x40, 0);
1390         NVRAM_set_lword(nvram,  0x44, 0);
1391     }
1392     NVRAM_set_lword(nvram,  0x48, initrd_image);
1393     NVRAM_set_lword(nvram,  0x4C, initrd_size);
1394     NVRAM_set_lword(nvram,  0x50, NVRAM_image);
1395
1396     NVRAM_set_word(nvram,   0x54, width);
1397     NVRAM_set_word(nvram,   0x56, height);
1398     NVRAM_set_word(nvram,   0x58, depth);
1399     crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1400     NVRAM_set_word(nvram,   0xFC, crc);
1401
1402     return 0;
1403 }