Fix PreP PCI IRQ mapping.
[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, 6);
176 }
177
178 #if defined(TARGET_PPC64)
179 /* PowerPC 970 internal IRQ controller */
180 static void ppc970_set_irq (void *opaque, int pin, int level)
181 {
182     CPUState *env = opaque;
183     int cur_level;
184
185 #if defined(PPC_DEBUG_IRQ)
186     if (loglevel & CPU_LOG_INT) {
187         fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
188                 env, pin, level);
189     }
190 #endif
191     cur_level = (env->irq_input_state >> pin) & 1;
192     /* Don't generate spurious events */
193     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
194         switch (pin) {
195         case PPC970_INPUT_INT:
196             /* Level sensitive - active high */
197 #if defined(PPC_DEBUG_IRQ)
198             if (loglevel & CPU_LOG_INT) {
199                 fprintf(logfile, "%s: set the external IRQ state to %d\n",
200                         __func__, level);
201             }
202 #endif
203             ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
204             break;
205         case PPC970_INPUT_THINT:
206             /* Level sensitive - active high */
207 #if defined(PPC_DEBUG_IRQ)
208             if (loglevel & CPU_LOG_INT) {
209                 fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
210                         level);
211             }
212 #endif
213             ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
214             break;
215         case PPC970_INPUT_MCP:
216             /* Negative edge sensitive */
217             /* XXX: TODO: actual reaction may depends on HID0 status
218              *            603/604/740/750: check HID0[EMCP]
219              */
220             if (cur_level == 1 && level == 0) {
221 #if defined(PPC_DEBUG_IRQ)
222                 if (loglevel & CPU_LOG_INT) {
223                     fprintf(logfile, "%s: raise machine check state\n",
224                             __func__);
225                 }
226 #endif
227                 ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
228             }
229             break;
230         case PPC970_INPUT_CKSTP:
231             /* Level sensitive - active low */
232             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
233             if (level) {
234 #if defined(PPC_DEBUG_IRQ)
235                 if (loglevel & CPU_LOG_INT) {
236                     fprintf(logfile, "%s: stop the CPU\n", __func__);
237                 }
238 #endif
239                 env->halted = 1;
240             } else {
241 #if defined(PPC_DEBUG_IRQ)
242                 if (loglevel & CPU_LOG_INT) {
243                     fprintf(logfile, "%s: restart the CPU\n", __func__);
244                 }
245 #endif
246                 env->halted = 0;
247             }
248             break;
249         case PPC970_INPUT_HRESET:
250             /* Level sensitive - active low */
251             if (level) {
252 #if 0 // XXX: TOFIX
253 #if defined(PPC_DEBUG_IRQ)
254                 if (loglevel & CPU_LOG_INT) {
255                     fprintf(logfile, "%s: reset the CPU\n", __func__);
256                 }
257 #endif
258                 cpu_reset(env);
259 #endif
260             }
261             break;
262         case PPC970_INPUT_SRESET:
263 #if defined(PPC_DEBUG_IRQ)
264             if (loglevel & CPU_LOG_INT) {
265                 fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
266                         __func__, level);
267             }
268 #endif
269             ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
270             break;
271         case PPC970_INPUT_TBEN:
272 #if defined(PPC_DEBUG_IRQ)
273             if (loglevel & CPU_LOG_INT) {
274                 fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
275                         level);
276             }
277 #endif
278             /* XXX: TODO */
279             break;
280         default:
281             /* Unknown pin - do nothing */
282 #if defined(PPC_DEBUG_IRQ)
283             if (loglevel & CPU_LOG_INT) {
284                 fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
285             }
286 #endif
287             return;
288         }
289         if (level)
290             env->irq_input_state |= 1 << pin;
291         else
292             env->irq_input_state &= ~(1 << pin);
293     }
294 }
295
296 void ppc970_irq_init (CPUState *env)
297 {
298     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
299 }
300 #endif /* defined(TARGET_PPC64) */
301
302 /* PowerPC 40x internal IRQ controller */
303 static void ppc40x_set_irq (void *opaque, int pin, int level)
304 {
305     CPUState *env = opaque;
306     int cur_level;
307
308 #if defined(PPC_DEBUG_IRQ)
309     if (loglevel & CPU_LOG_INT) {
310         fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
311                 env, pin, level);
312     }
313 #endif
314     cur_level = (env->irq_input_state >> pin) & 1;
315     /* Don't generate spurious events */
316     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
317         switch (pin) {
318         case PPC40x_INPUT_RESET_SYS:
319             if (level) {
320 #if defined(PPC_DEBUG_IRQ)
321                 if (loglevel & CPU_LOG_INT) {
322                     fprintf(logfile, "%s: reset the PowerPC system\n",
323                             __func__);
324                 }
325 #endif
326                 ppc40x_system_reset(env);
327             }
328             break;
329         case PPC40x_INPUT_RESET_CHIP:
330             if (level) {
331 #if defined(PPC_DEBUG_IRQ)
332                 if (loglevel & CPU_LOG_INT) {
333                     fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
334                 }
335 #endif
336                 ppc40x_chip_reset(env);
337             }
338             break;
339         case PPC40x_INPUT_RESET_CORE:
340             /* XXX: TODO: update DBSR[MRR] */
341             if (level) {
342 #if defined(PPC_DEBUG_IRQ)
343                 if (loglevel & CPU_LOG_INT) {
344                     fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
345                 }
346 #endif
347                 ppc40x_core_reset(env);
348             }
349             break;
350         case PPC40x_INPUT_CINT:
351             /* Level sensitive - active high */
352 #if defined(PPC_DEBUG_IRQ)
353             if (loglevel & CPU_LOG_INT) {
354                 fprintf(logfile, "%s: set the critical IRQ state to %d\n",
355                         __func__, level);
356             }
357 #endif
358             ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
359             break;
360         case PPC40x_INPUT_INT:
361             /* Level sensitive - active high */
362 #if defined(PPC_DEBUG_IRQ)
363             if (loglevel & CPU_LOG_INT) {
364                 fprintf(logfile, "%s: set the external IRQ state to %d\n",
365                         __func__, level);
366             }
367 #endif
368             ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
369             break;
370         case PPC40x_INPUT_HALT:
371             /* Level sensitive - active low */
372             if (level) {
373 #if defined(PPC_DEBUG_IRQ)
374                 if (loglevel & CPU_LOG_INT) {
375                     fprintf(logfile, "%s: stop the CPU\n", __func__);
376                 }
377 #endif
378                 env->halted = 1;
379             } else {
380 #if defined(PPC_DEBUG_IRQ)
381                 if (loglevel & CPU_LOG_INT) {
382                     fprintf(logfile, "%s: restart the CPU\n", __func__);
383                 }
384 #endif
385                 env->halted = 0;
386             }
387             break;
388         case PPC40x_INPUT_DEBUG:
389             /* Level sensitive - active high */
390 #if defined(PPC_DEBUG_IRQ)
391             if (loglevel & CPU_LOG_INT) {
392                 fprintf(logfile, "%s: set the debug pin state to %d\n",
393                         __func__, level);
394             }
395 #endif
396             ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
397             break;
398         default:
399             /* Unknown pin - do nothing */
400 #if defined(PPC_DEBUG_IRQ)
401             if (loglevel & CPU_LOG_INT) {
402                 fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
403             }
404 #endif
405             return;
406         }
407         if (level)
408             env->irq_input_state |= 1 << pin;
409         else
410             env->irq_input_state &= ~(1 << pin);
411     }
412 }
413
414 void ppc40x_irq_init (CPUState *env)
415 {
416     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
417                                                   env, PPC40x_INPUT_NB);
418 }
419
420 /*****************************************************************************/
421 /* PowerPC time base and decrementer emulation */
422 struct ppc_tb_t {
423     /* Time base management */
424     int64_t  tb_offset;    /* Compensation                    */
425     int64_t  atb_offset;   /* Compensation                    */
426     uint32_t tb_freq;      /* TB frequency                    */
427     /* Decrementer management */
428     uint64_t decr_next;    /* Tick for next decr interrupt    */
429     uint32_t decr_freq;    /* decrementer frequency           */
430     struct QEMUTimer *decr_timer;
431 #if defined(TARGET_PPC64H)
432     /* Hypervisor decrementer management */
433     uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
434     struct QEMUTimer *hdecr_timer;
435     uint64_t purr_load;
436     uint64_t purr_start;
437 #endif
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 #if defined(TARGET_PPC64H)
647 uint32_t cpu_ppc_load_hdecr (CPUState *env)
648 {
649     ppc_tb_t *tb_env = env->tb_env;
650
651     return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
652 }
653
654 uint64_t cpu_ppc_load_purr (CPUState *env)
655 {
656     ppc_tb_t *tb_env = env->tb_env;
657     uint64_t diff;
658
659     diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
660
661     return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
662 }
663 #endif /* defined(TARGET_PPC64H) */
664
665 /* When decrementer expires,
666  * all we need to do is generate or queue a CPU exception
667  */
668 static always_inline void cpu_ppc_decr_excp (CPUState *env)
669 {
670     /* Raise it */
671 #ifdef PPC_DEBUG_TB
672     if (loglevel != 0) {
673         fprintf(logfile, "raise decrementer exception\n");
674     }
675 #endif
676     ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
677 }
678
679 static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
680 {
681     /* Raise it */
682 #ifdef PPC_DEBUG_TB
683     if (loglevel != 0) {
684         fprintf(logfile, "raise decrementer exception\n");
685     }
686 #endif
687     ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
688 }
689
690 static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
691                                   struct QEMUTimer *timer,
692                                   void (*raise_excp)(CPUState *),
693                                   uint32_t decr, uint32_t value,
694                                   int is_excp)
695 {
696     ppc_tb_t *tb_env = env->tb_env;
697     uint64_t now, next;
698
699 #ifdef PPC_DEBUG_TB
700     if (loglevel != 0) {
701         fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
702     }
703 #endif
704     now = qemu_get_clock(vm_clock);
705     next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
706     if (is_excp)
707         next += *nextp - now;
708     if (next == now)
709         next++;
710     *nextp = next;
711     /* Adjust timer */
712     qemu_mod_timer(timer, next);
713     /* If we set a negative value and the decrementer was positive,
714      * raise an exception.
715      */
716     if ((value & 0x80000000) && !(decr & 0x80000000))
717         (*raise_excp)(env);
718 }
719
720 static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
721                                                uint32_t value, int is_excp)
722 {
723     ppc_tb_t *tb_env = env->tb_env;
724
725     __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
726                          &cpu_ppc_decr_excp, decr, value, is_excp);
727 }
728
729 void cpu_ppc_store_decr (CPUState *env, uint32_t value)
730 {
731     _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
732 }
733
734 static void cpu_ppc_decr_cb (void *opaque)
735 {
736     _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
737 }
738
739 #if defined(TARGET_PPC64H)
740 static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
741                                                 uint32_t value, int is_excp)
742 {
743     ppc_tb_t *tb_env = env->tb_env;
744
745     __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
746                          &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
747 }
748
749 void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
750 {
751     _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
752 }
753
754 static void cpu_ppc_hdecr_cb (void *opaque)
755 {
756     _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
757 }
758
759 void cpu_ppc_store_purr (CPUState *env, uint64_t value)
760 {
761     ppc_tb_t *tb_env = env->tb_env;
762
763     tb_env->purr_load = value;
764     tb_env->purr_start = qemu_get_clock(vm_clock);
765 }
766 #endif /* defined(TARGET_PPC64H) */
767
768 static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
769 {
770     CPUState *env = opaque;
771     ppc_tb_t *tb_env = env->tb_env;
772
773     tb_env->tb_freq = freq;
774     tb_env->decr_freq = freq;
775     /* There is a bug in Linux 2.4 kernels:
776      * if a decrementer exception is pending when it enables msr_ee at startup,
777      * it's not ready to handle it...
778      */
779     _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
780 #if defined(TARGET_PPC64H)
781     _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
782     cpu_ppc_store_purr(env, 0x0000000000000000ULL);
783 #endif /* defined(TARGET_PPC64H) */
784 }
785
786 /* Set up (once) timebase frequency (in Hz) */
787 clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
788 {
789     ppc_tb_t *tb_env;
790
791     tb_env = qemu_mallocz(sizeof(ppc_tb_t));
792     if (tb_env == NULL)
793         return NULL;
794     env->tb_env = tb_env;
795     /* Create new timer */
796     tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
797 #if defined(TARGET_PPC64H)
798     tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
799 #endif /* defined(TARGET_PPC64H) */
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 }