static void sysbus_esp_mem_write(void *opaque, target_phys_addr_t addr,

                                 uint64_t val, unsigned int size)

{

    SysBusESPState *sysbus = opaque;

    uint32_t saddr;

    saddr = addr >> sysbus->it_shift;

    esp_reg_write(&sysbus->esp, saddr, val);

}


static uint32_t adler32(uint32_t adler, const uint8_t *buf, unsigned int len)

{

    unsigned long s1 = adler & 0xffff;

    unsigned long s2 = (adler >> 16) & 0xffff;

    int k;

    if (buf == NULL) return 1L;

    while (len > 0) {

        k = len < NMAX ? len : NMAX;

        len -= k;

        while (k >= 16) {

            DO16(buf);

            k -= 16;

        }

        if (k != 0) do {

            DO1(buf);

        } while (--k);

        s1 %= BASE;

        s2 %= BASE;

    }

    return (s2 << 16) | s1;

}


static int wm8750_tx(I2CSlave *i2c, uint8_t data)

{

    WM8750State *s = WM8750(i2c);

    uint8_t cmd;

    uint16_t value;

    if (s->i2c_len >= 2) {

#ifdef VERBOSE

        printf("%s: long message (%i bytes)\n", __func__, s->i2c_len);

#endif

        return 1;

    }

    s->i2c_data[s->i2c_len ++] = data;

    if (s->i2c_len != 2)

        return 0;

    cmd = s->i2c_data[0] >> 1;

    value = ((s->i2c_data[0] << 8) | s->i2c_data[1]) & 0x1ff;

    switch (cmd) {

    case WM8750_LADCIN:	/* ADC Signal Path Control (Left) */

        s->diff[0] = (((value >> 6) & 3) == 3);	/* LINSEL */

        if (s->diff[0])

            s->in[0] = &s->adc_voice[0 + s->ds * 1];

        else

            s->in[0] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];

        break;

    case WM8750_RADCIN:	/* ADC Signal Path Control (Right) */

        s->diff[1] = (((value >> 6) & 3) == 3);	/* RINSEL */

        if (s->diff[1])

            s->in[1] = &s->adc_voice[0 + s->ds * 1];

        else

            s->in[1] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];

        break;

    case WM8750_ADCIN:	/* ADC Input Mode */

        s->ds = (value >> 8) & 1;	/* DS */

        if (s->diff[0])

            s->in[0] = &s->adc_voice[0 + s->ds * 1];

        if (s->diff[1])

            s->in[1] = &s->adc_voice[0 + s->ds * 1];

        s->monomix[0] = (value >> 6) & 3;	/* MONOMIX */

        break;

    case WM8750_ADCTL1:	/* Additional Control (1) */

        s->monomix[1] = (value >> 1) & 1;	/* DMONOMIX */

        break;

    case WM8750_PWR1:	/* Power Management (1) */

        s->enable = ((value >> 6) & 7) == 3;	/* VMIDSEL, VREF */

        wm8750_set_format(s);

        break;

    case WM8750_LINVOL:	/* Left Channel PGA */

        s->invol[0] = value & 0x3f;		/* LINVOL */

        s->inmute[0] = (value >> 7) & 1;	/* LINMUTE */

        wm8750_vol_update(s);

        break;

    case WM8750_RINVOL:	/* Right Channel PGA */

        s->invol[1] = value & 0x3f;		/* RINVOL */

        s->inmute[1] = (value >> 7) & 1;	/* RINMUTE */

        wm8750_vol_update(s);

        break;

    case WM8750_ADCDAC:	/* ADC and DAC Control */

        s->pol = (value >> 5) & 3;		/* ADCPOL */

        s->mute = (value >> 3) & 1;		/* DACMU */

        wm8750_vol_update(s);

        break;

    case WM8750_ADCTL3:	/* Additional Control (3) */

        break;

    case WM8750_LADC:	/* Left ADC Digital Volume */

        s->invol[2] = value & 0xff;		/* LADCVOL */

        wm8750_vol_update(s);

        break;

    case WM8750_RADC:	/* Right ADC Digital Volume */

        s->invol[3] = value & 0xff;		/* RADCVOL */

        wm8750_vol_update(s);

        break;

    case WM8750_ALC1:	/* ALC Control (1) */

        s->alc = (value >> 7) & 3;		/* ALCSEL */

        break;

    case WM8750_NGATE:	/* Noise Gate Control */

    case WM8750_3D:	/* 3D enhance */

        break;

    case WM8750_LDAC:	/* Left Channel Digital Volume */

        s->outvol[0] = value & 0xff;		/* LDACVOL */

        wm8750_vol_update(s);

        break;

    case WM8750_RDAC:	/* Right Channel Digital Volume */

        s->outvol[1] = value & 0xff;		/* RDACVOL */

        wm8750_vol_update(s);

        break;

    case WM8750_BASS:	/* Bass Control */

        break;

    case WM8750_LOUTM1:	/* Left Mixer Control (1) */

        s->path[0] = (value >> 8) & 1;		/* LD2LO */

        /* TODO: mute/unmute respective paths */

        wm8750_vol_update(s);

        break;

    case WM8750_LOUTM2:	/* Left Mixer Control (2) */

        s->path[1] = (value >> 8) & 1;		/* RD2LO */

        /* TODO: mute/unmute respective paths */

        wm8750_vol_update(s);

        break;

    case WM8750_ROUTM1:	/* Right Mixer Control (1) */

        s->path[2] = (value >> 8) & 1;		/* LD2RO */

        /* TODO: mute/unmute respective paths */

        wm8750_vol_update(s);

        break;

    case WM8750_ROUTM2:	/* Right Mixer Control (2) */

        s->path[3] = (value >> 8) & 1;		/* RD2RO */

        /* TODO: mute/unmute respective paths */

        wm8750_vol_update(s);

        break;

    case WM8750_MOUTM1:	/* Mono Mixer Control (1) */

        s->mpath[0] = (value >> 8) & 1;		/* LD2MO */

        /* TODO: mute/unmute respective paths */

        wm8750_vol_update(s);

        break;

    case WM8750_MOUTM2:	/* Mono Mixer Control (2) */

        s->mpath[1] = (value >> 8) & 1;		/* RD2MO */

        /* TODO: mute/unmute respective paths */

        wm8750_vol_update(s);

        break;

    case WM8750_LOUT1V:	/* LOUT1 Volume */

        s->outvol[2] = value & 0x7f;		/* LOUT1VOL */

        wm8750_vol_update(s);

        break;

    case WM8750_LOUT2V:	/* LOUT2 Volume */

        s->outvol[4] = value & 0x7f;		/* LOUT2VOL */

        wm8750_vol_update(s);

        break;

    case WM8750_ROUT1V:	/* ROUT1 Volume */

        s->outvol[3] = value & 0x7f;		/* ROUT1VOL */

        wm8750_vol_update(s);

        break;

    case WM8750_ROUT2V:	/* ROUT2 Volume */

        s->outvol[5] = value & 0x7f;		/* ROUT2VOL */

        wm8750_vol_update(s);

        break;

    case WM8750_MOUTV:	/* MONOOUT Volume */

        s->outvol[6] = value & 0x7f;		/* MONOOUTVOL */

        wm8750_vol_update(s);

        break;

    case WM8750_ADCTL2:	/* Additional Control (2) */

        break;

    case WM8750_PWR2:	/* Power Management (2) */

        s->power = value & 0x7e;

        /* TODO: mute/unmute respective paths */

        wm8750_vol_update(s);

        break;

    case WM8750_IFACE:	/* Digital Audio Interface Format */

        s->format = value;

        s->master = (value >> 6) & 1;			/* MS */

        wm8750_clk_update(s, s->master);

        break;

    case WM8750_SRATE:	/* Clocking and Sample Rate Control */

        s->rate = &wm_rate_table[(value >> 1) & 0x1f];

        wm8750_clk_update(s, 0);

        break;

    case WM8750_RESET:	/* Reset */

        wm8750_reset(I2C_SLAVE(s));

        break;

#ifdef VERBOSE

    default:

        printf("%s: unknown register %02x\n", __FUNCTION__, cmd);

#endif

    }

    return 0;

}


static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)

{

    int i;

    uint16_t limit;

    VncDisplay *vd = vs->vd;

    if (data[0] > 3) {

        vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;

        if (!qemu_timer_expired(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval))

            qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);

    }

    switch (data[0]) {

    case VNC_MSG_CLIENT_SET_PIXEL_FORMAT:

        if (len == 1)

            return 20;

        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),

                         read_u8(data, 6), read_u8(data, 7),

                         read_u16(data, 8), read_u16(data, 10),

                         read_u16(data, 12), read_u8(data, 14),

                         read_u8(data, 15), read_u8(data, 16));

        break;

    case VNC_MSG_CLIENT_SET_ENCODINGS:

        if (len == 1)

            return 4;

        if (len == 4) {

            limit = read_u16(data, 2);

            if (limit > 0)

                return 4 + (limit * 4);

        } else

            limit = read_u16(data, 2);

        for (i = 0; i < limit; i++) {

            int32_t val = read_s32(data, 4 + (i * 4));

            memcpy(data + 4 + (i * 4), &val, sizeof(val));

        }

        set_encodings(vs, (int32_t *)(data + 4), limit);

        break;

    case VNC_MSG_CLIENT_FRAMEBUFFER_UPDATE_REQUEST:

        if (len == 1)

            return 10;

        framebuffer_update_request(vs,

                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),

                                   read_u16(data, 6), read_u16(data, 8));

        break;

    case VNC_MSG_CLIENT_KEY_EVENT:

        if (len == 1)

            return 8;

        key_event(vs, read_u8(data, 1), read_u32(data, 4));

        break;

    case VNC_MSG_CLIENT_POINTER_EVENT:

        if (len == 1)

            return 6;

        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));

        break;

    case VNC_MSG_CLIENT_CUT_TEXT:

        if (len == 1)

            return 8;

        if (len == 8) {

            uint32_t dlen = read_u32(data, 4);

            if (dlen > 0)

                return 8 + dlen;

        }

        client_cut_text(vs, read_u32(data, 4), data + 8);

        break;

    case VNC_MSG_CLIENT_QEMU:

        if (len == 1)

            return 2;

        switch (read_u8(data, 1)) {

        case VNC_MSG_CLIENT_QEMU_EXT_KEY_EVENT:

            if (len == 2)

                return 12;

            ext_key_event(vs, read_u16(data, 2),

                          read_u32(data, 4), read_u32(data, 8));

            break;

        case VNC_MSG_CLIENT_QEMU_AUDIO:

            if (len == 2)

                return 4;

            switch (read_u16 (data, 2)) {

            case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE:

                audio_add(vs);

                break;

            case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE:

                audio_del(vs);

                break;

            case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT:

                if (len == 4)

                    return 10;

                switch (read_u8(data, 4)) {

                case 0: vs->as.fmt = AUD_FMT_U8; break;

                case 1: vs->as.fmt = AUD_FMT_S8; break;

                case 2: vs->as.fmt = AUD_FMT_U16; break;

                case 3: vs->as.fmt = AUD_FMT_S16; break;

                case 4: vs->as.fmt = AUD_FMT_U32; break;

                case 5: vs->as.fmt = AUD_FMT_S32; break;

                default:

                    printf("Invalid audio format %d\n", read_u8(data, 4));

                    vnc_client_error(vs);

                    break;

                }

                vs->as.nchannels = read_u8(data, 5);

                if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {

                    printf("Invalid audio channel coount %d\n",

                           read_u8(data, 5));

                    vnc_client_error(vs);

                    break;

                }

                vs->as.freq = read_u32(data, 6);

                break;

            default:

                printf ("Invalid audio message %d\n", read_u8(data, 4));

                vnc_client_error(vs);

                break;

            }

            break;

        default:

            printf("Msg: %d\n", read_u16(data, 0));

            vnc_client_error(vs);

            break;

        }

        break;

    default:

        printf("Msg: %d\n", data[0]);

        vnc_client_error(vs);

        break;

    }

    vnc_read_when(vs, protocol_client_msg, 1);

    return 0;

}


void ppc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))

{

    int i, max;

    max = ARRAY_SIZE(ppc_defs);

    for (i = 0; i < max; i++) {

        (*cpu_fprintf)(f, "PowerPC %-16s PVR %08x\n",

                       ppc_defs[i].name, ppc_defs[i].pvr);

    }

}


static void gic_update(gic_state *s)

{

    int best_irq;

    int best_prio;

    int irq;

    int level;

    int cpu;

    int cm;

    for (cpu = 0; cpu < NUM_CPU(s); cpu++) {

        cm = 1 << cpu;

        s->current_pending[cpu] = 1023;

        if (!s->enabled || !s->cpu_enabled[cpu]) {

	    qemu_irq_lower(s->parent_irq[cpu]);

            return;

        }

        best_prio = 0x100;

        best_irq = 1023;

        for (irq = 0; irq < GIC_NIRQ; irq++) {

            if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq, cm)) {

                if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {

                    best_prio = GIC_GET_PRIORITY(irq, cpu);

                    best_irq = irq;

                }

            }

        }

        level = 0;

        if (best_prio <= s->priority_mask[cpu]) {

            s->current_pending[cpu] = best_irq;

            if (best_prio < s->running_priority[cpu]) {

                DPRINTF("Raised pending IRQ %d\n", best_irq);

                level = 1;

            }

        }

        qemu_set_irq(s->parent_irq[cpu], level);

    }

}


static void *kqemu_vmalloc(size_t size)

{

    static int phys_ram_fd = -1;

    static int phys_ram_size = 0;

    void *ptr;

/* no need (?) for a dummy file on OpenBSD/FreeBSD */

#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)

    int map_anon = MAP_ANON;

#else

    int map_anon = 0;

    const char *tmpdir;

    char phys_ram_file[1024];

#ifdef CONFIG_SOLARIS

    struct statvfs stfs;

#else

    struct statfs stfs;

#endif

    if (!size) {

        abort ();

    }

    if (phys_ram_fd < 0) {

        tmpdir = getenv("QEMU_TMPDIR");

        if (!tmpdir)

#ifdef CONFIG_SOLARIS

            tmpdir = "/tmp";

        if (statvfs(tmpdir, &stfs) == 0) {

#else

            tmpdir = "/dev/shm";

        if (statfs(tmpdir, &stfs) == 0) {

#endif

            int64_t free_space;

            int ram_mb;

            free_space = (int64_t)stfs.f_bavail * stfs.f_bsize;

            if ((ram_size + 8192 * 1024) >= free_space) {

                ram_mb = (ram_size / (1024 * 1024));

                fprintf(stderr,

                        "You do not have enough space in '%s' for the %d MB of QEMU virtual RAM.\n",

                        tmpdir, ram_mb);

                if (strcmp(tmpdir, "/dev/shm") == 0) {

                    fprintf(stderr, "To have more space available provided you have enough RAM and swap, do as root:\n"

                            "mount -o remount,size=%dm /dev/shm\n",

                            ram_mb + 16);

                } else {

                    fprintf(stderr,

                            "Use the '-m' option of QEMU to diminish the amount of virtual RAM or use the\n"

                            "QEMU_TMPDIR environment variable to set another directory where the QEMU\n"

                            "temporary RAM file will be opened.\n");

                }

                fprintf(stderr, "Or disable the accelerator module with -no-kqemu\n");

                exit(1);

            }

        }

        snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX",

                 tmpdir);

        phys_ram_fd = mkstemp(phys_ram_file);

        if (phys_ram_fd < 0) {

            fprintf(stderr,

                    "warning: could not create temporary file in '%s'.\n"

                    "Use QEMU_TMPDIR to select a directory in a tmpfs filesystem.\n"

                    "Using '/tmp' as fallback.\n",

                    tmpdir);

            snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX",

                     "/tmp");

            phys_ram_fd = mkstemp(phys_ram_file);

            if (phys_ram_fd < 0) {

                fprintf(stderr, "Could not create temporary memory file '%s'\n",

                        phys_ram_file);

                exit(1);

            }

        }

        unlink(phys_ram_file);

    }

    size = (size + 4095) & ~4095;

    ftruncate(phys_ram_fd, phys_ram_size + size);

#endif /* !(__OpenBSD__ || __FreeBSD__ || __DragonFly__) */

    ptr = mmap(NULL,

               size,

               PROT_WRITE | PROT_READ, map_anon | MAP_SHARED,

               phys_ram_fd, phys_ram_size);

    if (ptr == MAP_FAILED) {

        fprintf(stderr, "Could not map physical memory\n");

        exit(1);

    }

    phys_ram_size += size;

    return ptr;

}


static uint32_t virtio_console_get_features(VirtIODevice *vdev)

{

    return 0;

}


void event_loop(void)

{

    SDL_Event event;

    double incr, pos, frac;

    for(;;) {

        SDL_WaitEvent(&event);

        switch(event.type) {

        case SDL_KEYDOWN:

            switch(event.key.keysym.sym) {

            case SDLK_ESCAPE:

            case SDLK_q:

                do_exit();

                break;

            case SDLK_f:

                toggle_full_screen();

                break;

            case SDLK_p:

            case SDLK_SPACE:

                toggle_pause();

                break;

            case SDLK_s: //S: Step to next frame

                step_to_next_frame();

                break;

            case SDLK_a:

                if (cur_stream)

                    stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);

                break;

            case SDLK_v:

                if (cur_stream)

                    stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);

                break;

            case SDLK_w:

                toggle_audio_display();

                break;

            case SDLK_LEFT:

                incr = -10.0;

                goto do_seek;

            case SDLK_RIGHT:

                incr = 10.0;

                goto do_seek;

            case SDLK_UP:

                incr = 60.0;

                goto do_seek;

            case SDLK_DOWN:

                incr = -60.0;

            do_seek:

                if (cur_stream) {

                    pos = get_master_clock(cur_stream);

printf("%f %f %d %d %d %d\n", (float)pos, (float)incr, cur_stream->av_sync_type == AV_SYNC_VIDEO_MASTER,

cur_stream->av_sync_type == AV_SYNC_AUDIO_MASTER, cur_stream->video_st, cur_stream->audio_st);

                    pos += incr;

                    stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE));

                }

                break;

            default:

                break;

            }

            break;

        case SDL_MOUSEBUTTONDOWN:

	    if (cur_stream) {

		int ns, hh, mm, ss;

		int tns, thh, tmm, tss;

		tns = cur_stream->ic->duration/1000000LL;

		thh = tns/3600;

		tmm = (tns%3600)/60;

		tss = (tns%60);

		frac = (double)event.button.x/(double)cur_stream->width;

		ns = frac*tns;

		hh = ns/3600;

		mm = (ns%3600)/60;

		ss = (ns%60);

		fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n", frac*100,

			hh, mm, ss, thh, tmm, tss);

		stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration));

	    }

	    break;

        case SDL_VIDEORESIZE:

            if (cur_stream) {

                screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,

                                          SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);

                cur_stream->width = event.resize.w;

                cur_stream->height = event.resize.h;

            }

            break;

        case SDL_QUIT:

        case FF_QUIT_EVENT:

            do_exit();

            break;

        case FF_ALLOC_EVENT:

            alloc_picture(event.user.data1);

            break;

        case FF_REFRESH_EVENT:

            video_refresh_timer(event.user.data1);

            break;

        default:

            break;

        }

    }

}


static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)

{

    set_bit(q->queue, n_IRQ);

}


static void sdl_callback (void *opaque, Uint8 *buf, int len)

{

    SDLVoiceOut *sdl = opaque;

    SDLAudioState *s = &glob_sdl;

    HWVoiceOut *hw = &sdl->hw;

    int samples = len >> hw->info.shift;

    if (s->exit) {

        return;

    }

    while (samples) {

        int to_mix, decr;

        /* dolog ("in callback samples=%d\n", samples); */

        sdl_wait (s, "sdl_callback");

        if (s->exit) {

            return;

        }

        if (sdl_lock (s, "sdl_callback")) {

            return;

        }

        if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) {

            dolog ("sdl->live=%d hw->samples=%d\n",

                   sdl->live, hw->samples);

            return;

        }

        if (!sdl->live) {

            goto again;

        }

        /* dolog ("in callback live=%d\n", live); */

        to_mix = audio_MIN (samples, sdl->live);

        decr = to_mix;

        while (to_mix) {

            int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);

            st_sample_t *src = hw->mix_buf + hw->rpos;

            /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */

            hw->clip (buf, src, chunk);

            sdl->rpos = (sdl->rpos + chunk) % hw->samples;

            to_mix -= chunk;

            buf += chunk << hw->info.shift;

        }

        samples -= decr;

        sdl->live -= decr;

        sdl->decr += decr;

    again:

        if (sdl_unlock (s, "sdl_callback")) {

            return;

        }

    }

    /* dolog ("done len=%d\n", len); */

}


static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,

                              AVFormatContext *s)

{

    int64_t pos = avio_tell(pb);

    avio_wb32(pb, 0); /* size */

    ffio_wfourcc(pb, "ilst");

    mov_write_string_metadata(s, pb, "\251nam", "title"    , 1);

    mov_write_string_metadata(s, pb, "\251ART", "artist"   , 1);

    mov_write_string_metadata(s, pb, "aART", "album_artist", 1);

    mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);

    mov_write_string_metadata(s, pb, "\251alb", "album"    , 1);

    mov_write_string_metadata(s, pb, "\251day", "date"     , 1);

    mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);

    mov_write_string_metadata(s, pb, "\251cmt", "comment"  , 1);

    mov_write_string_metadata(s, pb, "\251gen", "genre"    , 1);

    mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1);

    mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1);

    mov_write_string_metadata(s, pb, "\251lyr", "lyrics"   , 1);

    mov_write_string_metadata(s, pb, "desc",    "description",1);

    mov_write_string_metadata(s, pb, "ldes",    "synopsis" , 1);

    mov_write_string_metadata(s, pb, "tvsh",    "show"     , 1);

    mov_write_string_metadata(s, pb, "tven",    "episode_id",1);

    mov_write_string_metadata(s, pb, "tvnn",    "network"  , 1);

    mov_write_trkn_tag(pb, mov, s);

    return update_size(pb, pos);

}


static int gif_read_close(AVFormatContext *s1)

{

    GifState *s = s1->priv_data;

    av_free(s->image_buf);

    return 0;

}


void qemu_thread_get_self(QemuThread *thread)

{

    if (!thread->thread) {

        /* In the main thread of the process.  Initialize the QemuThread

           pointer in TLS, and use the dummy GetCurrentThread handle as

           the identifier for qemu_thread_is_self.  */

        qemu_thread_init();

        TlsSetValue(qemu_thread_tls_index, thread);

        thread->thread = GetCurrentThread();

    }

}


static void coroutine_fn qemu_co_mutex_lock_slowpath(CoMutex *mutex)

{

    Coroutine *self = qemu_coroutine_self();

    CoWaitRecord w;

    unsigned old_handoff;

    trace_qemu_co_mutex_lock_entry(mutex, self);

    w.co = self;

    push_waiter(mutex, &w);

    /* This is the "Responsibility Hand-Off" protocol; a lock() picks from

     * a concurrent unlock() the responsibility of waking somebody up.

     */

    old_handoff = atomic_mb_read(&mutex->handoff);

    if (old_handoff &&

        has_waiters(mutex) &&

        atomic_cmpxchg(&mutex->handoff, old_handoff, 0) == old_handoff) {

        /* There can be no concurrent pops, because there can be only

         * one active handoff at a time.

         */

        CoWaitRecord *to_wake = pop_waiter(mutex);

        Coroutine *co = to_wake->co;

        if (co == self) {

            /* We got the lock ourselves!  */

            assert(to_wake == &w);

            return;

        }

        aio_co_wake(co);

    }

    qemu_coroutine_yield();

    trace_qemu_co_mutex_lock_return(mutex, self);

}


static int pnm_decode_frame(AVCodecContext *avctx, void *data,

                            int *got_frame, AVPacket *avpkt)

{

    const uint8_t *buf   = avpkt->data;

    int buf_size         = avpkt->size;

    PNMContext * const s = avctx->priv_data;

    AVFrame * const p    = data;

    int i, j, n, linesize, h, upgrade = 0, is_mono = 0;

    unsigned char *ptr;

    int components, sample_len, ret;

    unsigned int maskval = 0;

    s->bytestream_start =

    s->bytestream       = (uint8_t *)buf;

    s->bytestream_end   = (uint8_t *)buf + buf_size;

    if ((ret = ff_pnm_decode_header(avctx, s)) < 0)

        return ret;

    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)

        return ret;

    p->pict_type = AV_PICTURE_TYPE_I;

    p->key_frame = 1;

    switch (avctx->pix_fmt) {

    default:

        return AVERROR(EINVAL);

    case AV_PIX_FMT_RGBA64BE:

        n = avctx->width * 8;

        components=4;

        sample_len=16;

        goto do_read;

    case AV_PIX_FMT_RGB48BE:

        n = avctx->width * 6;

        components=3;

        sample_len=16;

        goto do_read;

    case AV_PIX_FMT_RGBA:

        n = avctx->width * 4;

        components=4;

        sample_len=8;

        goto do_read;

    case AV_PIX_FMT_RGB24:

        n = avctx->width * 3;

        components=3;

        sample_len=8;

        goto do_read;

    case AV_PIX_FMT_GRAY8:

        n = avctx->width;

        components=1;

        sample_len=8;

        if (s->maxval < 255) {

            upgrade = 1;

            maskval = (2 << av_log2(s->maxval)) - 1;

        }

        goto do_read;

    case AV_PIX_FMT_GRAY8A:

        n = avctx->width * 2;

        components=2;

        sample_len=8;

        goto do_read;

    case AV_PIX_FMT_GRAY16BE:

    case AV_PIX_FMT_GRAY16LE:

        n = avctx->width * 2;

        components=1;

        sample_len=16;

        if (s->maxval < 65535) {

            upgrade = 2;

            maskval = (2 << av_log2(s->maxval)) - 1;

        }

        goto do_read;

    case AV_PIX_FMT_MONOWHITE:

    case AV_PIX_FMT_MONOBLACK:

        n = (avctx->width + 7) >> 3;

        components=1;

        sample_len=1;

        is_mono = 1;

    do_read:

        ptr      = p->data[0];

        linesize = p->linesize[0];

        if (s->bytestream + n * avctx->height > s->bytestream_end)

            return AVERROR_INVALIDDATA;

        if(s->type < 4 || (is_mono && s->type==7)){

            for (i=0; i<avctx->height; i++) {

                PutBitContext pb;

                init_put_bits(&pb, ptr, linesize);

                for(j=0; j<avctx->width * components; j++){

                    unsigned int c=0;

                    int v=0;

                    if(s->type < 4)

                    while(s->bytestream < s->bytestream_end && (*s->bytestream < '0' || *s->bytestream > '9' ))

                        s->bytestream++;

                    if(s->bytestream >= s->bytestream_end)

                        return AVERROR_INVALIDDATA;

                    if (is_mono) {

                        /* read a single digit */

                        v = (*s->bytestream++)&1;

                    } else {

                        /* read a sequence of digits */

                        do {

                            v = 10*v + c;

                            c = (*s->bytestream++) - '0';

                        } while (c <= 9);

                    }

                    put_bits(&pb, sample_len, (((1<<sample_len)-1)*v + (s->maxval>>1))/s->maxval);

                }

                flush_put_bits(&pb);

                ptr+= linesize;

            }

        }else{

        for (i = 0; i < avctx->height; i++) {

            if (!upgrade)

                memcpy(ptr, s->bytestream, n);

            else if (upgrade == 1) {

                unsigned int j, f = (255 * 128 + s->maxval / 2) / s->maxval;

                for (j = 0; j < n; j++)

                    ptr[j] = ((s->bytestream[j] & maskval) * f + 64) >> 7;

            } else if (upgrade == 2) {

                unsigned int j, v, f = (65535 * 32768 + s->maxval / 2) / s->maxval;

                for (j = 0; j < n / 2; j++) {

                    v = av_be2ne16(((uint16_t *)s->bytestream)[j]) & maskval;

                    ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;

                }

            }

            s->bytestream += n;

            ptr           += linesize;

        }

        }

        break;

    case AV_PIX_FMT_YUV420P:

    case AV_PIX_FMT_YUV420P9BE:

    case AV_PIX_FMT_YUV420P10BE:

        {

            unsigned char *ptr1, *ptr2;

            n        = avctx->width;

            ptr      = p->data[0];

            linesize = p->linesize[0];

            if (s->maxval >= 256)

                n *= 2;

            if (s->bytestream + n * avctx->height * 3 / 2 > s->bytestream_end)

                return AVERROR_INVALIDDATA;

            for (i = 0; i < avctx->height; i++) {

                memcpy(ptr, s->bytestream, n);

                s->bytestream += n;

                ptr           += linesize;

            }

            ptr1 = p->data[1];

            ptr2 = p->data[2];

            n >>= 1;

            h = avctx->height >> 1;

            for (i = 0; i < h; i++) {

                memcpy(ptr1, s->bytestream, n);

                s->bytestream += n;

                memcpy(ptr2, s->bytestream, n);

                s->bytestream += n;

                ptr1 += p->linesize[1];

                ptr2 += p->linesize[2];

            }

        }

        break;

    case AV_PIX_FMT_YUV420P16:

        {

            uint16_t *ptr1, *ptr2;

            const int f = (65535 * 32768 + s->maxval / 2) / s->maxval;

            unsigned int j, v;

            n        = avctx->width * 2;

            ptr      = p->data[0];

            linesize = p->linesize[0];

            if (s->bytestream + n * avctx->height * 3 / 2 > s->bytestream_end)

                return AVERROR_INVALIDDATA;

            for (i = 0; i < avctx->height; i++) {

                for (j = 0; j < n / 2; j++) {

                    v = av_be2ne16(((uint16_t *)s->bytestream)[j]);

                    ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;

                }

                s->bytestream += n;

                ptr           += linesize;

            }

            ptr1 = (uint16_t*)p->data[1];

            ptr2 = (uint16_t*)p->data[2];

            n >>= 1;

            h = avctx->height >> 1;

            for (i = 0; i < h; i++) {

                for (j = 0; j < n / 2; j++) {

                    v = av_be2ne16(((uint16_t *)s->bytestream)[j]);

                    ptr1[j] = (v * f + 16384) >> 15;

                }

                s->bytestream += n;

                for (j = 0; j < n / 2; j++) {

                    v = av_be2ne16(((uint16_t *)s->bytestream)[j]);

                    ptr2[j] = (v * f + 16384) >> 15;

                }

                s->bytestream += n;

                ptr1 += p->linesize[1] / 2;

                ptr2 += p->linesize[2] / 2;

            }

        }

        break;

    }

    *got_frame = 1;

    return s->bytestream - s->bytestream_start;

}


static ssize_t block_crypto_write_func(QCryptoBlock *block,

                                       void *opaque,

                                       size_t offset,

                                       const uint8_t *buf,

                                       size_t buflen,

                                       Error **errp)

{

    struct BlockCryptoCreateData *data = opaque;

    ssize_t ret;

    ret = blk_pwrite(data->blk, offset, buf, buflen, 0);

    if (ret < 0) {

        error_setg_errno(errp, -ret, "Could not write encryption header");

        return ret;

    }

    return ret;

}


static int qemu_calculate_timeout(void)

{

#ifndef CONFIG_IOTHREAD

    int timeout;

    if (!vm_running)

        timeout = 5000;

    else if (tcg_has_work())

        timeout = 0;

    else {

     /* XXX: use timeout computed from timers */

        int64_t add;

        int64_t delta;

        /* Advance virtual time to the next event.  */

	delta = qemu_icount_delta();

        if (delta > 0) {

            /* If virtual time is ahead of real time then just

               wait for IO.  */

            timeout = (delta + 999999) / 1000000;

        } else {

            /* Wait for either IO to occur or the next

               timer event.  */

            add = qemu_next_deadline();

            /* We advance the timer before checking for IO.

               Limit the amount we advance so that early IO

               activity won't get the guest too far ahead.  */

            if (add > 10000000)

                add = 10000000;

            delta += add;

            qemu_icount += qemu_icount_round (add);

            timeout = delta / 1000000;

            if (timeout < 0)

                timeout = 0;

        }

    }

    return timeout;

#else /* CONFIG_IOTHREAD */

    return 1000;

#endif

}


static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)

{

    SpiceCharDriver *s = chr->opaque;

    vmc_register_interface(s);

    assert(s->datalen == 0);

    if (s->bufsize < len) {

        s->bufsize = len;

        s->buffer = g_realloc(s->buffer, s->bufsize);

    }

    memcpy(s->buffer, buf, len);

    s->datapos = s->buffer;

    s->datalen = len;

    spice_server_char_device_wakeup(&s->sin);

    return len;

}


static int net_slirp_init(NetClientState *peer, const char *model,

                          const char *name, int restricted,

                          const char *vnetwork, const char *vhost,

                          const char *vhostname, const char *tftp_export,

                          const char *bootfile, const char *vdhcp_start,

                          const char *vnameserver, const char *smb_export,

                          const char *vsmbserver, const char **dnssearch)

{

    /* default settings according to historic slirp */

    struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */

    struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */

    struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */

    struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */

    struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */

#ifndef _WIN32

    struct in_addr smbsrv = { .s_addr = 0 };

#endif

    NetClientState *nc;

    SlirpState *s;

    char buf[20];

    uint32_t addr;

    int shift;

    char *end;

    struct slirp_config_str *config;

    if (!tftp_export) {

        tftp_export = legacy_tftp_prefix;

    }

    if (!bootfile) {

        bootfile = legacy_bootp_filename;

    }

    if (vnetwork) {

        if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {

            if (!inet_aton(vnetwork, &net)) {

                return -1;

            }

            addr = ntohl(net.s_addr);

            if (!(addr & 0x80000000)) {

                mask.s_addr = htonl(0xff000000); /* class A */

            } else if ((addr & 0xfff00000) == 0xac100000) {

                mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */

            } else if ((addr & 0xc0000000) == 0x80000000) {

                mask.s_addr = htonl(0xffff0000); /* class B */

            } else if ((addr & 0xffff0000) == 0xc0a80000) {

                mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */

            } else if ((addr & 0xffff0000) == 0xc6120000) {

                mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */

            } else if ((addr & 0xe0000000) == 0xe0000000) {

                mask.s_addr = htonl(0xffffff00); /* class C */

            } else {

                mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */

            }

        } else {

            if (!inet_aton(buf, &net)) {

                return -1;

            }

            shift = strtol(vnetwork, &end, 10);

            if (*end != '\0') {

                if (!inet_aton(vnetwork, &mask)) {

                    return -1;

                }

            } else if (shift < 4 || shift > 32) {

                return -1;

            } else {

                mask.s_addr = htonl(0xffffffff << (32 - shift));

            }

        }

        net.s_addr &= mask.s_addr;

        host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);

        dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);

        dns.s_addr  = net.s_addr | (htonl(0x0203) & ~mask.s_addr);

    }

    if (vhost && !inet_aton(vhost, &host)) {

        return -1;

    }

    if ((host.s_addr & mask.s_addr) != net.s_addr) {

        return -1;

    }

    if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {

        return -1;

    }

    if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||

        dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {

        return -1;

    }

    if (vnameserver && !inet_aton(vnameserver, &dns)) {

        return -1;

    }

    if ((dns.s_addr & mask.s_addr) != net.s_addr ||

        dns.s_addr == host.s_addr) {

        return -1;

    }

#ifndef _WIN32

    if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {

        return -1;

    }

#endif

    nc = qemu_new_net_client(&net_slirp_info, peer, model, name);

    snprintf(nc->info_str, sizeof(nc->info_str),

             "net=%s,restrict=%s", inet_ntoa(net),

             restricted ? "on" : "off");

    s = DO_UPCAST(SlirpState, nc, nc);

    s->slirp = slirp_init(restricted, net, mask, host, vhostname,

                          tftp_export, bootfile, dhcp, dns, dnssearch, s);

    QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);

    for (config = slirp_configs; config; config = config->next) {

        if (config->flags & SLIRP_CFG_HOSTFWD) {

            if (slirp_hostfwd(s, config->str,

                              config->flags & SLIRP_CFG_LEGACY) < 0)

                goto error;

        } else {

            if (slirp_guestfwd(s, config->str,

                               config->flags & SLIRP_CFG_LEGACY) < 0)

                goto error;

        }

    }

#ifndef _WIN32

    if (!smb_export) {

        smb_export = legacy_smb_export;

    }

    if (smb_export) {

        if (slirp_smb(s, smb_export, smbsrv) < 0)

            goto error;

    }

#endif

    return 0;

error:

    qemu_del_net_client(nc);

    return -1;

}


static int ppce500_load_device_tree(CPUPPCState *env,

                                    PPCE500Params *params,

                                    hwaddr addr,

                                    hwaddr initrd_base,

                                    hwaddr initrd_size)

{

    int ret = -1;

    uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) };

    int fdt_size;

    void *fdt;

    uint8_t hypercall[16];

    uint32_t clock_freq = 400000000;

    uint32_t tb_freq = 400000000;

    int i;

    const char *toplevel_compat = NULL; /* user override */

    char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";

    char soc[128];

    char mpic[128];

    uint32_t mpic_ph;

    uint32_t msi_ph;

    char gutil[128];

    char pci[128];

    char msi[128];

    uint32_t *pci_map = NULL;

    int len;

    uint32_t pci_ranges[14] =

        {

            0x2000000, 0x0, 0xc0000000,

            0x0, 0xc0000000,

            0x0, 0x20000000,

            0x1000000, 0x0, 0x0,

            0x0, 0xe1000000,

            0x0, 0x10000,

        };

    QemuOpts *machine_opts;

    const char *dtb_file = NULL;

    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);

    if (machine_opts) {

        dtb_file = qemu_opt_get(machine_opts, "dtb");

        toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");

    }

    if (dtb_file) {

        char *filename;

        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);

        if (!filename) {

            goto out;

        }

        fdt = load_device_tree(filename, &fdt_size);

        if (!fdt) {

            goto out;

        }

        goto done;

    }

    fdt = create_device_tree(&fdt_size);

    if (fdt == NULL) {

        goto out;

    }

    /* Manipulate device tree in memory. */

    qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);

    qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);

    qemu_devtree_add_subnode(fdt, "/memory");

    qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");

    qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,

                         sizeof(mem_reg_property));

    qemu_devtree_add_subnode(fdt, "/chosen");

    if (initrd_size) {

        ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",

                                        initrd_base);

        if (ret < 0) {

            fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");

        }

        ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",

                                        (initrd_base + initrd_size));

        if (ret < 0) {

            fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");

        }

    }

    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",

                                      params->kernel_cmdline);

    if (ret < 0)

        fprintf(stderr, "couldn't set /chosen/bootargs\n");

    if (kvm_enabled()) {

        /* Read out host's frequencies */

        clock_freq = kvmppc_get_clockfreq();

        tb_freq = kvmppc_get_tbfreq();

        /* indicate KVM hypercall interface */

        qemu_devtree_add_subnode(fdt, "/hypervisor");

        qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",

                                    "linux,kvm");

        kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));

        qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",

                             hypercall, sizeof(hypercall));

    }

    /* Create CPU nodes */

    qemu_devtree_add_subnode(fdt, "/cpus");

    qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);

    qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);

    /* We need to generate the cpu nodes in reverse order, so Linux can pick

       the first node as boot node and be happy */

    for (i = smp_cpus - 1; i >= 0; i--) {

        char cpu_name[128];

        uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);

        for (env = first_cpu; env != NULL; env = env->next_cpu) {

            if (env->cpu_index == i) {

                break;

            }

        }

        if (!env) {

            continue;

        }

        snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index);

        qemu_devtree_add_subnode(fdt, cpu_name);

        qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);

        qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);

        qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");

        qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index);

        qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",

                                  env->dcache_line_size);

        qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",

                                  env->icache_line_size);

        qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);

        qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);

        qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);

        if (env->cpu_index) {

            qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");

            qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");

            qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",

                                     cpu_release_addr);

        } else {

            qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");

        }

    }

    qemu_devtree_add_subnode(fdt, "/aliases");

    /* XXX These should go into their respective devices' code */

    snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);

    qemu_devtree_add_subnode(fdt, soc);

    qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");

    qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,

                         sizeof(compatible_sb));

    qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);

    qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);

    qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,

                               MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,

                               MPC8544_CCSRBAR_SIZE);

    /* XXX should contain a reasonable value */

    qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);

    snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);

    qemu_devtree_add_subnode(fdt, mpic);

    qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");

    qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic");

    qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,

                               0x40000);

    qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);

    qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);

    mpic_ph = qemu_devtree_alloc_phandle(fdt);

    qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);

    qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);

    qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);

    /*

     * We have to generate ser1 first, because Linux takes the first

     * device it finds in the dt as serial output device. And we generate

     * devices in reverse order to the dt.

     */

    dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,

                     soc, mpic, "serial1", 1, false);

    dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,

                     soc, mpic, "serial0", 0, true);

    snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,

             MPC8544_UTIL_OFFSET);

    qemu_devtree_add_subnode(fdt, gutil);

    qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");

    qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);

    qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);

    snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);

    qemu_devtree_add_subnode(fdt, msi);

    qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");

    qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);

    msi_ph = qemu_devtree_alloc_phandle(fdt);

    qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);

    qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);

    qemu_devtree_setprop_cells(fdt, msi, "interrupts",

        0xe0, 0x0,

        0xe1, 0x0,

        0xe2, 0x0,

        0xe3, 0x0,

        0xe4, 0x0,

        0xe5, 0x0,

        0xe6, 0x0,

        0xe7, 0x0);

    qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);

    qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);

    snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);

    qemu_devtree_add_subnode(fdt, pci);

    qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);

    qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");

    qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");

    qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,

                               0x0, 0x7);

    pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic),

                             0x11, 2, &len);

    qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len);

    qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);

    qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);

    qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);

    for (i = 0; i < 14; i++) {

        pci_ranges[i] = cpu_to_be32(pci_ranges[i]);

    }

    qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);

    qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));

    qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,

                               MPC8544_PCI_REGS_BASE, 0, 0x1000);

    qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);

    qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);

    qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);

    qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);

    qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);

    params->fixup_devtree(params, fdt);

    if (toplevel_compat) {

        qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,

                             strlen(toplevel_compat) + 1);

    }

done:

    qemu_devtree_dumpdtb(fdt, fdt_size);

    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);

    if (ret < 0) {

        goto out;

    }

    g_free(fdt);

    ret = fdt_size;

out:

    g_free(pci_map);

    return ret;

}


int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)

{

    int i, o;

    if ( am->in_channels <= 0 ||  am->in_channels > AVRESAMPLE_MAX_CHANNELS ||

        am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {

        av_log(am, AV_LOG_ERROR, "Invalid channel counts\n");

        return AVERROR(EINVAL);

    }

#define GET_MATRIX_CONVERT(suffix, scale)                                   \

    if (!am->matrix_ ## suffix[0]) {                                        \

        av_log(am, AV_LOG_ERROR, "matrix is not set\n");                    \

        return AVERROR(EINVAL);                                             \

    }                                                                       \

    for (o = 0; o < am->out_channels; o++)                                  \

        for (i = 0; i < am->in_channels; i++)                               \

            matrix[o * stride + i] = am->matrix_ ## suffix[o][i] * (scale);

    switch (am->coeff_type) {

    case AV_MIX_COEFF_TYPE_Q8:

        GET_MATRIX_CONVERT(q8, 1.0 / 256.0);

        break;

    case AV_MIX_COEFF_TYPE_Q15:

        GET_MATRIX_CONVERT(q15, 1.0 / 32768.0);

        break;

    case AV_MIX_COEFF_TYPE_FLT:

        GET_MATRIX_CONVERT(flt, 1.0);

        break;

    default:

        av_log(am, AV_LOG_ERROR, "Invalid mix coeff type\n");

        return AVERROR(EINVAL);

    }

    return 0;

}


DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)

{

    return bs->blk ? blk_legacy_dinfo(bs->blk) : NULL;

}


int kvm_arch_put_registers(CPUState *env, int level)

{

    int ret;

    assert(cpu_is_stopped(env) || qemu_cpu_self(env));

    ret = kvm_getput_regs(env, 1);

    if (ret < 0) {

        return ret;

    }

    ret = kvm_put_xsave(env);

    if (ret < 0) {

        return ret;

    }

    ret = kvm_put_xcrs(env);

    if (ret < 0) {

        return ret;

    }

    ret = kvm_put_sregs(env);

    if (ret < 0) {

        return ret;

    }

    ret = kvm_put_msrs(env, level);

    if (ret < 0) {

        return ret;

    }

    if (level >= KVM_PUT_RESET_STATE) {

        ret = kvm_put_mp_state(env);

        if (ret < 0) {

            return ret;

        }

    }

    ret = kvm_put_vcpu_events(env, level);

    if (ret < 0) {

        return ret;

    }

    ret = kvm_put_debugregs(env);

    if (ret < 0) {

        return ret;

    }

    /* must be last */

    ret = kvm_guest_debug_workarounds(env);

    if (ret < 0) {

        return ret;

    }

    return 0;

}


long do_sigreturn(CPUAlphaState *env)

{

    struct target_sigcontext *sc;

    abi_ulong sc_addr = env->ir[IR_A0];

    target_sigset_t target_set;

    sigset_t set;

    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {

        goto badframe;

    }

    target_sigemptyset(&target_set);

    __get_user(target_set.sig[0], &sc->sc_mask);

    target_to_host_sigset_internal(&set, &target_set);

    do_sigprocmask(SIG_SETMASK, &set, NULL);

    restore_sigcontext(env, sc);

    unlock_user_struct(sc, sc_addr, 0);

    return env->ir[IR_V0];

badframe:

    force_sig(TARGET_SIGSEGV);

}


static bool ide_sect_range_ok(IDEState *s,

                              uint64_t sector, uint64_t nb_sectors)

{

    uint64_t total_sectors;

    bdrv_get_geometry(s->bs, &total_sectors);

    if (sector > total_sectors || nb_sectors > total_sectors - sector) {

        return false;

    }

    return true;

}


int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,

                            unsigned int n)

{

    int ret = -EINPROGRESS;

    async_context_push();

    qed_write_l1_table(s, index, n, qed_sync_cb, &ret);

    while (ret == -EINPROGRESS) {

        qemu_aio_wait();

    }

    async_context_pop();

    return ret;

}


bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,

                             hwaddr size, unsigned client)

{

    assert(mr->terminates);

    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, client);

}


static void filter_mirror_setup(NetFilterState *nf, Error **errp)

{

    MirrorState *s = FILTER_MIRROR(nf);

    if (!s->outdev) {

        error_setg(errp, "filter filter mirror needs 'outdev' "

                   "property set");

        return;

    }

    s->chr_out = qemu_chr_find(s->outdev);

    if (s->chr_out == NULL) {

        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,

                  "Device '%s' not found", s->outdev);

        return;

    }

    if (qemu_chr_fe_claim(s->chr_out) != 0) {

        error_setg(errp, QERR_DEVICE_IN_USE, s->outdev);

        return;

    }

}


static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)

{

    enum { SDR = 0x4, DDR2 = 0x8 } type;

    uint8_t *spd = spd_eeprom.contents;

    uint8_t nbanks = 0;

    uint16_t density = 0;

    int i;

    /* work in terms of MB */

    ram_size >>= 20;

    while ((ram_size >= 4) && (nbanks <= 2)) {

        int sz_log2 = MIN(31 - clz32(ram_size), 14);

        nbanks++;

        density |= 1 << (sz_log2 - 2);

        ram_size -= 1 << sz_log2;

    }

    /* split to 2 banks if possible */

    if ((nbanks == 1) && (density > 1)) {

        nbanks++;

        density >>= 1;

    }

    if (density & 0xff00) {

        density = (density & 0xe0) | ((density >> 8) & 0x1f);

        type = DDR2;

    } else if (!(density & 0x1f)) {

        type = DDR2;

    } else {

        type = SDR;

    }

    if (ram_size) {

        fprintf(stderr, "Warning: SPD cannot represent final %dMB"

                " of SDRAM\n", (int)ram_size);

    }

    /* fill in SPD memory information */

    spd[2] = type;

    spd[5] = nbanks;

    spd[31] = density;

    /* checksum */

    spd[63] = 0;

    for (i = 0; i < 63; i++) {

        spd[63] += spd[i];

    }

    /* copy for SMBUS */

    memcpy(eeprom, spd, sizeof(spd_eeprom.contents));

}


static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)

{

    StringInputVisitor *siv = to_siv(v);

    Range *r;

    if (!siv->ranges || !siv->cur_range) {

        return NULL;

    }

    r = siv->cur_range->data;

    if (!r) {

        return NULL;

    }

    if (siv->cur < r->begin || siv->cur >= r->end) {

        siv->cur_range = g_list_next(siv->cur_range);

        if (!siv->cur_range) {

            return NULL;

        }

        r = siv->cur_range->data;

        if (!r) {

            return NULL;

        }

        siv->cur = r->begin;

    }

    tail->next = g_malloc0(size);

    return tail->next;

}


static int link_filter_inouts(AVFilterContext *filt_ctx,

                              AVFilterInOut **curr_inputs,

                              AVFilterInOut **open_inputs, void *log_ctx)

{

    int pad, ret;

    for (pad = 0; pad < filt_ctx->input_count; pad++) {

        AVFilterInOut *p = *curr_inputs;

        if (p)

            *curr_inputs = (*curr_inputs)->next;

        else if (!(p = av_mallocz(sizeof(*p))))

            return AVERROR(ENOMEM);

        if (p->filter_ctx) {

            if ((ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx)) < 0)

                return ret;

            av_free(p->name);

            av_free(p);

        } else {

            p->filter_ctx = filt_ctx;

            p->pad_idx = pad;

            append_inout(open_inputs, &p);

        }

    }

    if (*curr_inputs) {

        av_log(log_ctx, AV_LOG_ERROR,

               "Too many inputs specified for the \"%s\" filter.\n",

               filt_ctx->filter->name);

        return AVERROR(EINVAL);

    }

    pad = filt_ctx->output_count;

    while (pad--) {

        AVFilterInOut *currlinkn = av_mallocz(sizeof(AVFilterInOut));

        if (!currlinkn)

            return AVERROR(ENOMEM);

        currlinkn->filter_ctx  = filt_ctx;

        currlinkn->pad_idx = pad;

        insert_inout(curr_inputs, currlinkn);

    }

    return 0;

}


static void invalidate_and_set_dirty(hwaddr addr,

                                     hwaddr length)

{

    if (cpu_physical_memory_range_includes_clean(addr, length)) {

        tb_invalidate_phys_range(addr, addr + length, 0);

        cpu_physical_memory_set_dirty_range_nocode(addr, length);

    }

    xen_modified_memory(addr, length);

}


static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,

                          const char *name, int flags)

{

    int ret;

    V9fsString fullname;

    v9fs_string_init(&fullname);

    v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);

    ret = proxy_remove(ctx, fullname.data);

    v9fs_string_free(&fullname);

    return ret;

}


void virtio_scsi_common_realize(DeviceState *dev, Error **errp,

                                VirtIOHandleOutput ctrl,

                                VirtIOHandleOutput evt,

                                VirtIOHandleOutput cmd)

{

    VirtIODevice *vdev = VIRTIO_DEVICE(dev);

    VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);

    int i;

    virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,

                sizeof(VirtIOSCSIConfig));

    if (s->conf.num_queues == 0 ||

            s->conf.num_queues > VIRTIO_QUEUE_MAX - 2) {

        error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "

                         "must be a positive integer less than %d.",

                   s->conf.num_queues, VIRTIO_QUEUE_MAX - 2);

        virtio_cleanup(vdev);

        return;

    }

    s->cmd_vqs = g_new0(VirtQueue *, s->conf.num_queues);

    s->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;

    s->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;

    s->ctrl_vq = virtio_add_queue_aio(vdev, VIRTIO_SCSI_VQ_SIZE, ctrl);

    s->event_vq = virtio_add_queue_aio(vdev, VIRTIO_SCSI_VQ_SIZE, evt);

    for (i = 0; i < s->conf.num_queues; i++) {

        s->cmd_vqs[i] = virtio_add_queue_aio(vdev, VIRTIO_SCSI_VQ_SIZE, cmd);

    }

    if (s->conf.iothread) {

        virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);

    }

}


static inline void gen_intermediate_code_internal(SPARCCPU *cpu,

                                                  TranslationBlock *tb,

                                                  bool spc)

{

    CPUState *cs = CPU(cpu);

    CPUSPARCState *env = &cpu->env;

    target_ulong pc_start, last_pc;

    uint16_t *gen_opc_end;

    DisasContext dc1, *dc = &dc1;

    CPUBreakpoint *bp;

    int j, lj = -1;

    int num_insns;

    int max_insns;

    unsigned int insn;

    memset(dc, 0, sizeof(DisasContext));

    dc->tb = tb;

    pc_start = tb->pc;

    dc->pc = pc_start;

    last_pc = dc->pc;

    dc->npc = (target_ulong) tb->cs_base;

    dc->cc_op = CC_OP_DYNAMIC;

    dc->mem_idx = cpu_mmu_index(env);

    dc->def = env->def;

    dc->fpu_enabled = tb_fpu_enabled(tb->flags);

    dc->address_mask_32bit = tb_am_enabled(tb->flags);

    dc->singlestep = (cs->singlestep_enabled || singlestep);

    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;

    num_insns = 0;

    max_insns = tb->cflags & CF_COUNT_MASK;

    if (max_insns == 0)

        max_insns = CF_COUNT_MASK;

    gen_tb_start();

    do {

        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {

            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {

                if (bp->pc == dc->pc) {

                    if (dc->pc != pc_start)

                        save_state(dc);

                    gen_helper_debug(cpu_env);

                    tcg_gen_exit_tb(0);

                    dc->is_br = 1;

                    goto exit_gen_loop;

                }

            }

        }

        if (spc) {

            qemu_log("Search PC...\n");

            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;

            if (lj < j) {

                lj++;

                while (lj < j)

                    tcg_ctx.gen_opc_instr_start[lj++] = 0;

                tcg_ctx.gen_opc_pc[lj] = dc->pc;

                gen_opc_npc[lj] = dc->npc;

                tcg_ctx.gen_opc_instr_start[lj] = 1;

                tcg_ctx.gen_opc_icount[lj] = num_insns;

            }

        }

        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))

            gen_io_start();

        last_pc = dc->pc;

        insn = cpu_ldl_code(env, dc->pc);

        disas_sparc_insn(dc, insn);

        num_insns++;

        if (dc->is_br)

            break;

        /* if the next PC is different, we abort now */

        if (dc->pc != (last_pc + 4))

            break;

        /* if we reach a page boundary, we stop generation so that the

           PC of a TT_TFAULT exception is always in the right page */

        if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)

            break;

        /* if single step mode, we generate only one instruction and

           generate an exception */

        if (dc->singlestep) {

            break;

        }

    } while ((tcg_ctx.gen_opc_ptr < gen_opc_end) &&

             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&

             num_insns < max_insns);

 exit_gen_loop:

    if (tb->cflags & CF_LAST_IO) {

        gen_io_end();

    }

    if (!dc->is_br) {

        if (dc->pc != DYNAMIC_PC &&

            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {

            /* static PC and NPC: we can use direct chaining */

            gen_goto_tb(dc, 0, dc->pc, dc->npc);

        } else {

            if (dc->pc != DYNAMIC_PC) {

                tcg_gen_movi_tl(cpu_pc, dc->pc);

            }

            save_npc(dc);

            tcg_gen_exit_tb(0);

        }

    }

    gen_tb_end(tb, num_insns);

    *tcg_ctx.gen_opc_ptr = INDEX_op_end;

    if (spc) {

        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;

        lj++;

        while (lj <= j)

            tcg_ctx.gen_opc_instr_start[lj++] = 0;

#if 0

        log_page_dump();

#endif

        gen_opc_jump_pc[0] = dc->jump_pc[0];

        gen_opc_jump_pc[1] = dc->jump_pc[1];

    } else {

        tb->size = last_pc + 4 - pc_start;

        tb->icount = num_insns;

    }

#ifdef DEBUG_DISAS

    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {

        qemu_log("--------------\n");

        qemu_log("IN: %s\n", lookup_symbol(pc_start));

        log_target_disas(env, pc_start, last_pc + 4 - pc_start, 0);

        qemu_log("\n");

    }

#endif

}


static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,

                            int *is_linux, uint8_t image_type,

                            uint64_t (*translate_fn)(void *, uint64_t),

                            void *translate_opaque)

{

    int fd;

    int size;

    hwaddr address;

    uboot_image_header_t h;

    uboot_image_header_t *hdr = &h;

    uint8_t *data = NULL;

    int ret = -1;

    int do_uncompress = 0;

    fd = open(filename, O_RDONLY | O_BINARY);

    if (fd < 0)

        return -1;

    size = read(fd, hdr, sizeof(uboot_image_header_t));

    if (size < 0)

        goto out;

    bswap_uboot_header(hdr);

    if (hdr->ih_magic != IH_MAGIC)

        goto out;

    if (hdr->ih_type != image_type) {

        fprintf(stderr, "Wrong image type %d, expected %d\n", hdr->ih_type,

                image_type);

        goto out;

    }

    /* TODO: Implement other image types.  */

    switch (hdr->ih_type) {

    case IH_TYPE_KERNEL:

        address = hdr->ih_load;

        if (translate_fn) {

            address = translate_fn(translate_opaque, address);

        }

        if (loadaddr) {

            *loadaddr = hdr->ih_load;

        }

        switch (hdr->ih_comp) {

        case IH_COMP_NONE:

            break;

        case IH_COMP_GZIP:

            do_uncompress = 1;

            break;

        default:

            fprintf(stderr,

                    "Unable to load u-boot images with compression type %d\n",

                    hdr->ih_comp);

            goto out;

        }

        if (ep) {

            *ep = hdr->ih_ep;

        }

        /* TODO: Check CPU type.  */

        if (is_linux) {

            if (hdr->ih_os == IH_OS_LINUX) {

                *is_linux = 1;

            } else {

                *is_linux = 0;

            }

        }

        break;

    case IH_TYPE_RAMDISK:

        address = *loadaddr;

        break;

    default:

        fprintf(stderr, "Unsupported u-boot image type %d\n", hdr->ih_type);

        goto out;

    }

    data = g_malloc(hdr->ih_size);

    if (read(fd, data, hdr->ih_size) != hdr->ih_size) {

        fprintf(stderr, "Error reading file\n");

        goto out;

    }

    if (do_uncompress) {

        uint8_t *compressed_data;

        size_t max_bytes;

        ssize_t bytes;

        compressed_data = data;

        max_bytes = UBOOT_MAX_GUNZIP_BYTES;

        data = g_malloc(max_bytes);

        bytes = gunzip(data, max_bytes, compressed_data, hdr->ih_size);

        g_free(compressed_data);

        if (bytes < 0) {

            fprintf(stderr, "Unable to decompress gzipped image!\n");

            goto out;

        }

        hdr->ih_size = bytes;

    }

    rom_add_blob_fixed(filename, data, hdr->ih_size, address);

    ret = hdr->ih_size;

out:

    if (data)

        g_free(data);

    close(fd);

    return ret;

}


static void stellaris_init(const char *kernel_filename, const char *cpu_model,

                           DisplayState *ds, stellaris_board_info *board)

{

    static const int uart_irq[] = {5, 6, 33, 34};

    static const int timer_irq[] = {19, 21, 23, 35};

    static const uint32_t gpio_addr[7] =

      { 0x40004000, 0x40005000, 0x40006000, 0x40007000,

        0x40024000, 0x40025000, 0x40026000};

    static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};

    qemu_irq *pic;

    qemu_irq *gpio_in[7];

    qemu_irq *gpio_out[7];

    qemu_irq adc;

    int sram_size;

    int flash_size;

    i2c_bus *i2c;

    int i;

    flash_size = ((board->dc0 & 0xffff) + 1) << 1;

    sram_size = (board->dc0 >> 18) + 1;

    pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model);

    if (board->dc1 & (1 << 16)) {

        adc = stellaris_adc_init(0x40038000, pic[14]);

    } else {

        adc = NULL;

    }

    for (i = 0; i < 4; i++) {

        if (board->dc2 & (0x10000 << i)) {

            stellaris_gptm_init(0x40030000 + i * 0x1000,

                                pic[timer_irq[i]], adc);

        }

    }

    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr);

    for (i = 0; i < 7; i++) {

        if (board->dc4 & (1 << i)) {

            gpio_in[i] = pl061_init(gpio_addr[i], pic[gpio_irq[i]],

                                    &gpio_out[i]);

        }

    }

    if (board->dc2 & (1 << 12)) {

        i2c = i2c_init_bus();

        stellaris_i2c_init(0x40020000, pic[8], i2c);

        if (board->peripherals & BP_OLED_I2C) {

            ssd0303_init(ds, i2c, 0x3d);

        }

    }

    for (i = 0; i < 4; i++) {

        if (board->dc2 & (1 << i)) {

            pl011_init(0x4000c000 + i * 0x1000, pic[uart_irq[i]],

                       serial_hds[i], PL011_LUMINARY);

        }

    }

    if (board->dc2 & (1 << 4)) {

        if (board->peripherals & BP_OLED_SSI) {

            void * oled;

            void * sd;

            void *ssi_bus;

            int index;

            oled = ssd0323_init(ds, &gpio_out[GPIO_C][7]);

            index = drive_get_index(IF_SD, 0, 0);

            sd = ssi_sd_init(drives_table[index].bdrv);

            ssi_bus = stellaris_ssi_bus_init(&gpio_out[GPIO_D][0],

                                             ssi_sd_xfer, sd,

                                             ssd0323_xfer_ssi, oled);

            pl022_init(0x40008000, pic[7], stellaris_ssi_bus_xfer, ssi_bus);

            /* Make sure the select pin is high.  */

            qemu_irq_raise(gpio_out[GPIO_D][0]);

        } else {

            pl022_init(0x40008000, pic[7], NULL, NULL);

        }

    }

    if (board->dc4 & (1 << 28)) {

        /* FIXME: Obey network model.  */

        stellaris_enet_init(&nd_table[0], 0x40048000, pic[42]);

    }

    if (board->peripherals & BP_GAMEPAD) {

        qemu_irq gpad_irq[5];

        static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };

        gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */

        gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */

        gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */

        gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */

        gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */

        stellaris_gamepad_init(5, gpad_irq, gpad_keycode);

    }

}


static int pcnet_can_receive(void *opaque)

{

    PCNetState *s = opaque;

    if (CSR_STOP(s) || CSR_SPND(s))

        return 0;

    if (s->recv_pos > 0)

        return 0;

    return sizeof(s->buffer)-16;

}


static int write_object(int fd, char *buf, uint64_t oid, int copies,

                        unsigned int datalen, uint64_t offset, bool create,

                        bool cache)

{

    return read_write_object(fd, buf, oid, copies, datalen, offset, true,

                             create, cache);

}


static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)

{

    return 0;

}


void helper_iret_protected(int shift, int next_eip)

{

    int tss_selector, type;

    uint32_t e1, e2;

    /* specific case for TSS */

    if (env->eflags & NT_MASK) {

#ifdef TARGET_X86_64

        if (env->hflags & HF_LMA_MASK)

            raise_exception_err(EXCP0D_GPF, 0);

#endif

        tss_selector = lduw_kernel(env->tr.base + 0);

        if (tss_selector & 4)

            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);

        if (load_segment(&e1, &e2, tss_selector) != 0)

            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);

        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;

        /* NOTE: we check both segment and busy TSS */

        if (type != 3)

            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);

        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);

    } else {

        helper_ret_protected(shift, 1, 0);

    }

    env->hflags2 &= ~HF2_NMI_MASK;

#ifdef CONFIG_KQEMU

    if (kqemu_is_ok(env)) {

        CC_OP = CC_OP_EFLAGS;

        env->exception_index = -1;

        cpu_loop_exit();

    }

#endif

}


static void blend_image_rgba(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y)

{

    blend_image_packed_rgb(ctx, dst, src, 1, x, y, 0);

}


static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr,

                                   uint32_t val)

{

    PCIBonitoState *s = opaque;

    PCIDevice *d = PCI_DEVICE(s);

    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);

    uint32_t pciaddr;

    uint16_t status;

    DPRINTF("bonito_spciconf_writeb "TARGET_FMT_plx" val %x\n", addr, val);

    pciaddr = bonito_sbridge_pciaddr(s, addr);

    if (pciaddr == 0xffffffff) {

        return;

    }

    /* set the pci address in s->config_reg */

    phb->config_reg = (pciaddr) | (1u << 31);

    pci_data_write(phb->bus, phb->config_reg, val & 0xff, 1);

    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */

    status = pci_get_word(d->config + PCI_STATUS);

    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);

    pci_set_word(d->config + PCI_STATUS, status);

}


pvscsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid)

{

    PVSCSIRequest *pvscsi_req = req->hba_private;

    PVSCSIState *s = pvscsi_req->dev;

    if (!pvscsi_req) {

        trace_pvscsi_command_complete_not_found(req->tag);

        return;

    }

    if (resid) {

        /* Short transfer.  */

        trace_pvscsi_command_complete_data_run();

        pvscsi_req->cmp.hostStatus = BTSTAT_DATARUN;

    }

    pvscsi_req->cmp.scsiStatus = status;

    if (pvscsi_req->cmp.scsiStatus == CHECK_CONDITION) {

        uint8_t sense[SCSI_SENSE_BUF_SIZE];

        int sense_len =

            scsi_req_get_sense(pvscsi_req->sreq, sense, sizeof(sense));

        trace_pvscsi_command_complete_sense_len(sense_len);

        pvscsi_write_sense(pvscsi_req, sense, sense_len);

    }

    qemu_sglist_destroy(&pvscsi_req->sgl);

    pvscsi_complete_request(s, pvscsi_req);

}


static int proxy_open(FsContext *ctx, V9fsPath *fs_path,

                      int flags, V9fsFidOpenState *fs)

{

    fs->fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, flags);

    if (fs->fd < 0) {

        errno = -fs->fd;

        fs->fd = -1;

    }

    return fs->fd;

}


void mips_r4k_init (ram_addr_t ram_size, int vga_ram_size,

                    const char *boot_device, DisplayState *ds,

                    const char *kernel_filename, const char *kernel_cmdline,

                    const char *initrd_filename, const char *cpu_model)

{

    char buf[1024];

    unsigned long bios_offset;

    int bios_size;

    CPUState *env;

    RTCState *rtc_state;

    int i;

    qemu_irq *i8259;

    int index;

    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];

    /* init CPUs */

    if (cpu_model == NULL) {

#ifdef TARGET_MIPS64

        cpu_model = "R4000";

#else

        cpu_model = "24Kf";

#endif

    }

    env = cpu_init(cpu_model);

    if (!env) {

        fprintf(stderr, "Unable to find CPU definition\n");

        exit(1);

    }

    qemu_register_reset(main_cpu_reset, env);

    /* allocate RAM */

    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);

    if (!mips_qemu_iomemtype) {

        mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read,

                                                     mips_qemu_write, NULL);

    }

    cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);

    /* Try to load a BIOS image. If this fails, we continue regardless,

       but initialize the hardware ourselves. When a kernel gets

       preloaded we also initialize the hardware, since the BIOS wasn't

       run. */

    bios_offset = ram_size + vga_ram_size;

    if (bios_name == NULL)

        bios_name = BIOS_FILENAME;

    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);

    bios_size = load_image(buf, phys_ram_base + bios_offset);

    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {

	cpu_register_physical_memory(0x1fc00000,

				     BIOS_SIZE, bios_offset | IO_MEM_ROM);

    } else if ((index = drive_get_index(IF_PFLASH, 0, 0)) > -1) {

        uint32_t mips_rom = 0x00400000;

        cpu_register_physical_memory(0x1fc00000, mips_rom,

	                     qemu_ram_alloc(mips_rom) | IO_MEM_ROM);

        if (!pflash_cfi01_register(0x1fc00000, qemu_ram_alloc(mips_rom),

            drives_table[index].bdrv, sector_len, mips_rom / sector_len,

            4, 0, 0, 0, 0)) {

            fprintf(stderr, "qemu: Error registering flash memory.\n");

	}

    }

    else {

	/* not fatal */

        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",

		buf);

    }

    if (kernel_filename) {

        loaderparams.ram_size = ram_size;

        loaderparams.kernel_filename = kernel_filename;

        loaderparams.kernel_cmdline = kernel_cmdline;

        loaderparams.initrd_filename = initrd_filename;

        load_kernel (env);

    }

    /* Init CPU internal devices */

    cpu_mips_irq_init_cpu(env);

    cpu_mips_clock_init(env);

    /* The PIC is attached to the MIPS CPU INT0 pin */

    i8259 = i8259_init(env->irq[2]);

    rtc_state = rtc_init(0x70, i8259[8]);

    /* Register 64 KB of ISA IO space at 0x14000000 */

    isa_mmio_init(0x14000000, 0x00010000);

    isa_mem_base = 0x10000000;

    pit = pit_init(0x40, i8259[0]);

    for(i = 0; i < MAX_SERIAL_PORTS; i++) {

        if (serial_hds[i]) {

            serial_init(serial_io[i], i8259[serial_irq[i]], 115200,

                        serial_hds[i]);

        }

    }

    isa_vga_init(ds, phys_ram_base + ram_size, ram_size,

                 vga_ram_size);

    if (nd_table[0].vlan) {

        if (nd_table[i].model == NULL) {

	    nd_table[i].model = "ne2k_isa";

        }

        if (strcmp(nd_table[0].model, "ne2k_isa") == 0) {

            isa_ne2000_init(0x300, i8259[9], &nd_table[0]);

        } else if (strcmp(nd_table[0].model, "?") == 0) {

            fprintf(stderr, "qemu: Supported NICs: ne2k_isa\n");

            exit (1);

        } else {

            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);

            exit (1);

        }

    }

    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {

        fprintf(stderr, "qemu: too many IDE bus\n");

        exit(1);

    }

    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {

        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);

        if (index != -1)

            hd[i] = drives_table[index].bdrv;

        else

            hd[i] = NULL;

    }

    for(i = 0; i < MAX_IDE_BUS; i++)

        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],

                     hd[MAX_IDE_DEVS * i],

		     hd[MAX_IDE_DEVS * i + 1]);

    i8042_init(i8259[1], i8259[12], 0x60);

}


static bool spapr_drc_needed(void *opaque)

{

    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;

    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    bool rc = false;

    sPAPRDREntitySense value = drck->dr_entity_sense(drc);

    /* If no dev is plugged in there is no need to migrate the DRC state */

    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {

        return false;

    }

    /*

     * If there is dev plugged in, we need to migrate the DRC state when

     * it is different from cold-plugged state

     */

    switch (spapr_drc_type(drc)) {

    case SPAPR_DR_CONNECTOR_TYPE_PCI:

    case SPAPR_DR_CONNECTOR_TYPE_CPU:

    case SPAPR_DR_CONNECTOR_TYPE_LMB:

        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&

               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&

               drc->configured && !drc->awaiting_release);

        break;

    case SPAPR_DR_CONNECTOR_TYPE_PHB:

    case SPAPR_DR_CONNECTOR_TYPE_VIO:

    default:

        g_assert_not_reached();

    }

    return rc;

}


static inline void RENAME(yuv2yuv1)(SwsContext *c, const int16_t *lumSrc,

                                    const int16_t *chrUSrc, const int16_t *chrVSrc,

                                    const int16_t *alpSrc,

                                    uint8_t *dest, uint8_t *uDest, uint8_t *vDest,

                                    uint8_t *aDest, int dstW, int chrDstW)

{

    int p= 4;

    const uint8_t *src[4]= { alpSrc + dstW, lumSrc + dstW, chrUSrc + chrDstW, chrVSrc + chrDstW };

    uint8_t *dst[4]= { aDest, dest, uDest, vDest };

    x86_reg counter[4]= { dstW, dstW, chrDstW, chrDstW };

    while (p--) {

        if (dst[p]) {

            __asm__ volatile(

                "mov %2, %%"REG_a"                    \n\t"

                ".p2align               4             \n\t" /* FIXME Unroll? */

                "1:                                   \n\t"

                "movq  (%0, %%"REG_a", 2), %%mm0      \n\t"

                "movq 8(%0, %%"REG_a", 2), %%mm1      \n\t"

                "psraw                 $7, %%mm0      \n\t"

                "psraw                 $7, %%mm1      \n\t"

                "packuswb           %%mm1, %%mm0      \n\t"

                MOVNTQ(%%mm0, (%1, %%REGa))

                "add                   $8, %%"REG_a"  \n\t"

                "jnc                   1b             \n\t"

                :: "r" (src[p]), "r" (dst[p] + counter[p]),

                   "g" (-counter[p])

                : "%"REG_a

            );

        }

    }

}


static inline void RENAME(rgb15to16)(const uint8_t *src, uint8_t *dst, long src_size)

{

    register const uint8_t* s=src;

    register uint8_t* d=dst;

    register const uint8_t *end;

    const uint8_t *mm_end;

    end = s + src_size;

#if COMPILE_TEMPLATE_MMX

    __asm__ volatile(PREFETCH"    %0"::"m"(*s));

    __asm__ volatile("movq        %0, %%mm4"::"m"(mask15s));

    mm_end = end - 15;

    while (s<mm_end) {

        __asm__ volatile(

            PREFETCH"  32%1         \n\t"

            "movq        %1, %%mm0  \n\t"

            "movq       8%1, %%mm2  \n\t"

            "movq     %%mm0, %%mm1  \n\t"

            "movq     %%mm2, %%mm3  \n\t"

            "pand     %%mm4, %%mm0  \n\t"

            "pand     %%mm4, %%mm2  \n\t"

            "paddw    %%mm1, %%mm0  \n\t"

            "paddw    %%mm3, %%mm2  \n\t"

            MOVNTQ"   %%mm0,  %0    \n\t"

            MOVNTQ"   %%mm2, 8%0"

            :"=m"(*d)

            :"m"(*s)

        );

        d+=16;

        s+=16;

    }

    __asm__ volatile(SFENCE:::"memory");

    __asm__ volatile(EMMS:::"memory");

#endif

    mm_end = end - 3;

    while (s < mm_end) {

        register unsigned x= *((const uint32_t *)s);

        *((uint32_t *)d) = (x&0x7FFF7FFF) + (x&0x7FE07FE0);

        d+=4;

        s+=4;

    }

    if (s < end) {

        register unsigned short x= *((const uint16_t *)s);

        *((uint16_t *)d) = (x&0x7FFF) + (x&0x7FE0);

    }

}


PowerPCCPU *ppc4xx_init(const char *cpu_model,

                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,

                        uint32_t sysclk)

{

    PowerPCCPU *cpu;

    CPUPPCState *env;

    /* init CPUs */

    cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model));

    if (cpu == NULL) {

        fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",

                cpu_model);

        exit(1);

    }

    env = &cpu->env;

    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */

    cpu_clk->opaque = env;

    /* Set time-base frequency to sysclk */

    tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT);

    tb_clk->opaque = env;

    ppc_dcr_init(env, NULL, NULL);

    /* Register qemu callbacks */

    qemu_register_reset(ppc4xx_reset, cpu);

    return cpu;

}


void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
                                    int buf_size, int slice_count)
{
    struct vdpau_render_state *render, *last, *next;
    int i;
    render = (struct vdpau_render_state *)s->current_picture_ptr->data[0];
    assert(render);
    /* fill VdpPictureInfoMPEG1Or2 struct */
    render->info.mpeg.picture_structure          = s->picture_structure;
    render->info.mpeg.picture_coding_type        = s->pict_type;
    render->info.mpeg.intra_dc_precision         = s->intra_dc_precision;
    render->info.mpeg.frame_pred_frame_dct       = s->frame_pred_frame_dct;
    render->info.mpeg.concealment_motion_vectors = s->concealment_motion_vectors;
    render->info.mpeg.intra_vlc_format           = s->intra_vlc_format;
    render->info.mpeg.alternate_scan             = s->alternate_scan;
    render->info.mpeg.q_scale_type               = s->q_scale_type;
    render->info.mpeg.top_field_first            = s->top_field_first;
    render->info.mpeg.full_pel_forward_vector    = s->full_pel[0]; // MPEG-1 only.  Set 0 for MPEG-2
    render->info.mpeg.full_pel_backward_vector   = s->full_pel[1]; // MPEG-1 only.  Set 0 for MPEG-2
    render->info.mpeg.f_code[0][0]               = s->mpeg_f_code[0][0]; // For MPEG-1 fill both horiz. & vert.
    render->info.mpeg.f_code[0][1]               = s->mpeg_f_code[0][1];
    render->info.mpeg.f_code[1][0]               = s->mpeg_f_code[1][0];
    render->info.mpeg.f_code[1][1]               = s->mpeg_f_code[1][1];
    for (i = 0; i < 64; ++i) {
        render->info.mpeg.intra_quantizer_matrix[i]     = s->intra_matrix[i];
        render->info.mpeg.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
    }
    render->info.mpeg.forward_reference          = VDP_INVALID_HANDLE;
    render->info.mpeg.backward_reference         = VDP_INVALID_HANDLE;
    switch(s->pict_type){
    case  FF_B_TYPE:
        next = (struct vdpau_render_state *)s->next_picture.data[0];
        assert(next);
        render->info.mpeg.backward_reference     = next->surface;
        // no return here, going to set forward prediction
    case  FF_P_TYPE:
        last = (struct vdpau_render_state *)s->last_picture.data[0];
        if (!last) // FIXME: Does this test make sense?
            last = render; // predict second field from the first
        render->info.mpeg.forward_reference      = last->surface;
    }
    ff_vdpau_add_data_chunk(s, buf, buf_size);
    render->info.mpeg.slice_count                = slice_count;
    if (slice_count)
        ff_draw_horiz_band(s, 0, s->avctx->height);
    render->bitstream_buffers_used               = 0;
}


static int open_input_stream(HTTPContext *c, const char *info)

{

    char buf[128];

    char input_filename[1024];

    AVFormatContext *s = NULL;

    int buf_size, i, ret;

    int64_t stream_pos;

    /* find file name */

    if (c->stream->feed) {

        strcpy(input_filename, c->stream->feed->feed_filename);

        buf_size = FFM_PACKET_SIZE;

        /* compute position (absolute time) */

        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {

            if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0) {

                http_log("Invalid date specification '%s' for stream\n", buf);

                return ret;

            }

        } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {

            int prebuffer = strtol(buf, 0, 10);

            stream_pos = av_gettime() - prebuffer * (int64_t)1000000;

        } else

            stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;

    } else {

        strcpy(input_filename, c->stream->feed_filename);

        buf_size = 0;

        /* compute position (relative time) */

        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {

            if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0) {

                http_log("Invalid date specification '%s' for stream\n", buf);

                return ret;

            }

        } else

            stream_pos = 0;

    }

    if (!input_filename[0]) {

        http_log("No filename was specified for stream\n");

        return AVERROR(EINVAL);

    }

    /* open stream */

    ret = avformat_open_input(&s, input_filename, c->stream->ifmt,

                              &c->stream->in_opts);

    if (ret < 0) {

        http_log("Could not open input '%s': %s\n",

                 input_filename, av_err2str(ret));

        return ret;

    }

    /* set buffer size */

    if (buf_size > 0) {

        ret = ffio_set_buf_size(s->pb, buf_size);

        if (ret < 0) {

            http_log("Failed to set buffer size\n");

            return ret;

        }

    }

    s->flags |= AVFMT_FLAG_GENPTS;

    c->fmt_in = s;

    if (strcmp(s->iformat->name, "ffm") &&

        (ret = avformat_find_stream_info(c->fmt_in, NULL)) < 0) {

        http_log("Could not find stream info for input '%s'\n", input_filename);

        avformat_close_input(&s);

        return ret;

    }

    /* choose stream as clock source (we favor the video stream if

     * present) for packet sending */

    c->pts_stream_index = 0;

    for(i=0;i<c->stream->nb_streams;i++) {

        if (c->pts_stream_index == 0 &&

            c->stream->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {

            c->pts_stream_index = i;

        }

    }

    if (c->fmt_in->iformat->read_seek)

        av_seek_frame(c->fmt_in, -1, stream_pos, 0);

    /* set the start time (needed for maxtime and RTP packet timing) */

    c->start_time = cur_time;

    c->first_pts = AV_NOPTS_VALUE;

    return 0;

}


static int close_f(int argc, char **argv)

{

    bdrv_close(bs);

    bs = NULL;

    return 0;

}


static void pty_chr_state(CharDriverState *chr, int connected)

{

    PtyCharDriver *s = chr->opaque;

    if (!connected) {

        if (s->fd_tag) {

            io_remove_watch_poll(s->fd_tag);

            s->fd_tag = 0;

        }

        s->connected = 0;

        /* (re-)connect poll interval for idle guests: once per second.

         * We check more frequently in case the guests sends data to

         * the virtual device linked to our pty. */

        pty_chr_rearm_timer(chr, 1000);

    } else {

        if (s->timer_tag) {

            g_source_remove(s->timer_tag);

            s->timer_tag = 0;

        }

        if (!s->connected) {

            qemu_chr_be_generic_open(chr);

            s->connected = 1;

            s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr);

        }

    }

}


static void zynq_xadc_write(void *opaque, hwaddr offset, uint64_t val,

                            unsigned size)

{

    ZynqXADCState *s = (ZynqXADCState *)opaque;

    int reg = offset / 4;

    int xadc_reg;

    int xadc_cmd;

    int xadc_data;

    if (!zynq_xadc_check_offset(reg, false)) {

        qemu_log_mask(LOG_GUEST_ERROR, "zynq_xadc: Invalid write access "

                      "to addr %" HWADDR_PRIx "\n", offset);

        return;

    }

    switch (reg) {

    case CFG:

        s->regs[CFG] = val;

        break;

    case INT_STS:

        s->regs[INT_STS] &= ~val;

        break;

    case INT_MASK:

        s->regs[INT_MASK] = val & INT_ALL;

        break;

    case CMDFIFO:

        xadc_cmd  = extract32(val, 26,  4);

        xadc_reg  = extract32(val, 16, 10);

        xadc_data = extract32(val,  0, 16);

        if (s->regs[MCTL] & MCTL_RESET) {

            qemu_log_mask(LOG_GUEST_ERROR, "zynq_xadc: Sending command "

                          "while comm channel held in reset: %" PRIx32 "\n",

                          (uint32_t) val);

            break;

        }

        if (xadc_reg > ZYNQ_XADC_NUM_ADC_REGS && xadc_cmd != CMD_NOP) {

            qemu_log_mask(LOG_GUEST_ERROR, "read/write op to invalid xadc "

                          "reg 0x%x\n", xadc_reg);

            break;

        }

        switch (xadc_cmd) {

        case CMD_READ:

            xadc_push_dfifo(s, s->xadc_regs[xadc_reg]);

            break;

        case CMD_WRITE:

            s->xadc_regs[xadc_reg] = xadc_data;

            /* fallthrough */

        case CMD_NOP:

            xadc_push_dfifo(s, 0);

            break;

        }

        break;

    case MCTL:

        s->regs[MCTL] = val & 0x00fffeff;

        break;

    }

    zynq_xadc_update_ints(s);

}


static inline void gen_set_Rc0 (DisasContext *ctx)

{

    gen_op_cmpi(0);

    gen_op_set_Rc0();

}


static int kvm_log_start(CPUPhysMemoryClient *client,

                         target_phys_addr_t phys_addr, ram_addr_t size)

{

    return kvm_dirty_pages_log_change(phys_addr, size, true);

}


static int megasas_scsi_init(PCIDevice *dev)

{

    DeviceState *d = DEVICE(dev);

    MegasasState *s = MEGASAS(dev);

    MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s);

    uint8_t *pci_conf;

    int i, bar_type;

    Error *err = NULL;

    pci_conf = dev->config;

    /* PCI latency timer = 0 */

    pci_conf[PCI_LATENCY_TIMER] = 0;

    /* Interrupt pin 1 */

    pci_conf[PCI_INTERRUPT_PIN] = 0x01;

    memory_region_init_io(&s->mmio_io, OBJECT(s), &megasas_mmio_ops, s,

                          "megasas-mmio", 0x4000);

    memory_region_init_io(&s->port_io, OBJECT(s), &megasas_port_ops, s,

                          "megasas-io", 256);

    memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s,

                          "megasas-queue", 0x40000);

    if (megasas_use_msi(s) &&

        msi_init(dev, 0x50, 1, true, false)) {

        s->flags &= ~MEGASAS_MASK_USE_MSI;

    }

    if (megasas_use_msix(s) &&

        msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000,

                  &s->mmio_io, b->mmio_bar, 0x3800, 0x68)) {

        s->flags &= ~MEGASAS_MASK_USE_MSIX;

    }

    if (pci_is_express(dev)) {

        pcie_endpoint_cap_init(dev, 0xa0);

    }

    bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64;

    pci_register_bar(dev, b->ioport_bar,

                     PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);

    pci_register_bar(dev, b->mmio_bar, bar_type, &s->mmio_io);

    pci_register_bar(dev, 3, bar_type, &s->queue_io);

    if (megasas_use_msix(s)) {

        msix_vector_use(dev, 0);

    }

    s->fw_state = MFI_FWSTATE_READY;

    if (!s->sas_addr) {

        s->sas_addr = ((NAA_LOCALLY_ASSIGNED_ID << 24) |

                       IEEE_COMPANY_LOCALLY_ASSIGNED) << 36;

        s->sas_addr |= (pci_bus_num(dev->bus) << 16);

        s->sas_addr |= (PCI_SLOT(dev->devfn) << 8);

        s->sas_addr |= PCI_FUNC(dev->devfn);

    }

    if (!s->hba_serial) {

        s->hba_serial = g_strdup(MEGASAS_HBA_SERIAL);

    }

    if (s->fw_sge >= MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE) {

        s->fw_sge = MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE;

    } else if (s->fw_sge >= 128 - MFI_PASS_FRAME_SIZE) {

        s->fw_sge = 128 - MFI_PASS_FRAME_SIZE;

    } else {

        s->fw_sge = 64 - MFI_PASS_FRAME_SIZE;

    }

    if (s->fw_cmds > MEGASAS_MAX_FRAMES) {

        s->fw_cmds = MEGASAS_MAX_FRAMES;

    }

    trace_megasas_init(s->fw_sge, s->fw_cmds,

                       megasas_is_jbod(s) ? "jbod" : "raid");

    if (megasas_is_jbod(s)) {

        s->fw_luns = MFI_MAX_SYS_PDS;

    } else {

        s->fw_luns = MFI_MAX_LD;

    }

    s->producer_pa = 0;

    s->consumer_pa = 0;

    for (i = 0; i < s->fw_cmds; i++) {

        s->frames[i].index = i;

        s->frames[i].context = -1;

        s->frames[i].pa = 0;

        s->frames[i].state = s;

    }

    scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),

                 &megasas_scsi_info, NULL);

    if (!d->hotplugged) {

        scsi_bus_legacy_handle_cmdline(&s->bus, &err);

        if (err != NULL) {

            error_free(err);

            return -1;

        }

    }

    return 0;

}


VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)

{

    VirtIOBlock *s;

    int cylinders, heads, secs;

    static int virtio_blk_id;

    DriveInfo *dinfo;

    if (!conf->bs) {

        error_report("virtio-blk-pci: drive property not set");

    s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,

                                          sizeof(struct virtio_blk_config),

                                          sizeof(VirtIOBlock));

    s->vdev.get_config = virtio_blk_update_config;

    s->vdev.get_features = virtio_blk_get_features;

    s->vdev.reset = virtio_blk_reset;

    s->bs = conf->bs;

    s->conf = conf;

    s->rq = NULL;

    s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;

    bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);

    /* NB: per existing s/n string convention the string is terminated

     * by '\0' only when less than sizeof (s->sn)

     */

    dinfo = drive_get_by_blockdev(s->bs);

    strncpy(s->sn, dinfo->serial, sizeof (s->sn));

    s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);

    qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);

    register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,

                    virtio_blk_save, virtio_blk_load, s);

    bdrv_set_removable(s->bs, 0);

    return &s->vdev;


int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)

{

    BDRVQcowState *s = bs->opaque;

    QEMUSnapshotInfo *sn_tab, *sn_info;

    QCowSnapshot *sn;

    int i;

    if (!s->nb_snapshots) {

        *psn_tab = NULL;

        return s->nb_snapshots;

    }

    sn_tab = g_malloc0(s->nb_snapshots * sizeof(QEMUSnapshotInfo));

    for(i = 0; i < s->nb_snapshots; i++) {

        sn_info = sn_tab + i;

        sn = s->snapshots + i;

        pstrcpy(sn_info->id_str, sizeof(sn_info->id_str),

                sn->id_str);

        pstrcpy(sn_info->name, sizeof(sn_info->name),

                sn->name);

        sn_info->vm_state_size = sn->vm_state_size;

        sn_info->date_sec = sn->date_sec;

        sn_info->date_nsec = sn->date_nsec;

        sn_info->vm_clock_nsec = sn->vm_clock_nsec;

    }

    *psn_tab = sn_tab;

    return s->nb_snapshots;

}


DISAS_INSN(shift_reg)

{

    TCGv reg;

    TCGv shift;

    reg = DREG(insn, 0);

    shift = DREG(insn, 9);

    if (insn & 0x100) {

        gen_helper_shl_cc(reg, cpu_env, reg, shift);

    } else {

        if (insn & 8) {

            gen_helper_shr_cc(reg, cpu_env, reg, shift);

        } else {

            gen_helper_sar_cc(reg, cpu_env, reg, shift);

        }

    }

    set_cc_op(s, CC_OP_FLAGS);

}