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