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