static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,

        int64_t sector_num, int nb_sectors, int *pnum)

{

    BDRVVmdkState *s = bs->opaque;

    int64_t index_in_cluster, n, ret;

    uint64_t offset;

    VmdkExtent *extent;

    extent = find_extent(s, sector_num, NULL);

    if (!extent) {

        return 0;

    }

    qemu_co_mutex_lock(&s->lock);

    ret = get_cluster_offset(bs, extent, NULL,

                             sector_num * 512, false, &offset,

                             0, 0);

    qemu_co_mutex_unlock(&s->lock);

    switch (ret) {

    case VMDK_ERROR:

        ret = -EIO;

        break;

    case VMDK_UNALLOC:

        ret = 0;

        break;

    case VMDK_ZEROED:

        ret = BDRV_BLOCK_ZERO;

        break;

    case VMDK_OK:

        ret = BDRV_BLOCK_DATA;

        if (extent->file == bs->file && !extent->compressed) {

            ret |= BDRV_BLOCK_OFFSET_VALID | offset;

        }

        break;

    }

    index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);

    n = extent->cluster_sectors - index_in_cluster;

    if (n > nb_sectors) {

        n = nb_sectors;

    }

    *pnum = n;

    return ret;

}


static void vfio_listener_region_add(MemoryListener *listener,

                                     MemoryRegionSection *section)

{

    VFIOContainer *container = container_of(listener, VFIOContainer, listener);

    hwaddr iova, end;

    Int128 llend, llsize;

    void *vaddr;

    int ret;

    VFIOHostDMAWindow *hostwin;

    bool hostwin_found;

    if (vfio_listener_skipped_section(section)) {

        trace_vfio_listener_region_add_skip(

                section->offset_within_address_space,

                section->offset_within_address_space +

                int128_get64(int128_sub(section->size, int128_one())));

        return;

    }

    if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=

                 (section->offset_within_region & ~TARGET_PAGE_MASK))) {

        error_report("%s received unaligned region", __func__);

        return;

    }

    iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);

    llend = int128_make64(section->offset_within_address_space);

    llend = int128_add(llend, section->size);

    llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));

    if (int128_ge(int128_make64(iova), llend)) {

        return;

    }

    end = int128_get64(int128_sub(llend, int128_one()));

    if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {

        VFIOHostDMAWindow *hostwin;

        hwaddr pgsize = 0;

        /* For now intersections are not allowed, we may relax this later */

        QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {

            if (ranges_overlap(hostwin->min_iova,

                               hostwin->max_iova - hostwin->min_iova + 1,

                               section->offset_within_address_space,

                               int128_get64(section->size))) {

                ret = -1;

                goto fail;

            }

        }

        ret = vfio_spapr_create_window(container, section, &pgsize);

        if (ret) {

            goto fail;

        }

        vfio_host_win_add(container, section->offset_within_address_space,

                          section->offset_within_address_space +

                          int128_get64(section->size) - 1, pgsize);

    }

    hostwin_found = false;

    QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {

        if (hostwin->min_iova <= iova && end <= hostwin->max_iova) {

            hostwin_found = true;

            break;

        }

    }

    if (!hostwin_found) {

        error_report("vfio: IOMMU container %p can't map guest IOVA region"

                     " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,

                     container, iova, end);

        ret = -EFAULT;

        goto fail;

    }

    memory_region_ref(section->mr);

    if (memory_region_is_iommu(section->mr)) {

        VFIOGuestIOMMU *giommu;

        trace_vfio_listener_region_add_iommu(iova, end);

        /*

         * FIXME: For VFIO iommu types which have KVM acceleration to

         * avoid bouncing all map/unmaps through qemu this way, this

         * would be the right place to wire that up (tell the KVM

         * device emulation the VFIO iommu handles to use).

         */

        giommu = g_malloc0(sizeof(*giommu));

        giommu->iommu = section->mr;

        giommu->iommu_offset = section->offset_within_address_space -

                               section->offset_within_region;

        giommu->container = container;

        giommu->n.notify = vfio_iommu_map_notify;

        giommu->n.notifier_flags = IOMMU_NOTIFIER_ALL;

        QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);

        memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);

        memory_region_iommu_replay(giommu->iommu, &giommu->n, false);

        return;

    }

    /* Here we assume that memory_region_is_ram(section->mr)==true */

    vaddr = memory_region_get_ram_ptr(section->mr) +

            section->offset_within_region +

            (iova - section->offset_within_address_space);

    trace_vfio_listener_region_add_ram(iova, end, vaddr);

    llsize = int128_sub(llend, int128_make64(iova));

    ret = vfio_dma_map(container, iova, int128_get64(llsize),

                       vaddr, section->readonly);

    if (ret) {

        error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "

                     "0x%"HWADDR_PRIx", %p) = %d (%m)",

                     container, iova, int128_get64(llsize), vaddr, ret);

        goto fail;

    }

    return;

fail:

    /*

     * On the initfn path, store the first error in the container so we

     * can gracefully fail.  Runtime, there's not much we can do other

     * than throw a hardware error.

     */

    if (!container->initialized) {

        if (!container->error) {

            container->error = ret;

        }

    } else {

        hw_error("vfio: DMA mapping failed, unable to continue");

    }

}


static void niagara_init(MachineState *machine)

{

    NiagaraBoardState *s = g_new(NiagaraBoardState, 1);

    DriveInfo *dinfo = drive_get_next(IF_PFLASH);

    MemoryRegion *sysmem = get_system_memory();

    /* init CPUs */

    sparc64_cpu_devinit(machine->cpu_model, "Sun UltraSparc T1",

                        NIAGARA_PROM_BASE);

    /* set up devices */

    memory_region_allocate_system_memory(&s->hv_ram, NULL, "sun4v-hv.ram",

                                         NIAGARA_HV_RAM_SIZE);

    memory_region_add_subregion(sysmem, NIAGARA_HV_RAM_BASE, &s->hv_ram);

    memory_region_allocate_system_memory(&s->partition_ram, NULL,

                                         "sun4v-partition.ram",

                                         machine->ram_size);

    memory_region_add_subregion(sysmem, NIAGARA_PARTITION_RAM_BASE,

                                &s->partition_ram);

    memory_region_allocate_system_memory(&s->nvram, NULL,

                                         "sun4v.nvram", NIAGARA_NVRAM_SIZE);

    memory_region_add_subregion(sysmem, NIAGARA_NVRAM_BASE, &s->nvram);

    memory_region_allocate_system_memory(&s->md_rom, NULL,

                                         "sun4v-md.rom", NIAGARA_MD_ROM_SIZE);

    memory_region_add_subregion(sysmem, NIAGARA_MD_ROM_BASE, &s->md_rom);

    memory_region_allocate_system_memory(&s->hv_rom, NULL,

                                         "sun4v-hv.rom", NIAGARA_HV_ROM_SIZE);

    memory_region_add_subregion(sysmem, NIAGARA_HV_ROM_BASE, &s->hv_rom);

    memory_region_allocate_system_memory(&s->prom, NULL,

                                         "sun4v.prom", PROM_SIZE_MAX);

    memory_region_add_subregion(sysmem, NIAGARA_PROM_BASE, &s->prom);

    add_rom_or_fail("nvram1", NIAGARA_NVRAM_BASE);

    add_rom_or_fail("1up-md.bin", NIAGARA_MD_ROM_BASE);

    add_rom_or_fail("1up-hv.bin", NIAGARA_HV_ROM_BASE);

    add_rom_or_fail("reset.bin", NIAGARA_PROM_BASE);

    add_rom_or_fail("q.bin", NIAGARA_PROM_BASE + NIAGARA_Q_OFFSET);

    add_rom_or_fail("openboot.bin", NIAGARA_PROM_BASE + NIAGARA_OBP_OFFSET);

    /* the virtual ramdisk is kind of initrd, but it resides

       outside of the partition RAM */

    if (dinfo) {

        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);

        int size = blk_getlength(blk);

        if (size > 0) {

            memory_region_allocate_system_memory(&s->vdisk_ram, NULL,

                                                 "sun4v_vdisk.ram", size);

            memory_region_add_subregion(get_system_memory(),

                                        NIAGARA_VDISK_BASE, &s->vdisk_ram);

            dinfo->is_default = 1;

            rom_add_file_fixed(blk_bs(blk)->filename, NIAGARA_VDISK_BASE, -1);

        } else {

            fprintf(stderr, "qemu: could not load ram disk '%s'\n",

                    blk_bs(blk)->filename);

            exit(1);

        }

    }

    serial_mm_init(sysmem, NIAGARA_UART_BASE, 0, NULL, 115200,

                   serial_hds[0], DEVICE_BIG_ENDIAN);

    empty_slot_init(NIAGARA_IOBBASE, NIAGARA_IOBSIZE);

    sun4v_rtc_init(NIAGARA_RTC_BASE);

}


static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)

{

    uint16_t num_heads = vring_avail_idx(vq) - idx;

    /* Check it isn't doing very strange things with descriptor numbers. */

    if (num_heads > vq->vring.num) {

        error_report("Guest moved used index from %u to %u",

                     idx, vring_avail_idx(vq));

        exit(1);

    }

    /* On success, callers read a descriptor at vq->last_avail_idx.

     * Make sure descriptor read does not bypass avail index read. */

    if (num_heads) {

        smp_rmb();

    }

    return num_heads;

}


static void load_linux(void *fw_cfg,

                       target_phys_addr_t option_rom,

                       const char *kernel_filename,

		       const char *initrd_filename,

		       const char *kernel_cmdline,

               target_phys_addr_t max_ram_size)

{

    uint16_t protocol;

    uint32_t gpr[8];

    uint16_t seg[6];

    uint16_t real_seg;

    int setup_size, kernel_size, initrd_size = 0, cmdline_size;

    uint32_t initrd_max;

    uint8_t header[8192];

    target_phys_addr_t real_addr, prot_addr, cmdline_addr, initrd_addr = 0;

    FILE *f, *fi;

    char *vmode;

    /* Align to 16 bytes as a paranoia measure */

    cmdline_size = (strlen(kernel_cmdline)+16) & ~15;

    /* load the kernel header */

    f = fopen(kernel_filename, "rb");

    if (!f || !(kernel_size = get_file_size(f)) ||

	fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=

	MIN(ARRAY_SIZE(header), kernel_size)) {

	fprintf(stderr, "qemu: could not load kernel '%s': %s\n",

		kernel_filename, strerror(errno));

	exit(1);

    }

    /* kernel protocol version */

#if 0

    fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));

#endif

    if (ldl_p(header+0x202) == 0x53726448)

	protocol = lduw_p(header+0x206);

    else {

	/* This looks like a multiboot kernel. If it is, let's stop

	   treating it like a Linux kernel. */

	if (load_multiboot(fw_cfg, f, kernel_filename,

                           initrd_filename, kernel_cmdline, header))

            return;

	protocol = 0;

    }

    if (protocol < 0x200 || !(header[0x211] & 0x01)) {

	/* Low kernel */

	real_addr    = 0x90000;

	cmdline_addr = 0x9a000 - cmdline_size;

	prot_addr    = 0x10000;

    } else if (protocol < 0x202) {

	/* High but ancient kernel */

	real_addr    = 0x90000;

	cmdline_addr = 0x9a000 - cmdline_size;

	prot_addr    = 0x100000;

    } else {

	/* High and recent kernel */

	real_addr    = 0x10000;

	cmdline_addr = 0x20000;

	prot_addr    = 0x100000;

    }

#if 0

    fprintf(stderr,

	    "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"

	    "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"

	    "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",

	    real_addr,

	    cmdline_addr,

	    prot_addr);

#endif

    /* highest address for loading the initrd */

    if (protocol >= 0x203)

	initrd_max = ldl_p(header+0x22c);

    else

	initrd_max = 0x37ffffff;

    if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)

    	initrd_max = max_ram_size-ACPI_DATA_SIZE-1;

    /* kernel command line */

    pstrcpy_targphys(cmdline_addr, 4096, kernel_cmdline);

    if (protocol >= 0x202) {

	stl_p(header+0x228, cmdline_addr);

    } else {

	stw_p(header+0x20, 0xA33F);

	stw_p(header+0x22, cmdline_addr-real_addr);

    }

    /* handle vga= parameter */

    vmode = strstr(kernel_cmdline, "vga=");

    if (vmode) {

        unsigned int video_mode;

        /* skip "vga=" */

        vmode += 4;

        if (!strncmp(vmode, "normal", 6)) {

            video_mode = 0xffff;

        } else if (!strncmp(vmode, "ext", 3)) {

            video_mode = 0xfffe;

        } else if (!strncmp(vmode, "ask", 3)) {

            video_mode = 0xfffd;

        } else {

            video_mode = strtol(vmode, NULL, 0);

        }

        stw_p(header+0x1fa, video_mode);

    }

    /* loader type */

    /* High nybble = B reserved for Qemu; low nybble is revision number.

       If this code is substantially changed, you may want to consider

       incrementing the revision. */

    if (protocol >= 0x200)

	header[0x210] = 0xB0;

    /* heap */

    if (protocol >= 0x201) {

	header[0x211] |= 0x80;	/* CAN_USE_HEAP */

	stw_p(header+0x224, cmdline_addr-real_addr-0x200);

    }

    /* load initrd */

    if (initrd_filename) {

	if (protocol < 0x200) {

	    fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");

	    exit(1);

	}

	fi = fopen(initrd_filename, "rb");

	if (!fi) {

	    fprintf(stderr, "qemu: could not load initial ram disk '%s': %s\n",

		    initrd_filename, strerror(errno));

	    exit(1);

	}

	initrd_size = get_file_size(fi);

	initrd_addr = (initrd_max-initrd_size) & ~4095;

	if (!fread_targphys_ok(initrd_addr, initrd_size, fi)) {

	    fprintf(stderr, "qemu: read error on initial ram disk '%s': %s\n",

		    initrd_filename, strerror(errno));

	    exit(1);

	}

	fclose(fi);

	stl_p(header+0x218, initrd_addr);

	stl_p(header+0x21c, initrd_size);

    }

    /* store the finalized header and load the rest of the kernel */

    cpu_physical_memory_write(real_addr, header, ARRAY_SIZE(header));

    setup_size = header[0x1f1];

    if (setup_size == 0)

	setup_size = 4;

    setup_size = (setup_size+1)*512;

    /* Size of protected-mode code */

    kernel_size -= (setup_size > ARRAY_SIZE(header)) ? setup_size : ARRAY_SIZE(header);

    /* In case we have read too much already, copy that over */

    if (setup_size < ARRAY_SIZE(header)) {

        cpu_physical_memory_write(prot_addr, header + setup_size, ARRAY_SIZE(header) - setup_size);

        prot_addr += (ARRAY_SIZE(header) - setup_size);

        setup_size = ARRAY_SIZE(header);

    }

    if (!fread_targphys_ok(real_addr + ARRAY_SIZE(header),

                           setup_size - ARRAY_SIZE(header), f) ||

	!fread_targphys_ok(prot_addr, kernel_size, f)) {

	fprintf(stderr, "qemu: read error on kernel '%s'\n",

		kernel_filename);

	exit(1);

    }

    fclose(f);

    /* generate bootsector to set up the initial register state */

    real_seg = real_addr >> 4;

    seg[0] = seg[2] = seg[3] = seg[4] = seg[4] = real_seg;

    seg[1] = real_seg+0x20;	/* CS */

    memset(gpr, 0, sizeof gpr);

    gpr[4] = cmdline_addr-real_addr-16;	/* SP (-16 is paranoia) */

    option_rom_setup_reset(real_addr, setup_size);

    option_rom_setup_reset(prot_addr, kernel_size);

    option_rom_setup_reset(cmdline_addr, cmdline_size);

    if (initrd_filename)

        option_rom_setup_reset(initrd_addr, initrd_size);

    generate_bootsect(option_rom, gpr, seg, 0);

}


void qemu_boot_set(const char *boot_order, Error **errp)

{

    Error *local_err = NULL;

    if (!boot_set_handler) {

        error_setg(errp, "no function defined to set boot device list for"

                         " this architecture");

        return;

    }

    validate_bootdevices(boot_order, &local_err);

    if (local_err) {

        error_propagate(errp, local_err);

        return;

    }

    if (boot_set_handler(boot_set_opaque, boot_order)) {

        error_setg(errp, "setting boot device list failed");

        return;

    }

}


START_TEST(qdict_get_test)

{

    QInt *qi;

    QObject *obj;

    const int value = -42;

    const char *key = "test";

    qdict_put(tests_dict, key, qint_from_int(value));

    obj = qdict_get(tests_dict, key);

    fail_unless(obj != NULL);

    qi = qobject_to_qint(obj);

    fail_unless(qint_get_int(qi) == value);

}


static void rv40_h_loop_filter(uint8_t *src, int stride, int dmode,

                               int lim_q1, int lim_p1,

                               int alpha, int beta, int beta2, int chroma, int edge){

    rv40_adaptive_loop_filter(src, stride, 1, dmode, lim_q1, lim_p1,

                              alpha, beta, beta2, chroma, edge);

}


static int qio_dns_resolver_lookup_sync_nop(QIODNSResolver *resolver,

                                            SocketAddressLegacy *addr,

                                            size_t *naddrs,

                                            SocketAddressLegacy ***addrs,

                                            Error **errp)

{

    *naddrs = 1;

    *addrs = g_new0(SocketAddressLegacy *, 1);

    (*addrs)[0] = QAPI_CLONE(SocketAddressLegacy, addr);

    return 0;

}


static uint64_t ehci_opreg_read(void *ptr, hwaddr addr,

                                unsigned size)

{

    EHCIState *s = ptr;

    uint32_t val;

    val = s->opreg[addr >> 2];

    trace_usb_ehci_opreg_read(addr + s->opregbase, addr2str(addr), val);

    return val;

}


static void qemu_fflush(QEMUFile *f)

{

    int ret = 0;

    if (!f->ops->put_buffer) {

        return;

    }

    if (f->is_write && f->buf_index > 0) {

        ret = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);

        if (ret >= 0) {

            f->buf_offset += f->buf_index;

        }

        f->buf_index = 0;

    }

    if (ret < 0) {

        qemu_file_set_error(f, ret);

    }

}


static void omap_mpui_write(void *opaque, target_phys_addr_t addr,

                            uint64_t value, unsigned size)

{

    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;

    if (size != 4) {

        return omap_badwidth_write32(opaque, addr, value);

    }

    switch (addr) {

    case 0x00:	/* CTRL */

        s->mpui_ctrl = value & 0x007fffff;

        break;

    case 0x04:	/* DEBUG_ADDR */

    case 0x08:	/* DEBUG_DATA */

    case 0x0c:	/* DEBUG_FLAG */

    case 0x10:	/* STATUS */

    /* Not in OMAP310 */

    case 0x14:	/* DSP_STATUS */

        OMAP_RO_REG(addr);

    case 0x18:	/* DSP_BOOT_CONFIG */

    case 0x1c:	/* DSP_MPUI_CONFIG */

        break;

    default:

        OMAP_BAD_REG(addr);

    }

}


static void sdl_mouse_mode_change(Notifier *notify, void *data)

{

    if (kbd_mouse_is_absolute()) {

        if (!absolute_enabled) {

            sdl_hide_cursor();

            if (gui_grab) {

                sdl_grab_end();

            }

            absolute_enabled = 1;

        }

    } else if (absolute_enabled) {

	sdl_show_cursor();

	absolute_enabled = 0;

    }

}


static int mono_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer)

{

    int category_index[128];

    int quant_index_table[102];

    int category[128];

    int ret;

    memset(&category,       0, sizeof(category));

    memset(&category_index, 0, sizeof(category_index));

    if ((ret = decode_envelope(q, p, quant_index_table)) < 0)

        return ret;

    q->num_vectors = get_bits(&q->gb, p->log2_numvector_size);

    categorize(q, p, quant_index_table, category, category_index);

    expand_category(q, category, category_index);

    decode_vectors(q, p, category, quant_index_table, mlt_buffer);

    return 0;

}


static void omap_clkm_write(void *opaque, target_phys_addr_t addr,

                            uint64_t value, unsigned size)

{

    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;

    uint16_t diff;

    omap_clk clk;

    static const char *clkschemename[8] = {

        "fully synchronous", "fully asynchronous", "synchronous scalable",

        "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",

    };

    if (size != 2) {

        return omap_badwidth_write16(opaque, addr, value);

    }

    switch (addr) {

    case 0x00:	/* ARM_CKCTL */

        diff = s->clkm.arm_ckctl ^ value;

        s->clkm.arm_ckctl = value & 0x7fff;

        omap_clkm_ckctl_update(s, diff, value);

        return;

    case 0x04:	/* ARM_IDLECT1 */

        diff = s->clkm.arm_idlect1 ^ value;

        s->clkm.arm_idlect1 = value & 0x0fff;

        omap_clkm_idlect1_update(s, diff, value);

        return;

    case 0x08:	/* ARM_IDLECT2 */

        diff = s->clkm.arm_idlect2 ^ value;

        s->clkm.arm_idlect2 = value & 0x07ff;

        omap_clkm_idlect2_update(s, diff, value);

        return;

    case 0x0c:	/* ARM_EWUPCT */

        s->clkm.arm_ewupct = value & 0x003f;

        return;

    case 0x10:	/* ARM_RSTCT1 */

        diff = s->clkm.arm_rstct1 ^ value;

        s->clkm.arm_rstct1 = value & 0x0007;

        if (value & 9) {

            qemu_system_reset_request();

            s->clkm.cold_start = 0xa;

        }

        if (diff & ~value & 4) {				/* DSP_RST */

            omap_mpui_reset(s);

            omap_tipb_bridge_reset(s->private_tipb);

            omap_tipb_bridge_reset(s->public_tipb);

        }

        if (diff & 2) {						/* DSP_EN */

            clk = omap_findclk(s, "dsp_ck");

            omap_clk_canidle(clk, (~value >> 1) & 1);

        }

        return;

    case 0x14:	/* ARM_RSTCT2 */

        s->clkm.arm_rstct2 = value & 0x0001;

        return;

    case 0x18:	/* ARM_SYSST */

        if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {

            s->clkm.clocking_scheme = (value >> 11) & 7;

            printf("%s: clocking scheme set to %s\n", __FUNCTION__,

                            clkschemename[s->clkm.clocking_scheme]);

        }

        s->clkm.cold_start &= value & 0x3f;

        return;

    case 0x1c:	/* ARM_CKOUT1 */

        diff = s->clkm.arm_ckout1 ^ value;

        s->clkm.arm_ckout1 = value & 0x003f;

        omap_clkm_ckout1_update(s, diff, value);

        return;

    case 0x20:	/* ARM_CKOUT2 */

    default:

        OMAP_BAD_REG(addr);

    }

}


static int cuvid_test_dummy_decoder(AVCodecContext *avctx,

                                    const CUVIDPARSERPARAMS *cuparseinfo,

                                    int probed_width,

                                    int probed_height)

{

    CuvidContext *ctx = avctx->priv_data;

    CUVIDDECODECREATEINFO cuinfo;

    CUvideodecoder cudec = 0;

    int ret = 0;

    memset(&cuinfo, 0, sizeof(cuinfo));

    cuinfo.CodecType = cuparseinfo->CodecType;

    cuinfo.ChromaFormat = cudaVideoChromaFormat_420;

    cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12;

    cuinfo.ulWidth = probed_width;

    cuinfo.ulHeight = probed_height;

    cuinfo.ulTargetWidth = cuinfo.ulWidth;

    cuinfo.ulTargetHeight = cuinfo.ulHeight;

    cuinfo.target_rect.left = 0;

    cuinfo.target_rect.top = 0;

    cuinfo.target_rect.right = cuinfo.ulWidth;

    cuinfo.target_rect.bottom = cuinfo.ulHeight;

    cuinfo.ulNumDecodeSurfaces = ctx->nb_surfaces;

    cuinfo.ulNumOutputSurfaces = 1;

    cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID;

    cuinfo.bitDepthMinus8 = 0;

    cuinfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;

    ret = CHECK_CU(ctx->cvdl->cuvidCreateDecoder(&cudec, &cuinfo));

    if (ret < 0)

        return ret;

    ret = CHECK_CU(ctx->cvdl->cuvidDestroyDecoder(cudec));

    if (ret < 0)

        return ret;

    return 0;

}


static void vfio_intp_inject_pending_lockheld(VFIOINTp *intp)

{

    trace_vfio_platform_intp_inject_pending_lockheld(intp->pin,

                              event_notifier_get_fd(&intp->interrupt));

    intp->state = VFIO_IRQ_ACTIVE;

    /* trigger the virtual IRQ */

    qemu_set_irq(intp->qemuirq, 1);

}


void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)

{

    dprint(1, "%s:\n", __FUNCTION__);

    pthread_mutex_lock(&ssd->lock);

    memset(&ssd->dirty, 0, sizeof(ssd->dirty));

    qemu_pf_conv_put(ssd->conv);

    ssd->conv = NULL;

    pthread_mutex_unlock(&ssd->lock);

    qemu_spice_destroy_host_primary(ssd);

    qemu_spice_create_host_primary(ssd);

    pthread_mutex_lock(&ssd->lock);

    memset(&ssd->dirty, 0, sizeof(ssd->dirty));

    ssd->notify++;

    pthread_mutex_unlock(&ssd->lock);

}


void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)

{

    SaveStateEntry *se;

    QTAILQ_FOREACH(se, &savevm_handlers, entry) {

        if (se->save_live_state) {

            se->save_live_state(mon, f, -1, se->opaque);

        }

    }

}


VLANState *qemu_find_vlan(int id, int allocate)

{

    VLANState **pvlan, *vlan;

    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {

        if (vlan->id == id)

            return vlan;

    }

    if (!allocate) {

        return NULL;

    }

    vlan = qemu_mallocz(sizeof(VLANState));

    vlan->id = id;

    TAILQ_INIT(&vlan->send_queue);

    vlan->next = NULL;

    pvlan = &first_vlan;

    while (*pvlan != NULL)

        pvlan = &(*pvlan)->next;

    *pvlan = vlan;

    return vlan;

}


static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,

                               BlockDriverAmendStatusCB *status_cb)

{

    BDRVQcowState *s = bs->opaque;

    int old_version = s->qcow_version, new_version = old_version;

    uint64_t new_size = 0;

    const char *backing_file = NULL, *backing_format = NULL;

    bool lazy_refcounts = s->use_lazy_refcounts;

    const char *compat = NULL;

    uint64_t cluster_size = s->cluster_size;

    bool encrypt;

    int ret;

    QemuOptDesc *desc = opts->list->desc;

    while (desc && desc->name) {

        if (!qemu_opt_find(opts, desc->name)) {

            /* only change explicitly defined options */

            desc++;

            continue;

        }

        if (!strcmp(desc->name, BLOCK_OPT_COMPAT_LEVEL)) {

            compat = qemu_opt_get(opts, BLOCK_OPT_COMPAT_LEVEL);

            if (!compat) {

                /* preserve default */

            } else if (!strcmp(compat, "0.10")) {

                new_version = 2;

            } else if (!strcmp(compat, "1.1")) {

                new_version = 3;

            } else {

                fprintf(stderr, "Unknown compatibility level %s.\n", compat);

                return -EINVAL;

            }

        } else if (!strcmp(desc->name, BLOCK_OPT_PREALLOC)) {

            fprintf(stderr, "Cannot change preallocation mode.\n");

            return -ENOTSUP;

        } else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) {

            new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);

        } else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FILE)) {

            backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);

        } else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FMT)) {

            backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);

        } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT)) {

            encrypt = qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT,

                                        s->crypt_method);

            if (encrypt != !!s->crypt_method) {

                fprintf(stderr, "Changing the encryption flag is not "

                        "supported.\n");

                return -ENOTSUP;

            }

        } else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) {

            cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,

                                             cluster_size);

            if (cluster_size != s->cluster_size) {

                fprintf(stderr, "Changing the cluster size is not "

                        "supported.\n");

                return -ENOTSUP;

            }

        } else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {

            lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,

                                               lazy_refcounts);

        } else if (!strcmp(desc->name, BLOCK_OPT_REFCOUNT_BITS)) {

            error_report("Cannot change refcount entry width");

            return -ENOTSUP;

        } else {

            /* if this assertion fails, this probably means a new option was

             * added without having it covered here */

            assert(false);

        }

        desc++;

    }

    if (new_version != old_version) {

        if (new_version > old_version) {

            /* Upgrade */

            s->qcow_version = new_version;

            ret = qcow2_update_header(bs);

            if (ret < 0) {

                s->qcow_version = old_version;

                return ret;

            }

        } else {

            ret = qcow2_downgrade(bs, new_version, status_cb);

            if (ret < 0) {

                return ret;

            }

        }

    }

    if (backing_file || backing_format) {

        ret = qcow2_change_backing_file(bs, backing_file ?: bs->backing_file,

                                        backing_format ?: bs->backing_format);

        if (ret < 0) {

            return ret;

        }

    }

    if (s->use_lazy_refcounts != lazy_refcounts) {

        if (lazy_refcounts) {

            if (s->qcow_version < 3) {

                fprintf(stderr, "Lazy refcounts only supported with compatibility "

                        "level 1.1 and above (use compat=1.1 or greater)\n");

                return -EINVAL;

            }

            s->compatible_features |= QCOW2_COMPAT_LAZY_REFCOUNTS;

            ret = qcow2_update_header(bs);

            if (ret < 0) {

                s->compatible_features &= ~QCOW2_COMPAT_LAZY_REFCOUNTS;

                return ret;

            }

            s->use_lazy_refcounts = true;

        } else {

            /* make image clean first */

            ret = qcow2_mark_clean(bs);

            if (ret < 0) {

                return ret;

            }

            /* now disallow lazy refcounts */

            s->compatible_features &= ~QCOW2_COMPAT_LAZY_REFCOUNTS;

            ret = qcow2_update_header(bs);

            if (ret < 0) {

                s->compatible_features |= QCOW2_COMPAT_LAZY_REFCOUNTS;

                return ret;

            }

            s->use_lazy_refcounts = false;

        }

    }

    if (new_size) {

        ret = bdrv_truncate(bs, new_size);

        if (ret < 0) {

            return ret;

        }

    }

    return 0;

}


void aio_set_event_notifier(AioContext *ctx,

                            EventNotifier *e,

                            bool is_external,

                            EventNotifierHandler *io_notify,

                            AioPollFn *io_poll)

{

    AioHandler *node;

    qemu_lockcnt_lock(&ctx->list_lock);

    QLIST_FOREACH(node, &ctx->aio_handlers, node) {

        if (node->e == e && !node->deleted) {

            break;

        }

    }

    /* Are we deleting the fd handler? */

    if (!io_notify) {

        if (node) {

            g_source_remove_poll(&ctx->source, &node->pfd);

            /* aio_poll is in progress, just mark the node as deleted */

            if (qemu_lockcnt_count(&ctx->list_lock)) {

                node->deleted = 1;

                node->pfd.revents = 0;

            } else {

                /* Otherwise, delete it for real.  We can't just mark it as

                 * deleted because deleted nodes are only cleaned up after

                 * releasing the list_lock.

                 */

                QLIST_REMOVE(node, node);

                g_free(node);

            }

        }

    } else {

        if (node == NULL) {

            /* Alloc and insert if it's not already there */

            node = g_new0(AioHandler, 1);

            node->e = e;

            node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);

            node->pfd.events = G_IO_IN;

            node->is_external = is_external;

            QLIST_INSERT_HEAD_RCU(&ctx->aio_handlers, node, node);

            g_source_add_poll(&ctx->source, &node->pfd);

        }

        /* Update handler with latest information */

        node->io_notify = io_notify;

    }

    qemu_lockcnt_unlock(&ctx->list_lock);

    aio_notify(ctx);

}


static int ehci_state_fetchqtd(EHCIQueue *q)

{

    EHCIqtd qtd;

    EHCIPacket *p;

    int again = 0;

    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd,

               sizeof(EHCIqtd) >> 2);

    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);

    p = QTAILQ_FIRST(&q->packets);

    if (p != NULL) {

        if (p->qtdaddr != q->qtdaddr ||

            (!NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd.next)) ||

            (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) ||

            p->qtd.bufptr[0] != qtd.bufptr[0]) {

            ehci_cancel_queue(q);

            ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD");

            p = NULL;

        } else {

            p->qtd = qtd;

            ehci_qh_do_overlay(q);

        }

    }

    if (!(qtd.token & QTD_TOKEN_ACTIVE)) {

        if (p != NULL) {

            /* transfer canceled by guest (clear active) */

            ehci_cancel_queue(q);

            p = NULL;

        }

        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);

        again = 1;

    } else if (p != NULL) {

        switch (p->async) {

        case EHCI_ASYNC_NONE:

        case EHCI_ASYNC_INITIALIZED:

            /* Not yet executed (MULT), or previously nacked (int) packet */

            ehci_set_state(q->ehci, q->async, EST_EXECUTE);

            break;

        case EHCI_ASYNC_INFLIGHT:

            /* Unfinished async handled packet, go horizontal */

            ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);

            break;

        case EHCI_ASYNC_FINISHED:

            /*

             * We get here when advqueue moves to a packet which is already

             * finished, which can happen with packets queued up by fill_queue

             */

            ehci_set_state(q->ehci, q->async, EST_EXECUTING);

            break;

        }

        again = 1;

    } else {

        p = ehci_alloc_packet(q);

        p->qtdaddr = q->qtdaddr;

        p->qtd = qtd;

        ehci_set_state(q->ehci, q->async, EST_EXECUTE);

        again = 1;

    }

    return again;

}


int net_init_hubport(const NetClientOptions *opts, const char *name,

                     NetClientState *peer)

{

    const NetdevHubPortOptions *hubport;

    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT);

    hubport = opts->hubport;

    if (peer) {

        return -EINVAL;

    }

    net_hub_add_port(hubport->hubid, name);

    return 0;

}


int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)

{

#if defined(TARGET_HAS_ICE)

    CPUBreakpoint *bp;

    TAILQ_FOREACH(bp, &env->breakpoints, entry) {

        if (bp->pc == pc && bp->flags == flags) {

            cpu_breakpoint_remove_by_ref(env, bp);

            return 0;

        }

    }

    return -ENOENT;

#else

    return -ENOSYS;

#endif

}


static void mm_decode_inter(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)

{

    const int data_ptr = 2 + AV_RL16(&buf[0]);

    int d, r, y;

    d = data_ptr; r = 2; y = 0;

    while(r < data_ptr) {

        int i, j;

        int length = buf[r] & 0x7f;

        int x = buf[r+1] + ((buf[r] & 0x80) << 1);

        r += 2;

        if (length==0) {

            y += x;

            continue;

        }

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

            for(j=0; j<8; j++) {

                int replace = (buf[r+i] >> (7-j)) & 1;

                if (replace) {

                    int color = buf[d];

                    s->frame.data[0][y*s->frame.linesize[0] + x] = color;

                    if (half_horiz)

                        s->frame.data[0][y*s->frame.linesize[0] + x + 1] = color;

                    if (half_vert) {

                        s->frame.data[0][(y+1)*s->frame.linesize[0] + x] = color;

                        if (half_horiz)

                            s->frame.data[0][(y+1)*s->frame.linesize[0] + x + 1] = color;

                    }

                    d++;

                }

                x += half_horiz ? 2 : 1;

            }

        }

        r += length;

        y += half_vert ? 2 : 1;

    }

}


static void pxa2xx_ssp_fifo_update(PXA2xxSSPState *s)

{

    s->sssr &= ~(0xf << 12);	/* Clear RFL */

    s->sssr &= ~(0xf << 8);	/* Clear TFL */

    s->sssr &= ~SSSR_TNF;

    if (s->enable) {

        s->sssr |= ((s->rx_level - 1) & 0xf) << 12;

        if (s->rx_level >= SSCR1_RFT(s->sscr[1]))

            s->sssr |= SSSR_RFS;

        else

            s->sssr &= ~SSSR_RFS;

        if (0 <= SSCR1_TFT(s->sscr[1]))

            s->sssr |= SSSR_TFS;

        else

            s->sssr &= ~SSSR_TFS;

        if (s->rx_level)

            s->sssr |= SSSR_RNE;

        else

            s->sssr &= ~SSSR_RNE;

        s->sssr |= SSSR_TNF;

    }

    pxa2xx_ssp_int_update(s);

}


static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr,

                                uint64_t value, unsigned size)

{

    UART          *uart = opaque;

    unsigned char  c    = 0;

    addr &= 0xff;

    /* Unit registers */

    switch (addr) {

    case DATA_OFFSET:

    case DATA_OFFSET + 3:       /* When only one byte write */

        c = value & 0xFF;

        qemu_chr_fe_write(uart->chr, &c, 1);

        return;

    case STATUS_OFFSET:

        /* Read Only */

        return;

    case CONTROL_OFFSET:

        uart->control = value;

        return;

    case SCALER_OFFSET:

        /* Not supported */

        return;

    default:

        break;

    }

    trace_grlib_apbuart_writel_unknown(addr, value);

}


int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr,

                             int is_write, int is_user, int is_softmmu)

{

    uint8_t *pde_ptr, *pte_ptr;

    uint32_t pde, pte, virt_addr, ptep;

    int error_code, is_dirty, prot, page_size, ret;

    unsigned long paddr, vaddr, page_offset;

#if defined(DEBUG_MMU)

    printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n",

           addr, is_write, is_user, env->eip);

#endif

    if (env->user_mode_only) {

        /* user mode only emulation */

        error_code = 0;

        goto do_fault;

    }

    if (!(env->cr[0] & CR0_PG_MASK)) {

        pte = addr;

        virt_addr = addr & TARGET_PAGE_MASK;

        prot = PROT_READ | PROT_WRITE;

        page_size = 4096;

        goto do_mapping;

    }

    /* page directory entry */

    pde_ptr = phys_ram_base +

        (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & a20_mask);

    pde = ldl_raw(pde_ptr);

    if (!(pde & PG_PRESENT_MASK)) {

        error_code = 0;

        goto do_fault;

    }

    /* if PSE bit is set, then we use a 4MB page */

    if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {

        if (is_user) {

            if (!(pde & PG_USER_MASK))

                goto do_fault_protect;

            if (is_write && !(pde & PG_RW_MASK))

                goto do_fault_protect;

        } else {

            if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&

                is_write && !(pde & PG_RW_MASK))

                goto do_fault_protect;

        }

        is_dirty = is_write && !(pde & PG_DIRTY_MASK);

        if (!(pde & PG_ACCESSED_MASK) || is_dirty) {

            pde |= PG_ACCESSED_MASK;

            if (is_dirty)

                pde |= PG_DIRTY_MASK;

            stl_raw(pde_ptr, pde);

        }

        pte = pde & ~0x003ff000; /* align to 4MB */

        ptep = pte;

        page_size = 4096 * 1024;

        virt_addr = addr & ~0x003fffff;

    } else {

        if (!(pde & PG_ACCESSED_MASK)) {

            pde |= PG_ACCESSED_MASK;

            stl_raw(pde_ptr, pde);

        }

        /* page directory entry */

        pte_ptr = phys_ram_base +

            (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask);

        pte = ldl_raw(pte_ptr);

        if (!(pte & PG_PRESENT_MASK)) {

            error_code = 0;

            goto do_fault;

        }

        /* combine pde and pte user and rw protections */

        ptep = pte & pde;

        if (is_user) {

            if (!(ptep & PG_USER_MASK))

                goto do_fault_protect;

            if (is_write && !(ptep & PG_RW_MASK))

                goto do_fault_protect;

        } else {

            if ((env->cr[0] & CR0_WP_MASK) && (ptep & PG_USER_MASK) &&

                is_write && !(ptep & PG_RW_MASK))

                goto do_fault_protect;

        }

        is_dirty = is_write && !(pte & PG_DIRTY_MASK);

        if (!(pte & PG_ACCESSED_MASK) || is_dirty) {

            pte |= PG_ACCESSED_MASK;

            if (is_dirty)

                pte |= PG_DIRTY_MASK;

            stl_raw(pte_ptr, pte);

        }

        page_size = 4096;

        virt_addr = addr & ~0xfff;

    }

    /* the page can be put in the TLB */

    prot = PROT_READ;

    if (pte & PG_DIRTY_MASK) {

        /* only set write access if already dirty... otherwise wait

           for dirty access */

        if (is_user) {

            if (ptep & PG_RW_MASK)

                prot |= PROT_WRITE;

        } else {

            if (!(env->cr[0] & CR0_WP_MASK) || !(ptep & PG_USER_MASK) ||

                (ptep & PG_RW_MASK))

                prot |= PROT_WRITE;

        }

    }

 do_mapping:

    pte = pte & a20_mask;

    /* Even if 4MB pages, we map only one 4KB page in the cache to

       avoid filling it too fast */

    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);

    paddr = (pte & TARGET_PAGE_MASK) + page_offset;

    vaddr = virt_addr + page_offset;

    ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);

    return ret;

 do_fault_protect:

    error_code = PG_ERROR_P_MASK;

 do_fault:

    env->cr[2] = addr;

    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;

    if (is_user)

        env->error_code |= PG_ERROR_U_MASK;

    return 1;

}


static void term_delete_char(void)

{

    if (term_cmd_buf_index < term_cmd_buf_size) {

        memmove(term_cmd_buf + term_cmd_buf_index,

                term_cmd_buf + term_cmd_buf_index + 1,

                term_cmd_buf_size - term_cmd_buf_index - 1);

        term_cmd_buf_size--;

    }

}


static void sch_handle_start_func(SubchDev *sch, ORB *orb)

{

    PMCW *p = &sch->curr_status.pmcw;

    SCSW *s = &sch->curr_status.scsw;

    int path;

    int ret;

    bool suspend_allowed;

    /* Path management: In our simple css, we always choose the only path. */

    path = 0x80;

    if (!(s->ctrl & SCSW_ACTL_SUSP)) {

        /* Start Function triggered via ssch, i.e. we have an ORB */

        s->cstat = 0;

        s->dstat = 0;

        /* Look at the orb and try to execute the channel program. */

        assert(orb != NULL); /* resume does not pass an orb */

        p->intparm = orb->intparm;

        if (!(orb->lpm & path)) {

            /* Generate a deferred cc 3 condition. */

            s->flags |= SCSW_FLAGS_MASK_CC;

            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;

            s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);

            return;

        }

        sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT);

        s->flags |= (sch->ccw_fmt_1) ? SCSW_FLAGS_MASK_FMT : 0;

        sch->ccw_no_data_cnt = 0;

        suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND);

    } else {

        /* Start Function resumed via rsch, i.e. we don't have an

         * ORB */

        s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND);

        /* The channel program had been suspended before. */

        suspend_allowed = true;

    }

    sch->last_cmd_valid = false;

    do {

        ret = css_interpret_ccw(sch, sch->channel_prog, suspend_allowed);

        switch (ret) {

        case -EAGAIN:

            /* ccw chain, continue processing */

            break;

        case 0:

            /* success */

            s->ctrl &= ~SCSW_ACTL_START_PEND;

            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;

            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |

                    SCSW_STCTL_STATUS_PEND;

            s->dstat = SCSW_DSTAT_CHANNEL_END | SCSW_DSTAT_DEVICE_END;

            s->cpa = sch->channel_prog + 8;

            break;

        case -EIO:

            /* I/O errors, status depends on specific devices */

            break;

        case -ENOSYS:

            /* unsupported command, generate unit check (command reject) */

            s->ctrl &= ~SCSW_ACTL_START_PEND;

            s->dstat = SCSW_DSTAT_UNIT_CHECK;

            /* Set sense bit 0 in ecw0. */

            sch->sense_data[0] = 0x80;

            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;

            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |

                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;

            s->cpa = sch->channel_prog + 8;

            break;

        case -EFAULT:

            /* memory problem, generate channel data check */

            s->ctrl &= ~SCSW_ACTL_START_PEND;

            s->cstat = SCSW_CSTAT_DATA_CHECK;

            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;

            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |

                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;

            s->cpa = sch->channel_prog + 8;

            break;

        case -EBUSY:

            /* subchannel busy, generate deferred cc 1 */

            s->flags &= ~SCSW_FLAGS_MASK_CC;

            s->flags |= (1 << 8);

            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;

            s->ctrl |= SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;

            break;

        case -EINPROGRESS:

            /* channel program has been suspended */

            s->ctrl &= ~SCSW_ACTL_START_PEND;

            s->ctrl |= SCSW_ACTL_SUSP;

            break;

        default:

            /* error, generate channel program check */

            s->ctrl &= ~SCSW_ACTL_START_PEND;

            s->cstat = SCSW_CSTAT_PROG_CHECK;

            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;

            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |

                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;

            s->cpa = sch->channel_prog + 8;

            break;

        }

    } while (ret == -EAGAIN);

}


QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state)

{

    QEMUFileBuffered *s;

    s = g_malloc0(sizeof(*s));

    s->migration_state = migration_state;

    s->xfer_limit = migration_state->bandwidth_limit / 10;

    s->file = qemu_fopen_ops(s, &buffered_file_ops);

    s->timer = qemu_new_timer_ms(rt_clock, buffered_rate_tick, s);

    qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100);

    return s->file;

}


static int walk_memory_regions_1(struct walk_memory_regions_data *data,

                                 abi_ulong base, int level, void **lp)

{

    abi_ulong pa;

    int i, rc;

    if (*lp == NULL) {

        return walk_memory_regions_end(data, base, 0);

    }

    if (level == 0) {

        PageDesc *pd = *lp;

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

            int prot = pd[i].flags;

            pa = base | (i << TARGET_PAGE_BITS);

            if (prot != data->prot) {

                rc = walk_memory_regions_end(data, pa, prot);

                if (rc != 0) {

                    return rc;

                }

            }

        }

    } else {

        void **pp = *lp;

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

            pa = base | ((abi_ulong)i <<

                (TARGET_PAGE_BITS + L2_BITS * level));

            rc = walk_memory_regions_1(data, pa, level - 1, pp + i);

            if (rc != 0) {

                return rc;

            }

        }

    }

    return 0;

}


void helper_ldq_data(uint64_t t0, uint64_t t1)

{

    ldq_data(t1, t0);

}


static int v9fs_do_open2(V9fsState *s, V9fsCreateState *vs)

{

    FsCred cred;

    int flags;

    cred_init(&cred);

    cred.fc_uid = vs->fidp->uid;

    cred.fc_mode = vs->perm & 0777;

    flags = omode_to_uflags(vs->mode) | O_CREAT;

    return s->ops->open2(&s->ctx, vs->fullname.data, flags, &cred);

}


static inline void RENAME(vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2,

                                       uint8_t *dst1, uint8_t *dst2,

                                       long width, long height,

                                       long srcStride1, long srcStride2,

                                       long dstStride1, long dstStride2)

{

    x86_reg y;

    long x,w,h;

    w=width/2; h=height/2;

#if COMPILE_TEMPLATE_MMX

    __asm__ volatile(

        PREFETCH" %0    \n\t"

        PREFETCH" %1    \n\t"

        ::"m"(*(src1+srcStride1)),"m"(*(src2+srcStride2)):"memory");

#endif

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

        const uint8_t* s1=src1+srcStride1*(y>>1);

        uint8_t* d=dst1+dstStride1*y;

        x=0;

#if COMPILE_TEMPLATE_MMX

        for (;x<w-31;x+=32) {

            __asm__ volatile(

                PREFETCH"   32%1        \n\t"

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

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

                "movq       16%1, %%mm4 \n\t"

                "movq       24%1, %%mm6 \n\t"

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

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

                "movq      %%mm4, %%mm5 \n\t"

                "movq      %%mm6, %%mm7 \n\t"

                "punpcklbw %%mm0, %%mm0 \n\t"

                "punpckhbw %%mm1, %%mm1 \n\t"

                "punpcklbw %%mm2, %%mm2 \n\t"

                "punpckhbw %%mm3, %%mm3 \n\t"

                "punpcklbw %%mm4, %%mm4 \n\t"

                "punpckhbw %%mm5, %%mm5 \n\t"

                "punpcklbw %%mm6, %%mm6 \n\t"

                "punpckhbw %%mm7, %%mm7 \n\t"

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

                MOVNTQ"    %%mm1,  8%0  \n\t"

                MOVNTQ"    %%mm2, 16%0  \n\t"

                MOVNTQ"    %%mm3, 24%0  \n\t"

                MOVNTQ"    %%mm4, 32%0  \n\t"

                MOVNTQ"    %%mm5, 40%0  \n\t"

                MOVNTQ"    %%mm6, 48%0  \n\t"

                MOVNTQ"    %%mm7, 56%0"

                :"=m"(d[2*x])

                :"m"(s1[x])

                :"memory");

        }

#endif

        for (;x<w;x++) d[2*x]=d[2*x+1]=s1[x];

    }

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

        const uint8_t* s2=src2+srcStride2*(y>>1);

        uint8_t* d=dst2+dstStride2*y;

        x=0;

#if COMPILE_TEMPLATE_MMX

        for (;x<w-31;x+=32) {

            __asm__ volatile(

                PREFETCH"   32%1        \n\t"

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

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

                "movq       16%1, %%mm4 \n\t"

                "movq       24%1, %%mm6 \n\t"

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

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

                "movq      %%mm4, %%mm5 \n\t"

                "movq      %%mm6, %%mm7 \n\t"

                "punpcklbw %%mm0, %%mm0 \n\t"

                "punpckhbw %%mm1, %%mm1 \n\t"

                "punpcklbw %%mm2, %%mm2 \n\t"

                "punpckhbw %%mm3, %%mm3 \n\t"

                "punpcklbw %%mm4, %%mm4 \n\t"

                "punpckhbw %%mm5, %%mm5 \n\t"

                "punpcklbw %%mm6, %%mm6 \n\t"

                "punpckhbw %%mm7, %%mm7 \n\t"

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

                MOVNTQ"    %%mm1,  8%0  \n\t"

                MOVNTQ"    %%mm2, 16%0  \n\t"

                MOVNTQ"    %%mm3, 24%0  \n\t"

                MOVNTQ"    %%mm4, 32%0  \n\t"

                MOVNTQ"    %%mm5, 40%0  \n\t"

                MOVNTQ"    %%mm6, 48%0  \n\t"

                MOVNTQ"    %%mm7, 56%0"

                :"=m"(d[2*x])

                :"m"(s2[x])

                :"memory");

        }

#endif

        for (;x<w;x++) d[2*x]=d[2*x+1]=s2[x];

    }

#if COMPILE_TEMPLATE_MMX

    __asm__(

            EMMS"       \n\t"

            SFENCE"     \n\t"

            ::: "memory"

        );

#endif

}


static TranslationBlock *tb_find_slow(target_ulong pc,

                                      target_ulong cs_base,

                                      uint64_t flags)

{

    TranslationBlock *tb, **ptb1;

    unsigned int h;

    tb_page_addr_t phys_pc, phys_page1, phys_page2;

    target_ulong virt_page2;

    tb_invalidated_flag = 0;

    /* find translated block using physical mappings */

    phys_pc = get_page_addr_code(env, pc);

    phys_page1 = phys_pc & TARGET_PAGE_MASK;

    phys_page2 = -1;

    h = tb_phys_hash_func(phys_pc);

    ptb1 = &tb_phys_hash[h];

    for(;;) {

        tb = *ptb1;

        if (!tb)

            goto not_found;

        if (tb->pc == pc &&

            tb->page_addr[0] == phys_page1 &&

            tb->cs_base == cs_base &&

            tb->flags == flags) {

            /* check next page if needed */

            if (tb->page_addr[1] != -1) {

                virt_page2 = (pc & TARGET_PAGE_MASK) +

                    TARGET_PAGE_SIZE;

                phys_page2 = get_page_addr_code(env, virt_page2);

                if (tb->page_addr[1] == phys_page2)

                    goto found;

            } else {

                goto found;

            }

        }

        ptb1 = &tb->phys_hash_next;

    }

 not_found:

   /* if no translated code available, then translate it now */

    tb = tb_gen_code(env, pc, cs_base, flags, 0);

 found:

    /* Move the last found TB to the head of the list */

    if (likely(*ptb1)) {

        *ptb1 = tb->phys_hash_next;

        tb->phys_hash_next = tb_phys_hash[h];

        tb_phys_hash[h] = tb;

    }

    /* we add the TB in the virtual pc hash table */

    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;

    return tb;

}


static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd)

{

    uint32_t pa_hi, pa_lo;

    target_phys_addr_t iq_pa, initq_size;

    struct mfi_init_qinfo *initq;

    uint32_t flags;

    int ret = MFI_STAT_OK;

    pa_lo = le32_to_cpu(cmd->frame->init.qinfo_new_addr_lo);

    pa_hi = le32_to_cpu(cmd->frame->init.qinfo_new_addr_hi);

    iq_pa = (((uint64_t) pa_hi << 32) | pa_lo);

    trace_megasas_init_firmware((uint64_t)iq_pa);

    initq_size = sizeof(*initq);

    initq = cpu_physical_memory_map(iq_pa, &initq_size, 0);

    if (!initq || initq_size != sizeof(*initq)) {

        trace_megasas_initq_map_failed(cmd->index);

        s->event_count++;

        ret = MFI_STAT_MEMORY_NOT_AVAILABLE;

        goto out;

    }

    s->reply_queue_len = le32_to_cpu(initq->rq_entries) & 0xFFFF;

    if (s->reply_queue_len > s->fw_cmds) {

        trace_megasas_initq_mismatch(s->reply_queue_len, s->fw_cmds);

        s->event_count++;

        ret = MFI_STAT_INVALID_PARAMETER;

        goto out;

    }

    pa_lo = le32_to_cpu(initq->rq_addr_lo);

    pa_hi = le32_to_cpu(initq->rq_addr_hi);

    s->reply_queue_pa = ((uint64_t) pa_hi << 32) | pa_lo;

    pa_lo = le32_to_cpu(initq->ci_addr_lo);

    pa_hi = le32_to_cpu(initq->ci_addr_hi);

    s->consumer_pa = ((uint64_t) pa_hi << 32) | pa_lo;

    pa_lo = le32_to_cpu(initq->pi_addr_lo);

    pa_hi = le32_to_cpu(initq->pi_addr_hi);

    s->producer_pa = ((uint64_t) pa_hi << 32) | pa_lo;

    s->reply_queue_head = ldl_le_phys(s->producer_pa);

    s->reply_queue_tail = ldl_le_phys(s->consumer_pa);

    flags = le32_to_cpu(initq->flags);

    if (flags & MFI_QUEUE_FLAG_CONTEXT64) {

        s->flags |= MEGASAS_MASK_USE_QUEUE64;

    }

    trace_megasas_init_queue((unsigned long)s->reply_queue_pa,

                             s->reply_queue_len, s->reply_queue_head,

                             s->reply_queue_tail, flags);

    megasas_reset_frames(s);

    s->fw_state = MFI_FWSTATE_OPERATIONAL;

out:

    if (initq) {

        cpu_physical_memory_unmap(initq, initq_size, 0, 0);

    }

    return ret;

}


static void pmac_ide_writel (void *opaque,

                             target_phys_addr_t addr, uint32_t val)

{

    MACIOIDEState *d = opaque;

    addr = (addr & 0xFFF) >> 4;

    val = bswap32(val);

    if (addr == 0) {

        ide_data_writel(&d->bus, 0, val);

    }

}


static void control_out(VirtIODevice *vdev, VirtQueue *vq)

{

    VirtQueueElement elem;

    VirtIOSerial *vser;

    uint8_t *buf;

    size_t len;

    vser = VIRTIO_SERIAL(vdev);

    len = 0;

    buf = NULL;

    while (virtqueue_pop(vq, &elem)) {

        size_t cur_len;

        cur_len = iov_size(elem.out_sg, elem.out_num);

        /*

         * Allocate a new buf only if we didn't have one previously or

         * if the size of the buf differs

         */

        if (cur_len > len) {

            g_free(buf);

            buf = g_malloc(cur_len);

            len = cur_len;

        }

        iov_to_buf(elem.out_sg, elem.out_num, 0, buf, cur_len);

        handle_control_message(vser, buf, cur_len);

        virtqueue_push(vq, &elem, 0);

    }

    g_free(buf);

    virtio_notify(vdev, vq);

}