static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,

                uint32_t value)

{

    int i, tm = 0;

    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;

    switch (offset) {

    case OSMR3:  tm ++;

    case OSMR2:  tm ++;

    case OSMR1:  tm ++;

    case OSMR0:

        s->timer[tm].value = value;

        pxa2xx_timer_update(s, qemu_get_clock(vm_clock));

        break;

    case OSMR11: tm ++;

    case OSMR10: tm ++;

    case OSMR9:  tm ++;

    case OSMR8:  tm ++;

    case OSMR7:  tm ++;

    case OSMR6:  tm ++;

    case OSMR5:  tm ++;

    case OSMR4:

        if (!pxa2xx_timer_has_tm4(s))

            goto badreg;

        s->tm4[tm].tm.value = value;

        pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);

        break;

    case OSCR:

        s->oldclock = s->clock;

        s->lastload = qemu_get_clock(vm_clock);

        s->clock = value;

        pxa2xx_timer_update(s, s->lastload);

        break;

    case OSCR11: tm ++;

    case OSCR10: tm ++;

    case OSCR9:  tm ++;

    case OSCR8:  tm ++;

    case OSCR7:  tm ++;

    case OSCR6:  tm ++;

    case OSCR5:  tm ++;

    case OSCR4:

        if (!pxa2xx_timer_has_tm4(s))

            goto badreg;

        s->tm4[tm].oldclock = s->tm4[tm].clock;

        s->tm4[tm].lastload = qemu_get_clock(vm_clock);

        s->tm4[tm].clock = value;

        pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);

        break;

    case OIER:

        s->irq_enabled = value & 0xfff;

        break;

    case OSSR:	/* Status register */

        s->events &= ~value;

        for (i = 0; i < 4; i ++, value >>= 1) {

            if (s->timer[i].level && (value & 1)) {

                s->timer[i].level = 0;

                qemu_irq_lower(s->timer[i].irq);

            }

        }

        if (pxa2xx_timer_has_tm4(s)) {

            for (i = 0; i < 8; i ++, value >>= 1)

                if (s->tm4[i].tm.level && (value & 1))

                    s->tm4[i].tm.level = 0;

            if (!(s->events & 0xff0))

                qemu_irq_lower(s->tm4->tm.irq);

        }

        break;

    case OWER:	/* XXX: Reset on OSMR3 match? */

        s->reset3 = value;

        break;

    case OMCR7:  tm ++;

    case OMCR6:  tm ++;

    case OMCR5:  tm ++;

    case OMCR4:

        if (!pxa2xx_timer_has_tm4(s))

            goto badreg;

        s->tm4[tm].control = value & 0x0ff;

        /* XXX Stop if running (shouldn't happen) */

        if ((value & (1 << 7)) || tm == 0)

            s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];

        else {

            s->tm4[tm].freq = 0;

            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);

        }

        break;

    case OMCR11: tm ++;

    case OMCR10: tm ++;

    case OMCR9:  tm ++;

    case OMCR8:  tm += 4;

        if (!pxa2xx_timer_has_tm4(s))

            goto badreg;

        s->tm4[tm].control = value & 0x3ff;

        /* XXX Stop if running (shouldn't happen) */

        if ((value & (1 << 7)) || !(tm & 1))

            s->tm4[tm].freq =

                    pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];

        else {

            s->tm4[tm].freq = 0;

            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);

        }

        break;

    default:

    badreg:

        hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);

    }

}


static void mipsnet_ioport_write(void *opaque, hwaddr addr,

                                 uint64_t val, unsigned int size)

{

    MIPSnetState *s = opaque;

    addr &= 0x3f;

    trace_mipsnet_write(addr, val);

    switch (addr) {

    case MIPSNET_TX_DATA_COUNT:

	s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;

        s->tx_written = 0;

        break;

    case MIPSNET_INT_CTL:

        if (val & MIPSNET_INTCTL_TXDONE) {

            s->intctl &= ~MIPSNET_INTCTL_TXDONE;

        } else if (val & MIPSNET_INTCTL_RXDONE) {

            s->intctl &= ~MIPSNET_INTCTL_RXDONE;

        } else if (val & MIPSNET_INTCTL_TESTBIT) {

            mipsnet_reset(s);

            s->intctl |= MIPSNET_INTCTL_TESTBIT;

        } else if (!val) {

            /* ACK testbit interrupt, flag was cleared on read. */

        }

        s->busy = !!s->intctl;

        mipsnet_update_irq(s);

        if (mipsnet_can_receive(s->nic->ncs)) {

            qemu_flush_queued_packets(qemu_get_queue(s->nic));

        }

        break;

    case MIPSNET_TX_DATA_BUFFER:

        s->tx_buffer[s->tx_written++] = val;

        if (s->tx_written == s->tx_count) {

            /* Send buffer. */

            trace_mipsnet_send(s->tx_count);

            qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer, s->tx_count);

            s->tx_count = s->tx_written = 0;

            s->intctl |= MIPSNET_INTCTL_TXDONE;

            s->busy = 1;

            mipsnet_update_irq(s);

        }

        break;

    /* Read-only registers */

    case MIPSNET_DEV_ID:

    case MIPSNET_BUSY:

    case MIPSNET_RX_DATA_COUNT:

    case MIPSNET_INTERRUPT_INFO:

    case MIPSNET_RX_DATA_BUFFER:

    default:

        break;

    }

}


void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra)

{

    CRW crw;

    uint64_t addr;

    int cc;

    CPUS390XState *env = &cpu->env;

    uint8_t ar;

    addr = decode_basedisp_s(env, ipb, &ar);

    if (addr & 3) {

        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);

        return;

    }

    cc = css_do_stcrw(&crw);

    /* 0 - crw stored, 1 - zeroes stored */

    if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {

        setcc(cpu, cc);

    } else if (cc == 0) {

        /* Write failed: requeue CRW since STCRW is a suppressing instruction */

        css_undo_stcrw(&crw);

    }

}


static void migrate_put_status(QDict *qdict, const char *name,

                               uint64_t trans, uint64_t rem, uint64_t total)

{

    QObject *obj;

    obj = qobject_from_jsonf("{ 'transferred': %" PRId64 ", "

                               "'remaining': %" PRId64 ", "

                               "'total': %" PRId64 " }", trans, rem, total);

    assert(obj != NULL);

    qdict_put_obj(qdict, name, obj);

}


static int parse_pixel_format(AVCodecContext *avctx)

{

    DDSContext *ctx = avctx->priv_data;

    GetByteContext *gbc = &ctx->gbc;

    char buf[32];

    uint32_t flags, fourcc, gimp_tag;

    enum DDSDXGIFormat dxgi;

    int size, bpp, r, g, b, a;

    int alpha_exponent, ycocg_classic, ycocg_scaled, normal_map, array;

    /* Alternative DDS implementations use reserved1 as custom header. */

    bytestream2_skip(gbc, 4 * 3);

    gimp_tag = bytestream2_get_le32(gbc);

    alpha_exponent = gimp_tag == MKTAG('A', 'E', 'X', 'P');

    ycocg_classic  = gimp_tag == MKTAG('Y', 'C', 'G', '1');

    ycocg_scaled   = gimp_tag == MKTAG('Y', 'C', 'G', '2');

    bytestream2_skip(gbc, 4 * 7);

    /* Now the real DDPF starts. */

    size = bytestream2_get_le32(gbc);

    if (size != 32) {

        av_log(avctx, AV_LOG_ERROR, "Invalid pixel format header %d.\n", size);

        return AVERROR_INVALIDDATA;

    }

    flags = bytestream2_get_le32(gbc);

    ctx->compressed = flags & DDPF_FOURCC;

    ctx->paletted   = flags & DDPF_PALETTE;

    normal_map      = flags & DDPF_NORMALMAP;

    fourcc = bytestream2_get_le32(gbc);

    if (ctx->compressed && ctx->paletted) {

        av_log(avctx, AV_LOG_WARNING,

               "Disabling invalid palette flag for compressed dds.\n");

        ctx->paletted = 0;

    }

    bpp = bytestream2_get_le32(gbc); // rgbbitcount

    r   = bytestream2_get_le32(gbc); // rbitmask

    g   = bytestream2_get_le32(gbc); // gbitmask

    b   = bytestream2_get_le32(gbc); // bbitmask

    a   = bytestream2_get_le32(gbc); // abitmask

    bytestream2_skip(gbc, 4); // caps

    bytestream2_skip(gbc, 4); // caps2

    bytestream2_skip(gbc, 4); // caps3

    bytestream2_skip(gbc, 4); // caps4

    bytestream2_skip(gbc, 4); // reserved2

    av_get_codec_tag_string(buf, sizeof(buf), fourcc);

    av_log(avctx, AV_LOG_VERBOSE, "fourcc %s bpp %d "

           "r 0x%x g 0x%x b 0x%x a 0x%x\n", buf, bpp, r, g, b, a);

    if (gimp_tag) {

        av_get_codec_tag_string(buf, sizeof(buf), gimp_tag);

        av_log(avctx, AV_LOG_VERBOSE, "and GIMP-DDS tag %s\n", buf);

    }

    if (ctx->compressed)

        avctx->pix_fmt = AV_PIX_FMT_RGBA;

    if (ctx->compressed) {

        switch (fourcc) {

        case MKTAG('D', 'X', 'T', '1'):

            ctx->tex_ratio = 8;

            ctx->tex_funct = ctx->texdsp.dxt1a_block;

            break;

        case MKTAG('D', 'X', 'T', '2'):

            ctx->tex_ratio = 16;

            ctx->tex_funct = ctx->texdsp.dxt2_block;

            break;

        case MKTAG('D', 'X', 'T', '3'):

            ctx->tex_ratio = 16;

            ctx->tex_funct = ctx->texdsp.dxt3_block;

            break;

        case MKTAG('D', 'X', 'T', '4'):

            ctx->tex_ratio = 16;

            ctx->tex_funct = ctx->texdsp.dxt4_block;

            break;

        case MKTAG('D', 'X', 'T', '5'):

            ctx->tex_ratio = 16;

            if (ycocg_scaled)

                ctx->tex_funct = ctx->texdsp.dxt5ys_block;

            else if (ycocg_classic)

                ctx->tex_funct = ctx->texdsp.dxt5y_block;

            else

                ctx->tex_funct = ctx->texdsp.dxt5_block;

            break;

        case MKTAG('R', 'X', 'G', 'B'):

            ctx->tex_ratio = 16;

            ctx->tex_funct = ctx->texdsp.dxt5_block;

            /* This format may be considered as a normal map,

             * but it is handled differently in a separate postproc. */

            ctx->postproc = DDS_SWIZZLE_RXGB;

            normal_map = 0;

            break;

        case MKTAG('A', 'T', 'I', '1'):

        case MKTAG('B', 'C', '4', 'U'):

            ctx->tex_ratio = 8;

            ctx->tex_funct = ctx->texdsp.rgtc1u_block;

            break;

        case MKTAG('B', 'C', '4', 'S'):

            ctx->tex_ratio = 8;

            ctx->tex_funct = ctx->texdsp.rgtc1s_block;

            break;

        case MKTAG('A', 'T', 'I', '2'):

            /* RGT2 variant with swapped R and G (3Dc)*/

            ctx->tex_ratio = 16;

            ctx->tex_funct = ctx->texdsp.dxn3dc_block;

            break;

        case MKTAG('B', 'C', '5', 'U'):

            ctx->tex_ratio = 16;

            ctx->tex_funct = ctx->texdsp.rgtc2u_block;

            break;

        case MKTAG('B', 'C', '5', 'S'):

            ctx->tex_ratio = 16;

            ctx->tex_funct = ctx->texdsp.rgtc2s_block;

            break;

        case MKTAG('U', 'Y', 'V', 'Y'):

            ctx->compressed = 0;

            avctx->pix_fmt = AV_PIX_FMT_UYVY422;

            break;

        case MKTAG('Y', 'U', 'Y', '2'):

            ctx->compressed = 0;

            avctx->pix_fmt = AV_PIX_FMT_YUYV422;

            break;

        case MKTAG('P', '8', ' ', ' '):

            /* ATI Palette8, same as normal palette */

            ctx->compressed = 0;

            ctx->paletted   = 1;

            avctx->pix_fmt  = AV_PIX_FMT_PAL8;

            break;

        case MKTAG('D', 'X', '1', '0'):

            /* DirectX 10 extra header */

            dxgi = bytestream2_get_le32(gbc);

            bytestream2_skip(gbc, 4); // resourceDimension

            bytestream2_skip(gbc, 4); // miscFlag

            array = bytestream2_get_le32(gbc);

            bytestream2_skip(gbc, 4); // miscFlag2

            if (array != 0)

                av_log(avctx, AV_LOG_VERBOSE,

                       "Found array of size %d (ignored).\n", array);

            /* Only BC[1-5] are actually compressed. */

            ctx->compressed = (dxgi >= 70) && (dxgi <= 84);

            av_log(avctx, AV_LOG_VERBOSE, "DXGI format %d.\n", dxgi);

            switch (dxgi) {

            /* RGB types. */

            case DXGI_FORMAT_R16G16B16A16_TYPELESS:

            case DXGI_FORMAT_R16G16B16A16_FLOAT:

            case DXGI_FORMAT_R16G16B16A16_UNORM:

            case DXGI_FORMAT_R16G16B16A16_UINT:

            case DXGI_FORMAT_R16G16B16A16_SNORM:

            case DXGI_FORMAT_R16G16B16A16_SINT:

                avctx->pix_fmt = AV_PIX_FMT_BGRA64;

                break;

            case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:

                avctx->colorspace = AVCOL_SPC_RGB;

            case DXGI_FORMAT_R8G8B8A8_TYPELESS:

            case DXGI_FORMAT_R8G8B8A8_UNORM:

            case DXGI_FORMAT_R8G8B8A8_UINT:

            case DXGI_FORMAT_R8G8B8A8_SNORM:

            case DXGI_FORMAT_R8G8B8A8_SINT:

                avctx->pix_fmt = AV_PIX_FMT_BGRA;

                break;

            case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:

                avctx->colorspace = AVCOL_SPC_RGB;

            case DXGI_FORMAT_B8G8R8A8_TYPELESS:

            case DXGI_FORMAT_B8G8R8A8_UNORM:

                avctx->pix_fmt = AV_PIX_FMT_RGBA;

                break;

            case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:

                avctx->colorspace = AVCOL_SPC_RGB;

            case DXGI_FORMAT_B8G8R8X8_TYPELESS:

            case DXGI_FORMAT_B8G8R8X8_UNORM:

                avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque

                break;

            case DXGI_FORMAT_B5G6R5_UNORM:

                avctx->pix_fmt = AV_PIX_FMT_RGB565LE;

                break;

            /* Texture types. */

            case DXGI_FORMAT_BC1_UNORM_SRGB:

                avctx->colorspace = AVCOL_SPC_RGB;

            case DXGI_FORMAT_BC1_TYPELESS:

            case DXGI_FORMAT_BC1_UNORM:

                ctx->tex_ratio = 8;

                ctx->tex_funct = ctx->texdsp.dxt1a_block;

                break;

            case DXGI_FORMAT_BC2_UNORM_SRGB:

                avctx->colorspace = AVCOL_SPC_RGB;

            case DXGI_FORMAT_BC2_TYPELESS:

            case DXGI_FORMAT_BC2_UNORM:

                ctx->tex_ratio = 16;

                ctx->tex_funct = ctx->texdsp.dxt3_block;

                break;

            case DXGI_FORMAT_BC3_UNORM_SRGB:

                avctx->colorspace = AVCOL_SPC_RGB;

            case DXGI_FORMAT_BC3_TYPELESS:

            case DXGI_FORMAT_BC3_UNORM:

                ctx->tex_ratio = 16;

                ctx->tex_funct = ctx->texdsp.dxt5_block;

                break;

            case DXGI_FORMAT_BC4_TYPELESS:

            case DXGI_FORMAT_BC4_UNORM:

                ctx->tex_ratio = 8;

                ctx->tex_funct = ctx->texdsp.rgtc1u_block;

                break;

            case DXGI_FORMAT_BC4_SNORM:

                ctx->tex_ratio = 8;

                ctx->tex_funct = ctx->texdsp.rgtc1s_block;

                break;

            case DXGI_FORMAT_BC5_TYPELESS:

            case DXGI_FORMAT_BC5_UNORM:

                ctx->tex_ratio = 16;

                ctx->tex_funct = ctx->texdsp.rgtc2u_block;

                break;

            case DXGI_FORMAT_BC5_SNORM:

                ctx->tex_ratio = 16;

                ctx->tex_funct = ctx->texdsp.rgtc2s_block;

                break;

            default:

                av_log(avctx, AV_LOG_ERROR,

                       "Unsupported DXGI format %d.\n", dxgi);

                return AVERROR_INVALIDDATA;

            }

            break;

        default:

            av_log(avctx, AV_LOG_ERROR, "Unsupported %s fourcc.\n", buf);

            return AVERROR_INVALIDDATA;

        }

    } else if (ctx->paletted) {

        if (bpp == 8) {

            avctx->pix_fmt = AV_PIX_FMT_PAL8;

        } else {

            av_log(avctx, AV_LOG_ERROR, "Unsupported palette bpp %d.\n", bpp);

            return AVERROR_INVALIDDATA;

        }

    } else {

        /*  8 bpp */

        if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0)

            avctx->pix_fmt = AV_PIX_FMT_GRAY8;

        else if (bpp == 8 && r == 0 && g == 0 && b == 0 && a == 0xff)

            avctx->pix_fmt = AV_PIX_FMT_GRAY8;

        /* 16 bpp */

        else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00)

            avctx->pix_fmt = AV_PIX_FMT_YA8;

        else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0)

            avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;

        else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0)

            avctx->pix_fmt = AV_PIX_FMT_RGB555LE;

        else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0x8000)

            avctx->pix_fmt = AV_PIX_FMT_RGB555LE; // alpha ignored

        else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0)

            avctx->pix_fmt = AV_PIX_FMT_RGB565LE;

        /* 24 bpp */

        else if (bpp == 24 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)

            avctx->pix_fmt = AV_PIX_FMT_BGR24;

        /* 32 bpp */

        else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)

            avctx->pix_fmt = AV_PIX_FMT_BGRA; // opaque

        else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0)

            avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque

        else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0xff000000)

            avctx->pix_fmt = AV_PIX_FMT_BGRA;

        else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0xff000000)

            avctx->pix_fmt = AV_PIX_FMT_RGBA;

        /* give up */

        else {

            av_log(avctx, AV_LOG_ERROR, "Unknown pixel format "

                   "[bpp %d r 0x%x g 0x%x b 0x%x a 0x%x].\n", bpp, r, g, b, a);

            return AVERROR_INVALIDDATA;

        }

    }

    /* Set any remaining post-proc that should happen before frame is ready. */

    if (alpha_exponent)

        ctx->postproc = DDS_ALPHA_EXP;

    else if (normal_map)

        ctx->postproc = DDS_NORMAL_MAP;

    else if (ycocg_classic && !ctx->compressed)

        ctx->postproc = DDS_RAW_YCOCG;

    else if (avctx->pix_fmt == AV_PIX_FMT_YA8)

        ctx->postproc = DDS_SWAP_ALPHA;

    /* ATI/NVidia variants sometimes add swizzling in bpp. */

    switch (bpp) {

    case MKTAG('A', '2', 'X', 'Y'):

        ctx->postproc = DDS_SWIZZLE_A2XY;

        break;

    case MKTAG('x', 'G', 'B', 'R'):

        ctx->postproc = DDS_SWIZZLE_XGBR;

        break;

    case MKTAG('x', 'R', 'B', 'G'):

        ctx->postproc = DDS_SWIZZLE_XRBG;

        break;

    case MKTAG('R', 'B', 'x', 'G'):

        ctx->postproc = DDS_SWIZZLE_RBXG;

        break;

    case MKTAG('R', 'G', 'x', 'B'):

        ctx->postproc = DDS_SWIZZLE_RGXB;

        break;

    case MKTAG('R', 'x', 'B', 'G'):

        ctx->postproc = DDS_SWIZZLE_RXBG;

        break;

    case MKTAG('x', 'G', 'x', 'R'):

        ctx->postproc = DDS_SWIZZLE_XGXR;

        break;

    case MKTAG('A', '2', 'D', '5'):

        ctx->postproc = DDS_NORMAL_MAP;

        break;

    }

    return 0;

}


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

                            int *got_frame, AVPacket *avpkt)

{

    SVCContext *s = avctx->priv_data;

    SBufferInfo info = { 0 };

    uint8_t* ptrs[3];

    int linesize[3];

    AVFrame *avframe = data;

    DECODING_STATE state;

    state = (*s->decoder)->DecodeFrame2(s->decoder, avpkt->data, avpkt->size, ptrs, &info);

    if (state != dsErrorFree) {

        av_log(avctx, AV_LOG_ERROR, "DecodeFrame2 failed\n");

        return AVERROR_UNKNOWN;

    }

    if (info.iBufferStatus != 1) {

        av_log(avctx, AV_LOG_DEBUG, "No frame produced\n");

        return avpkt->size;

    }

    ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight);

    // The decoder doesn't (currently) support decoding into a user

    // provided buffer, so do a copy instead.

    if (ff_get_buffer(avctx, avframe, 0) < 0) {

        av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n");

        return AVERROR(ENOMEM);

    }

    linesize[0] = info.UsrData.sSystemBuffer.iStride[0];

    linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1];

    av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height);

    avframe->pts     = avpkt->pts;

    avframe->pkt_dts = avpkt->dts;

#if FF_API_PKT_PTS

FF_DISABLE_DEPRECATION_WARNINGS

    avframe->pkt_pts = avpkt->pts;

FF_ENABLE_DEPRECATION_WARNINGS

#endif

    *got_frame = 1;

    return avpkt->size;

}


PCIBus *pci_apb_init(target_phys_addr_t special_base,

                     target_phys_addr_t mem_base,

                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,

                     qemu_irq **pbm_irqs)

{

    DeviceState *dev;

    SysBusDevice *s;

    APBState *d;

    PCIDevice *pci_dev;

    PCIBridge *br;

    /* Ultrasparc PBM main bus */

    dev = qdev_create(NULL, "pbm");

    qdev_init_nofail(dev);

    s = sysbus_from_qdev(dev);

    /* apb_config */

    sysbus_mmio_map(s, 0, special_base);

    /* PCI configuration space */

    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);

    /* pci_ioport */

    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);

    d = FROM_SYSBUS(APBState, s);

    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);

    memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);

    d->bus = pci_register_bus(&d->busdev.qdev, "pci",

                              pci_apb_set_irq, pci_pbm_map_irq, d,

                              &d->pci_mmio,

                              get_system_io(),

                              0, 32);

    *pbm_irqs = d->pbm_irqs;

    d->ivec_irqs = ivec_irqs;

    pci_create_simple(d->bus, 0, "pbm-pci");

    /* APB secondary busses */

    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,

                                   "pbm-bridge");

    br = DO_UPCAST(PCIBridge, dev, pci_dev);

    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",

                       pci_apb_map_irq);

    qdev_init_nofail(&pci_dev->qdev);

    *bus2 = pci_bridge_get_sec_bus(br);

    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,

                                   "pbm-bridge");

    br = DO_UPCAST(PCIBridge, dev, pci_dev);

    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",

                       pci_apb_map_irq);

    qdev_init_nofail(&pci_dev->qdev);

    *bus3 = pci_bridge_get_sec_bus(br);

    return d->bus;

}


static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,

        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)

{

    /* Perform I/O through a temporary buffer so that users who scribble over

     * their read buffer while the operation is in progress do not end up

     * modifying the image file.  This is critical for zero-copy guest I/O

     * where anything might happen inside guest memory.

     */

    void *bounce_buffer;

    BlockDriver *drv = bs->drv;

    struct iovec iov;

    QEMUIOVector bounce_qiov;

    int64_t cluster_sector_num;

    int cluster_nb_sectors;

    size_t skip_bytes;

    int ret;

    /* Cover entire cluster so no additional backing file I/O is required when

     * allocating cluster in the image file.

     */

    bdrv_round_to_clusters(bs, sector_num, nb_sectors,

                           &cluster_sector_num, &cluster_nb_sectors);

    trace_bdrv_co_do_copy_on_readv(bs, sector_num, nb_sectors,

                                   cluster_sector_num, cluster_nb_sectors);

    iov.iov_len = cluster_nb_sectors * BDRV_SECTOR_SIZE;

    iov.iov_base = bounce_buffer = qemu_try_blockalign(bs, iov.iov_len);

    if (bounce_buffer == NULL) {

        ret = -ENOMEM;

        goto err;

    }

    qemu_iovec_init_external(&bounce_qiov, &iov, 1);

    ret = drv->bdrv_co_readv(bs, cluster_sector_num, cluster_nb_sectors,

                             &bounce_qiov);

    if (ret < 0) {

        goto err;

    }

    if (drv->bdrv_co_write_zeroes &&

        buffer_is_zero(bounce_buffer, iov.iov_len)) {

        ret = bdrv_co_do_write_zeroes(bs, cluster_sector_num,

                                      cluster_nb_sectors, 0);

    } else {

        /* This does not change the data on the disk, it is not necessary

         * to flush even in cache=writethrough mode.

         */

        ret = drv->bdrv_co_writev(bs, cluster_sector_num, cluster_nb_sectors,

                                  &bounce_qiov);

    }

    if (ret < 0) {

        /* It might be okay to ignore write errors for guest requests.  If this

         * is a deliberate copy-on-read then we don't want to ignore the error.

         * Simply report it in all cases.

         */

        goto err;

    }

    skip_bytes = (sector_num - cluster_sector_num) * BDRV_SECTOR_SIZE;

    qemu_iovec_from_buf(qiov, 0, bounce_buffer + skip_bytes,

                        nb_sectors * BDRV_SECTOR_SIZE);

err:

    qemu_vfree(bounce_buffer);

    return ret;

}


static void qmp_input_stack_object_free(StackObject *tos)

{

    if (tos->h) {

        g_hash_table_unref(tos->h);

    }

    g_free(tos);

}


bool timer_expired(QEMUTimer *timer_head, int64_t current_time)

{

    return timer_expired_ns(timer_head, current_time * timer_head->scale);

}


static void check_cmd(AHCIState *s, int port)

{

    AHCIPortRegs *pr = &s->dev[port].port_regs;

    int slot;

    if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) {

        for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) {

            if ((pr->cmd_issue & (1 << slot)) &&

                !handle_cmd(s, port, slot)) {

                pr->cmd_issue &= ~(1 << slot);

            }

        }

    }

}


static void cleanup_infolist(CommandLineParameterInfoList *head)

{

    CommandLineParameterInfoList *pre_entry, *cur, *del_entry;

    cur = head;

    while (cur->next) {

        pre_entry = head;

        while (pre_entry != cur->next) {

            if (!strcmp(pre_entry->value->name, cur->next->value->name)) {

                del_entry = cur->next;

                cur->next = cur->next->next;

                g_free(del_entry);

                break;

            }

            pre_entry = pre_entry->next;

        }

        cur = cur->next;

    }

}


static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)

{

    int l1 = gen_new_label();

    TCGv t0 = tcg_temp_new();

    TCGv_i32 t1, t2;

    /* NIP cannot be restored if the memory exception comes from an helper */

    gen_update_nip(ctx, ctx->nip - 4);

    tcg_gen_andi_tl(t0, EA, mask);

    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);

    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);

    t2 = tcg_const_i32(0);

    gen_helper_raise_exception_err(cpu_env, t1, t2);

    tcg_temp_free_i32(t1);

    tcg_temp_free_i32(t2);

    gen_set_label(l1);

    tcg_temp_free(t0);

}


_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)

#endif

#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)

_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)

#endif

#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)

_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,

          uid_t,owner,gid_t,group,int,flags)

#endif

#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \

        defined(__NR_fstatat64)

_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,

          struct stat *,buf,int,flags)

#endif

#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)

_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,

         const struct timeval *,times)

#endif

#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \

        defined(__NR_newfstatat)

_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,

          struct stat *,buf,int,flags)

#endif

#if defined(TARGET_NR_linkat) && defined(__NR_linkat)

_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,

      int,newdirfd,const char *,newpath,int,flags)

#endif

#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)

_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)

#endif

#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)

_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,

          mode_t,mode,dev_t,dev)

#endif

#if defined(TARGET_NR_openat) && defined(__NR_openat)

_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)

#endif

#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)

_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,

          char *,buf,size_t,bufsize)

#endif

#if defined(TARGET_NR_renameat) && defined(__NR_renameat)

_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,

          int,newdirfd,const char *,newpath)

#endif

#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)

_syscall3(int,sys_symlinkat,const char *,oldpath,

          int,newdirfd,const char *,newpath)

#endif

#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)

_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)

#endif

#endif /* CONFIG_ATFILE */

#ifdef CONFIG_UTIMENSAT

static int sys_utimensat(int dirfd, const char *pathname,

    const struct timespec times[2], int flags)

{

    if (pathname == NULL)

        return futimens(dirfd, times);

    else

        return utimensat(dirfd, pathname, times, flags);

}


int64_t bdrv_nb_sectors(BlockDriverState *bs)

{

    BlockDriver *drv = bs->drv;

    if (!drv)

        return -ENOMEDIUM;

    if (drv->has_variable_length) {

        int ret = refresh_total_sectors(bs, bs->total_sectors);

        if (ret < 0) {

            return ret;

        }

    }

    return bs->total_sectors;

}


static void udp_chr_update_read_handler(CharDriverState *chr)

{

    NetCharDriver *s = chr->opaque;

    if (s->tag) {

        g_source_remove(s->tag);

        s->tag = 0;

    }

    if (s->chan) {

        s->tag = io_add_watch_poll(s->chan, udp_chr_read_poll, udp_chr_read, chr);

    }

}


void qemu_system_guest_panicked(GuestPanicInformation *info)
{
    if (current_cpu) {
        current_cpu->crash_occurred = true;
    }
    qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
                                   !!info, info, &error_abort);
    vm_stop(RUN_STATE_GUEST_PANICKED);
    if (!no_shutdown) {
        qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
                                       !!info, info, &error_abort);
        qemu_system_shutdown_request();
    }
    if (info) {
        if (info->type == GUEST_PANIC_INFORMATION_KIND_HYPER_V) {
            qemu_log_mask(LOG_GUEST_ERROR, "HV crash parameters: (%#"PRIx64
                          " %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
                          info->u.hyper_v.data->arg1,
                          info->u.hyper_v.data->arg2,
                          info->u.hyper_v.data->arg3,
                          info->u.hyper_v.data->arg4,
                          info->u.hyper_v.data->arg5);
        }
        qapi_free_GuestPanicInformation(info);
    }
}


static void vp8_decode_flush(AVCodecContext *avctx)

{

    vp8_decode_flush_impl(avctx, 0, 0);

}


static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s, AVFrame *frame)
{
    int x, y;
    unsigned char P[4];
    /* 4-color encoding */
    bytestream2_get_buffer(&s->stream_ptr, P, 4);
    if (P[0] <= P[1]) {
        if (P[2] <= P[3]) {
            /* 1 of 4 colors for each pixel, need 16 more bytes */
            for (y = 0; y < 8; y++) {
                /* get the next set of 8 2-bit flags */
                int flags = bytestream2_get_le16(&s->stream_ptr);
                for (x = 0; x < 8; x++, flags >>= 2)
                    *s->pixel_ptr++ = P[flags & 0x03];
                s->pixel_ptr += s->line_inc;
        } else {
            uint32_t flags;
            /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
            flags = bytestream2_get_le32(&s->stream_ptr);
            for (y = 0; y < 8; y += 2) {
                for (x = 0; x < 8; x += 2, flags >>= 2) {
                    s->pixel_ptr[x                ] =
                    s->pixel_ptr[x + 1            ] =
                    s->pixel_ptr[x +     s->stride] =
                    s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
                s->pixel_ptr += s->stride * 2;
    } else {
        uint64_t flags;
        /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */
        flags = bytestream2_get_le64(&s->stream_ptr);
        if (P[2] <= P[3]) {
            for (y = 0; y < 8; y++) {
                for (x = 0; x < 8; x += 2, flags >>= 2) {
                    s->pixel_ptr[x    ] =
                    s->pixel_ptr[x + 1] = P[flags & 0x03];
                s->pixel_ptr += s->stride;
        } else {
            for (y = 0; y < 8; y += 2) {
                for (x = 0; x < 8; x++, flags >>= 2) {
                    s->pixel_ptr[x            ] =
                    s->pixel_ptr[x + s->stride] = P[flags & 0x03];
                s->pixel_ptr += s->stride * 2;
    /* report success */
    return 0;


static void pc_compat_0_13(MachineState *machine)

{

    pc_compat_1_2(machine);

    kvmclock_enabled = false;

}


static void do_gdbserver(int argc, const char **argv)

{

    int port;

    port = DEFAULT_GDBSTUB_PORT;

    if (argc >= 2)

        port = atoi(argv[1]);

    if (gdbserver_start(port) < 0) {

        qemu_printf("Could not open gdbserver socket on port %d\n", port);

    } else {

        qemu_printf("Waiting gdb connection on port %d\n", port);

    }

}


sofcantsendmore(struct socket *so)

{

	if ((so->so_state & SS_NOFDREF) == 0) {

            shutdown(so->s,1);           /* send FIN to fhost */

            if (global_readfds) {

                FD_CLR(so->s,global_readfds);

            }

            if (global_xfds) {

                FD_CLR(so->s,global_xfds);

            }

	}

	so->so_state &= ~(SS_ISFCONNECTING);

	if (so->so_state & SS_FCANTRCVMORE) {

	   so->so_state &= SS_PERSISTENT_MASK;

	   so->so_state |= SS_NOFDREF; /* as above */

	} else {

	   so->so_state |= SS_FCANTSENDMORE;

	}

}


static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)

{

    const char *rn = "invalid";

    if (sel != 0)

        check_insn(env, ctx, ISA_MIPS32);

    switch (reg) {

    case 0:

        switch (sel) {

        case 0:

           gen_op_mtc0_index();

            rn = "Index";

            break;

        case 1:

            check_mips_mt(env, ctx);

            gen_op_mtc0_mvpcontrol();

            rn = "MVPControl";

            break;

        case 2:

            check_mips_mt(env, ctx);

            /* ignored */

            rn = "MVPConf0";

            break;

        case 3:

            check_mips_mt(env, ctx);

            /* ignored */

            rn = "MVPConf1";

            break;

        default:

            goto die;

        }

        break;

    case 1:

        switch (sel) {

        case 0:

            /* ignored */

            rn = "Random";

            break;

        case 1:

            check_mips_mt(env, ctx);

            gen_op_mtc0_vpecontrol();

            rn = "VPEControl";

            break;

        case 2:

            check_mips_mt(env, ctx);

            gen_op_mtc0_vpeconf0();

            rn = "VPEConf0";

            break;

        case 3:

            check_mips_mt(env, ctx);

            gen_op_mtc0_vpeconf1();

            rn = "VPEConf1";

            break;

        case 4:

            check_mips_mt(env, ctx);

            gen_op_mtc0_yqmask();

            rn = "YQMask";

            break;

        case 5:

            check_mips_mt(env, ctx);

            gen_op_mtc0_vpeschedule();

            rn = "VPESchedule";

            break;

        case 6:

            check_mips_mt(env, ctx);

            gen_op_mtc0_vpeschefback();

            rn = "VPEScheFBack";

            break;

        case 7:

            check_mips_mt(env, ctx);

            gen_op_mtc0_vpeopt();

            rn = "VPEOpt";

            break;

        default:

            goto die;

        }

        break;

    case 2:

        switch (sel) {

        case 0:

            gen_op_mtc0_entrylo0();

            rn = "EntryLo0";

            break;

        case 1:

            check_mips_mt(env, ctx);

            gen_op_mtc0_tcstatus();

            rn = "TCStatus";

            break;

        case 2:

            check_mips_mt(env, ctx);

            gen_op_mtc0_tcbind();

            rn = "TCBind";

            break;

        case 3:

            check_mips_mt(env, ctx);

            gen_op_mtc0_tcrestart();

            rn = "TCRestart";

            break;

        case 4:

            check_mips_mt(env, ctx);

            gen_op_mtc0_tchalt();

            rn = "TCHalt";

            break;

        case 5:

            check_mips_mt(env, ctx);

            gen_op_mtc0_tccontext();

            rn = "TCContext";

            break;

        case 6:

            check_mips_mt(env, ctx);

            gen_op_mtc0_tcschedule();

            rn = "TCSchedule";

            break;

        case 7:

            check_mips_mt(env, ctx);

            gen_op_mtc0_tcschefback();

            rn = "TCScheFBack";

            break;

        default:

            goto die;

        }

        break;

    case 3:

        switch (sel) {

        case 0:

            gen_op_mtc0_entrylo1();

            rn = "EntryLo1";

            break;

        default:

            goto die;

        }

        break;

    case 4:

        switch (sel) {

        case 0:

            gen_op_mtc0_context();

            rn = "Context";

            break;

        case 1:

//            gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */

            rn = "ContextConfig";

//            break;

        default:

            goto die;

        }

        break;

    case 5:

        switch (sel) {

        case 0:

            gen_op_mtc0_pagemask();

            rn = "PageMask";

            break;

        case 1:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_pagegrain();

            rn = "PageGrain";

            break;

        default:

            goto die;

        }

        break;

    case 6:

        switch (sel) {

        case 0:

            gen_op_mtc0_wired();

            rn = "Wired";

            break;

        case 1:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_srsconf0();

            rn = "SRSConf0";

            break;

        case 2:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_srsconf1();

            rn = "SRSConf1";

            break;

        case 3:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_srsconf2();

            rn = "SRSConf2";

            break;

        case 4:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_srsconf3();

            rn = "SRSConf3";

            break;

        case 5:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_srsconf4();

            rn = "SRSConf4";

            break;

        default:

            goto die;

        }

        break;

    case 7:

        switch (sel) {

        case 0:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_hwrena();

            rn = "HWREna";

            break;

        default:

            goto die;

        }

        break;

    case 8:

        /* ignored */

        rn = "BadVaddr";

        break;

    case 9:

        switch (sel) {

        case 0:

            gen_op_mtc0_count();

            rn = "Count";

            break;

        /* 6,7 are implementation dependent */

        default:

            goto die;

        }

        /* Stop translation as we may have switched the execution mode */

        ctx->bstate = BS_STOP;

        break;

    case 10:

        switch (sel) {

        case 0:

            gen_op_mtc0_entryhi();

            rn = "EntryHi";

            break;

        default:

            goto die;

        }

        break;

    case 11:

        switch (sel) {

        case 0:

            gen_op_mtc0_compare();

            rn = "Compare";

            break;

        /* 6,7 are implementation dependent */

        default:

            goto die;

        }

        /* Stop translation as we may have switched the execution mode */

        ctx->bstate = BS_STOP;

        break;

    case 12:

        switch (sel) {

        case 0:

            gen_op_mtc0_status();

            /* BS_STOP isn't good enough here, hflags may have changed. */

            gen_save_pc(ctx->pc + 4);

            ctx->bstate = BS_EXCP;

            rn = "Status";

            break;

        case 1:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_intctl();

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

            rn = "IntCtl";

            break;

        case 2:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_srsctl();

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

            rn = "SRSCtl";

            break;

        case 3:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_srsmap();

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

            rn = "SRSMap";

            break;

        default:

            goto die;

        }

        break;

    case 13:

        switch (sel) {

        case 0:

            gen_op_mtc0_cause();

            rn = "Cause";

            break;

        default:

            goto die;

        }

        /* Stop translation as we may have switched the execution mode */

        ctx->bstate = BS_STOP;

        break;

    case 14:

        switch (sel) {

        case 0:

            gen_op_mtc0_epc();

            rn = "EPC";

            break;

        default:

            goto die;

        }

        break;

    case 15:

        switch (sel) {

        case 0:

            /* ignored */

            rn = "PRid";

            break;

        case 1:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mtc0_ebase();

            rn = "EBase";

            break;

        default:

            goto die;

        }

        break;

    case 16:

        switch (sel) {

        case 0:

            gen_op_mtc0_config0();

            rn = "Config";

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

            break;

        case 1:

            /* ignored, read only */

            rn = "Config1";

            break;

        case 2:

            gen_op_mtc0_config2();

            rn = "Config2";

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

            break;

        case 3:

            /* ignored, read only */

            rn = "Config3";

            break;

        /* 4,5 are reserved */

        /* 6,7 are implementation dependent */

        case 6:

            /* ignored */

            rn = "Config6";

            break;

        case 7:

            /* ignored */

            rn = "Config7";

            break;

        default:

            rn = "Invalid config selector";

            goto die;

        }

        break;

    case 17:

        switch (sel) {

        case 0:

            /* ignored */

            rn = "LLAddr";

            break;

        default:

            goto die;

        }

        break;

    case 18:

        switch (sel) {

        case 0 ... 7:

            gen_op_mtc0_watchlo(sel);

            rn = "WatchLo";

            break;

        default:

            goto die;

        }

        break;

    case 19:

        switch (sel) {

        case 0 ... 7:

            gen_op_mtc0_watchhi(sel);

            rn = "WatchHi";

            break;

        default:

            goto die;

        }

        break;

    case 20:

        switch (sel) {

        case 0:

#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)

            check_insn(env, ctx, ISA_MIPS3);

            gen_op_mtc0_xcontext();

            rn = "XContext";

            break;

#endif

        default:

            goto die;

        }

        break;

    case 21:

       /* Officially reserved, but sel 0 is used for R1x000 framemask */

        switch (sel) {

        case 0:

            gen_op_mtc0_framemask();

            rn = "Framemask";

            break;

        default:

            goto die;

        }

        break;

    case 22:

        /* ignored */

        rn = "Diagnostic"; /* implementation dependent */

        break;

    case 23:

        switch (sel) {

        case 0:

            gen_op_mtc0_debug(); /* EJTAG support */

            /* BS_STOP isn't good enough here, hflags may have changed. */

            gen_save_pc(ctx->pc + 4);

            ctx->bstate = BS_EXCP;

            rn = "Debug";

            break;

        case 1:

//            gen_op_mtc0_tracecontrol(); /* PDtrace support */

            rn = "TraceControl";

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

//            break;

        case 2:

//            gen_op_mtc0_tracecontrol2(); /* PDtrace support */

            rn = "TraceControl2";

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

//            break;

        case 3:

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

//            gen_op_mtc0_usertracedata(); /* PDtrace support */

            rn = "UserTraceData";

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

//            break;

        case 4:

//            gen_op_mtc0_debug(); /* PDtrace support */

            /* Stop translation as we may have switched the execution mode */

            ctx->bstate = BS_STOP;

            rn = "TraceBPC";

//            break;

        default:

            goto die;

        }

        break;

    case 24:

        switch (sel) {

        case 0:

            gen_op_mtc0_depc(); /* EJTAG support */

            rn = "DEPC";

            break;

        default:

            goto die;

        }

        break;

    case 25:

        switch (sel) {

        case 0:

            gen_op_mtc0_performance0();

            rn = "Performance0";

            break;

        case 1:

//            gen_op_mtc0_performance1();

            rn = "Performance1";

//            break;

        case 2:

//            gen_op_mtc0_performance2();

            rn = "Performance2";

//            break;

        case 3:

//            gen_op_mtc0_performance3();

            rn = "Performance3";

//            break;

        case 4:

//            gen_op_mtc0_performance4();

            rn = "Performance4";

//            break;

        case 5:

//            gen_op_mtc0_performance5();

            rn = "Performance5";

//            break;

        case 6:

//            gen_op_mtc0_performance6();

            rn = "Performance6";

//            break;

        case 7:

//            gen_op_mtc0_performance7();

            rn = "Performance7";

//            break;

        default:

            goto die;

        }

       break;

    case 26:

        /* ignored */

        rn = "ECC";

        break;

    case 27:

        switch (sel) {

        case 0 ... 3:

            /* ignored */

            rn = "CacheErr";

            break;

        default:

            goto die;

        }

       break;

    case 28:

        switch (sel) {

        case 0:

        case 2:

        case 4:

        case 6:

            gen_op_mtc0_taglo();

            rn = "TagLo";

            break;

        case 1:

        case 3:

        case 5:

        case 7:

            gen_op_mtc0_datalo();

            rn = "DataLo";

            break;

        default:

            goto die;

        }

        break;

    case 29:

        switch (sel) {

        case 0:

        case 2:

        case 4:

        case 6:

            gen_op_mtc0_taghi();

            rn = "TagHi";

            break;

        case 1:

        case 3:

        case 5:

        case 7:

            gen_op_mtc0_datahi();

            rn = "DataHi";

            break;

        default:

            rn = "invalid sel";

            goto die;

        }

       break;

    case 30:

        switch (sel) {

        case 0:

            gen_op_mtc0_errorepc();

            rn = "ErrorEPC";

            break;

        default:

            goto die;

        }

        break;

    case 31:

        switch (sel) {

        case 0:

            gen_op_mtc0_desave(); /* EJTAG support */

            rn = "DESAVE";

            break;

        default:

            goto die;

        }

        /* Stop translation as we may have switched the execution mode */

        ctx->bstate = BS_STOP;

        break;

    default:

       goto die;

    }

#if defined MIPS_DEBUG_DISAS

    if (loglevel & CPU_LOG_TB_IN_ASM) {

        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",

                rn, reg, sel);

    }

#endif

    return;

die:

#if defined MIPS_DEBUG_DISAS

    if (loglevel & CPU_LOG_TB_IN_ASM) {

        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",

                rn, reg, sel);

    }

#endif

    generate_exception(ctx, EXCP_RI);

}


static void thread_pool_init(void)

{

    thread_pool_init_one(&global_pool, NULL);

}


static void handle_notify(EventNotifier *e)

{

    VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,

                                           host_notifier);

    VirtQueueElement *elem;

    VirtIOBlockReq *req;

    int ret;

    MultiReqBuffer mrb = {

        .num_writes = 0,

    };

    event_notifier_test_and_clear(&s->host_notifier);

    bdrv_io_plug(s->blk->conf.bs);

    for (;;) {

        /* Disable guest->host notifies to avoid unnecessary vmexits */

        vring_disable_notification(s->vdev, &s->vring);

        for (;;) {

            ret = vring_pop(s->vdev, &s->vring, &elem);

            if (ret < 0) {

                assert(elem == NULL);

                break; /* no more requests */

            }

            trace_virtio_blk_data_plane_process_request(s, elem->out_num,

                                                        elem->in_num, elem->index);

            req = g_slice_new(VirtIOBlockReq);

            req->dev = VIRTIO_BLK(s->vdev);

            req->elem = elem;

            virtio_blk_handle_request(req, &mrb);

        }

        virtio_submit_multiwrite(s->blk->conf.bs, &mrb);

        if (likely(ret == -EAGAIN)) { /* vring emptied */

            /* Re-enable guest->host notifies and stop processing the vring.

             * But if the guest has snuck in more descriptors, keep processing.

             */

            if (vring_enable_notification(s->vdev, &s->vring)) {

                break;

            }

        } else { /* fatal error */

            break;

        }

    }

    bdrv_io_unplug(s->blk->conf.bs);

}


static int get_int32_equal(QEMUFile *f, void *pv, size_t size,

                           VMStateField *field)

{

    int32_t *v = pv;

    int32_t v2;

    qemu_get_sbe32s(f, &v2);

    if (*v == v2) {

        return 0;

    error_report("%" PRIx32 " != %" PRIx32, *v, v2);

    return -EINVAL;


static int select_input_picture(MpegEncContext *s)

{

    int i, ret;

    for (i = 1; i < MAX_PICTURE_COUNT; i++)

        s->reordered_input_picture[i - 1] = s->reordered_input_picture[i];

    s->reordered_input_picture[MAX_PICTURE_COUNT - 1] = NULL;

    /* set next picture type & ordering */

    if (s->reordered_input_picture[0] == NULL && s->input_picture[0]) {

        if (/*s->picture_in_gop_number >= s->gop_size ||*/

            s->next_picture_ptr == NULL || s->intra_only) {

            s->reordered_input_picture[0] = s->input_picture[0];

            s->reordered_input_picture[0]->f.pict_type = AV_PICTURE_TYPE_I;

            s->reordered_input_picture[0]->f.coded_picture_number =

                s->coded_picture_number++;

        } else {

            int b_frames;

            if (s->avctx->frame_skip_threshold || s->avctx->frame_skip_factor) {

                if (s->picture_in_gop_number < s->gop_size &&

                    skip_check(s, s->input_picture[0], s->next_picture_ptr)) {

                    // FIXME check that te gop check above is +-1 correct

                    av_frame_unref(&s->input_picture[0]->f);

                    emms_c();

                    ff_vbv_update(s, 0);

                    goto no_output_pic;

                }

            }

            if (s->flags & CODEC_FLAG_PASS2) {

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

                    int pict_num = s->input_picture[0]->f.display_picture_number + i;

                    if (pict_num >= s->rc_context.num_entries)

                        break;

                    if (!s->input_picture[i]) {

                        s->rc_context.entry[pict_num - 1].new_pict_type = AV_PICTURE_TYPE_P;

                        break;

                    }

                    s->input_picture[i]->f.pict_type =

                        s->rc_context.entry[pict_num].new_pict_type;

                }

            }

            if (s->avctx->b_frame_strategy == 0) {

                b_frames = s->max_b_frames;

                while (b_frames && !s->input_picture[b_frames])

                    b_frames--;

            } else if (s->avctx->b_frame_strategy == 1) {

                for (i = 1; i < s->max_b_frames + 1; i++) {

                    if (s->input_picture[i] &&

                        s->input_picture[i]->b_frame_score == 0) {

                        s->input_picture[i]->b_frame_score =

                            get_intra_count(s,

                                            s->input_picture[i    ]->f.data[0],

                                            s->input_picture[i - 1]->f.data[0],

                                            s->linesize) + 1;

                    }

                }

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

                    if (s->input_picture[i] == NULL ||

                        s->input_picture[i]->b_frame_score - 1 >

                            s->mb_num / s->avctx->b_sensitivity)

                        break;

                }

                b_frames = FFMAX(0, i - 1);

                /* reset scores */

                for (i = 0; i < b_frames + 1; i++) {

                    s->input_picture[i]->b_frame_score = 0;

                }

            } else if (s->avctx->b_frame_strategy == 2) {

                b_frames = estimate_best_b_count(s);

            } else {

                av_log(s->avctx, AV_LOG_ERROR, "illegal b frame strategy\n");

                b_frames = 0;

            }

            emms_c();

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

                int type = s->input_picture[i]->f.pict_type;

                if (type && type != AV_PICTURE_TYPE_B)

                    b_frames = i;

            }

            if (s->input_picture[b_frames]->f.pict_type == AV_PICTURE_TYPE_B &&

                b_frames == s->max_b_frames) {

                av_log(s->avctx, AV_LOG_ERROR,

                       "warning, too many b frames in a row\n");

            }

            if (s->picture_in_gop_number + b_frames >= s->gop_size) {

                if ((s->mpv_flags & FF_MPV_FLAG_STRICT_GOP) &&

                    s->gop_size > s->picture_in_gop_number) {

                    b_frames = s->gop_size - s->picture_in_gop_number - 1;

                } else {

                    if (s->flags & CODEC_FLAG_CLOSED_GOP)

                        b_frames = 0;

                    s->input_picture[b_frames]->f.pict_type = AV_PICTURE_TYPE_I;

                }

            }

            if ((s->flags & CODEC_FLAG_CLOSED_GOP) && b_frames &&

                s->input_picture[b_frames]->f.pict_type == AV_PICTURE_TYPE_I)

                b_frames--;

            s->reordered_input_picture[0] = s->input_picture[b_frames];

            if (s->reordered_input_picture[0]->f.pict_type != AV_PICTURE_TYPE_I)

                s->reordered_input_picture[0]->f.pict_type = AV_PICTURE_TYPE_P;

            s->reordered_input_picture[0]->f.coded_picture_number =

                s->coded_picture_number++;

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

                s->reordered_input_picture[i + 1] = s->input_picture[i];

                s->reordered_input_picture[i + 1]->f.pict_type =

                    AV_PICTURE_TYPE_B;

                s->reordered_input_picture[i + 1]->f.coded_picture_number =

                    s->coded_picture_number++;

            }

        }

    }

no_output_pic:

    if (s->reordered_input_picture[0]) {

        s->reordered_input_picture[0]->reference =

           s->reordered_input_picture[0]->f.pict_type !=

               AV_PICTURE_TYPE_B ? 3 : 0;

        ff_mpeg_unref_picture(s, &s->new_picture);

        if ((ret = ff_mpeg_ref_picture(s, &s->new_picture, s->reordered_input_picture[0])))

            return ret;

        if (s->reordered_input_picture[0]->shared || s->avctx->rc_buffer_size) {

            // input is a shared pix, so we can't modifiy it -> alloc a new

            // one & ensure that the shared one is reuseable

            Picture *pic;

            int i = ff_find_unused_picture(s, 0);

            if (i < 0)

                return i;

            pic = &s->picture[i];

            pic->reference = s->reordered_input_picture[0]->reference;

            if (ff_alloc_picture(s, pic, 0) < 0) {

                return -1;

            }

            ret = av_frame_copy_props(&pic->f, &s->reordered_input_picture[0]->f);

            if (ret < 0)

                return ret;

            /* mark us unused / free shared pic */

            av_frame_unref(&s->reordered_input_picture[0]->f);

            s->reordered_input_picture[0]->shared = 0;

            s->current_picture_ptr = pic;

        } else {

            // input is not a shared pix -> reuse buffer for current_pix

            s->current_picture_ptr = s->reordered_input_picture[0];

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

                s->new_picture.f.data[i] += INPLACE_OFFSET;

            }

        }

        ff_mpeg_unref_picture(s, &s->current_picture);

        if ((ret = ff_mpeg_ref_picture(s, &s->current_picture,

                                       s->current_picture_ptr)) < 0)

            return ret;

        s->picture_number = s->new_picture.f.display_picture_number;

    } else {

        ff_mpeg_unref_picture(s, &s->new_picture);

    }

    return 0;

}


float ff_amr_set_fixed_gain(float fixed_gain_factor, float fixed_mean_energy,

                            float *prediction_error, float energy_mean,

                            const float *pred_table)

{

    // Equations 66-69:

    // ^g_c = ^gamma_gc * 100.05 (predicted dB + mean dB - dB of fixed vector)

    // Note 10^(0.05 * -10log(average x2)) = 1/sqrt((average x2)).

    float val = fixed_gain_factor *

        ff_exp10(0.05 *

              (avpriv_scalarproduct_float_c(pred_table, prediction_error, 4) +

               energy_mean)) /

        sqrtf(fixed_mean_energy);

    // update quantified prediction error energy history

    memmove(&prediction_error[0], &prediction_error[1],

            3 * sizeof(prediction_error[0]));

    prediction_error[3] = 20.0 * log10f(fixed_gain_factor);

    return val;

}


static void cpu_sh4_reset(CPUSH4State * env)
{
#if defined(CONFIG_USER_ONLY)
    env->sr = 0;
#else
    env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
#endif
    env->vbr = 0;
    env->pc = 0xA0000000;
#if defined(CONFIG_USER_ONLY)
    env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
#else
    env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
    set_float_rounding_mode(float_round_to_zero, &env->fp_status);
#endif
    env->mmucr = 0;


static void spapr_vlan_cleanup(NetClientState *nc)

{

    VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc);

    dev->nic = NULL;

}


BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,

        QEMUWin32AIOState *aio, HANDLE hfile,

        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,

        BlockDriverCompletionFunc *cb, void *opaque, int type)

{

    struct QEMUWin32AIOCB *waiocb;

    uint64_t offset = sector_num * 512;

    DWORD rc;

    waiocb = qemu_aio_get(&win32_aio_pool, bs, cb, opaque);

    waiocb->nbytes = nb_sectors * 512;

    waiocb->qiov = qiov;

    waiocb->is_read = (type == QEMU_AIO_READ);

    if (qiov->niov > 1) {

        waiocb->buf = qemu_blockalign(bs, qiov->size);

        if (type & QEMU_AIO_WRITE) {

            char *p = waiocb->buf;

            int i;

            for (i = 0; i < qiov->niov; ++i) {

                memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len);

                p += qiov->iov[i].iov_len;

            }

        }

        waiocb->is_linear = false;

    } else {

        waiocb->buf = qiov->iov[0].iov_base;

        waiocb->is_linear = true;

    }

    waiocb->ov = (OVERLAPPED) {

        .Offset = (DWORD) offset,

        .OffsetHigh = (DWORD) (offset >> 32),

        .hEvent = event_notifier_get_handle(&aio->e)

    };

    aio->count++;

    if (type & QEMU_AIO_READ) {

        rc = ReadFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov);

    } else {

        rc = WriteFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov);

    }

    if(rc == 0 && GetLastError() != ERROR_IO_PENDING) {

        goto out_dec_count;

    }

    return &waiocb->common;

out_dec_count:

    aio->count--;

    qemu_aio_release(waiocb);

    return NULL;

}


static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)

{

    BDRVBlkdebugState *s = bs->opaque;

    int ret;

    char *config, *c;

    /* Parse the blkdebug: prefix */

    if (strncmp(filename, "blkdebug:", strlen("blkdebug:"))) {

        return -EINVAL;

    }

    filename += strlen("blkdebug:");

    /* Read rules from config file */

    c = strchr(filename, ':');

    if (c == NULL) {

        return -EINVAL;

    }

    config = strdup(filename);

    config[c - filename] = '\0';

    ret = read_config(s, config);

    free(config);

    if (ret < 0) {

        return ret;

    }

    filename = c + 1;

    /* Set initial state */

    s->vars.state = 1;

    /* Open the backing file */

    ret = bdrv_file_open(&bs->file, filename, flags);

    if (ret < 0) {

        return ret;

    }

    return 0;

}


static int decode_chunks(AVCodecContext *avctx, AVFrame *picture,

                         int *got_output, const uint8_t *buf, int buf_size)

{

    Mpeg1Context *s = avctx->priv_data;

    MpegEncContext *s2 = &s->mpeg_enc_ctx;

    const uint8_t *buf_ptr = buf;

    const uint8_t *buf_end = buf + buf_size;

    int ret, input_size;

    int last_code = 0, skip_frame = 0;

    for (;;) {

        /* find next start code */

        uint32_t start_code = -1;

        buf_ptr = avpriv_find_start_code(buf_ptr, buf_end, &start_code);

        if (start_code > 0x1ff) {

            if (!skip_frame) {

                if (HAVE_THREADS &&

                    (avctx->active_thread_type & FF_THREAD_SLICE) &&

                    !avctx->hwaccel) {

                    int i;

                    avctx->execute(avctx, slice_decode_thread,

                                   &s2->thread_context[0], NULL,

                                   s->slice_count, sizeof(void *));

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

                        s2->er.error_count += s2->thread_context[i]->er.error_count;

                }

                ret = slice_end(avctx, picture);

                if (ret < 0)

                    return ret;

                else if (ret) {

                    // FIXME: merge with the stuff in mpeg_decode_slice

                    if (s2->last_picture_ptr || s2->low_delay)

                        *got_output = 1;

                }

            }

            s2->pict_type = 0;

            return FFMAX(0, buf_ptr - buf - s2->parse_context.last_index);

        }

        input_size = buf_end - buf_ptr;

        if (avctx->debug & FF_DEBUG_STARTCODE)

            av_log(avctx, AV_LOG_DEBUG, "%3"PRIX32" at %td left %d\n",

                   start_code, buf_ptr - buf, input_size);

        /* prepare data for next start code */

        switch (start_code) {

        case SEQ_START_CODE:

            if (last_code == 0) {

                mpeg1_decode_sequence(avctx, buf_ptr, input_size);

                s->sync = 1;

            } else {

                av_log(avctx, AV_LOG_ERROR,

                       "ignoring SEQ_START_CODE after %X\n", last_code);

                if (avctx->err_recognition & AV_EF_EXPLODE)

                    return AVERROR_INVALIDDATA;

            }

            break;

        case PICTURE_START_CODE:

            if (s2->width <= 0 || s2->height <= 0) {

                av_log(avctx, AV_LOG_ERROR, "Invalid frame dimensions %dx%d.\n",

                       s2->width, s2->height);

                return AVERROR_INVALIDDATA;

            }

            if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_SLICE) &&

                !avctx->hwaccel && s->slice_count) {

                int i;

                avctx->execute(avctx, slice_decode_thread,

                               s2->thread_context, NULL,

                               s->slice_count, sizeof(void *));

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

                    s2->er.error_count += s2->thread_context[i]->er.error_count;

                s->slice_count = 0;

            }

            if (last_code == 0 || last_code == SLICE_MIN_START_CODE) {

                ret = mpeg_decode_postinit(avctx);

                if (ret < 0) {

                    av_log(avctx, AV_LOG_ERROR,

                           "mpeg_decode_postinit() failure\n");

                    return ret;

                }

                /* We have a complete image: we try to decompress it. */

                if (mpeg1_decode_picture(avctx, buf_ptr, input_size) < 0)

                    s2->pict_type = 0;

                s->first_slice = 1;

                last_code      = PICTURE_START_CODE;

            } else {

                av_log(avctx, AV_LOG_ERROR,

                       "ignoring pic after %X\n", last_code);

                if (avctx->err_recognition & AV_EF_EXPLODE)

                    return AVERROR_INVALIDDATA;

            }

            break;

        case EXT_START_CODE:

            init_get_bits(&s2->gb, buf_ptr, input_size * 8);

            switch (get_bits(&s2->gb, 4)) {

            case 0x1:

                if (last_code == 0) {

                    mpeg_decode_sequence_extension(s);

                } else {

                    av_log(avctx, AV_LOG_ERROR,

                           "ignoring seq ext after %X\n", last_code);

                    if (avctx->err_recognition & AV_EF_EXPLODE)

                        return AVERROR_INVALIDDATA;

                }

                break;

            case 0x2:

                mpeg_decode_sequence_display_extension(s);

                break;

            case 0x3:

                mpeg_decode_quant_matrix_extension(s2);

                break;

            case 0x7:

                mpeg_decode_picture_display_extension(s);

                break;

            case 0x8:

                if (last_code == PICTURE_START_CODE) {

                    mpeg_decode_picture_coding_extension(s);

                } else {

                    av_log(avctx, AV_LOG_ERROR,

                           "ignoring pic cod ext after %X\n", last_code);

                    if (avctx->err_recognition & AV_EF_EXPLODE)

                        return AVERROR_INVALIDDATA;

                }

                break;

            }

            break;

        case USER_START_CODE:

            mpeg_decode_user_data(avctx, buf_ptr, input_size);

            break;

        case GOP_START_CODE:

            if (last_code == 0) {

                s2->first_field = 0;

                mpeg_decode_gop(avctx, buf_ptr, input_size);

                s->sync = 1;

            } else {

                av_log(avctx, AV_LOG_ERROR,

                       "ignoring GOP_START_CODE after %X\n", last_code);

                if (avctx->err_recognition & AV_EF_EXPLODE)

                    return AVERROR_INVALIDDATA;

            }

            break;

        default:

            if (start_code >= SLICE_MIN_START_CODE &&

                start_code <= SLICE_MAX_START_CODE && last_code != 0) {

                const int field_pic = s2->picture_structure != PICT_FRAME;

                int mb_y = (start_code - SLICE_MIN_START_CODE) << field_pic;

                last_code = SLICE_MIN_START_CODE;

                if (s2->picture_structure == PICT_BOTTOM_FIELD)

                    mb_y++;

                if (mb_y >= s2->mb_height) {

                    av_log(s2->avctx, AV_LOG_ERROR,

                           "slice below image (%d >= %d)\n", mb_y, s2->mb_height);

                    return -1;

                }

                if (s2->last_picture_ptr == NULL) {

                    /* Skip B-frames if we do not have reference frames and

                     * GOP is not closed. */

                    if (s2->pict_type == AV_PICTURE_TYPE_B) {

                        if (!s->closed_gop) {

                            skip_frame = 1;

                            break;

                        }

                    }

                }

                if (s2->pict_type == AV_PICTURE_TYPE_I)

                    s->sync = 1;

                if (s2->next_picture_ptr == NULL) {

                    /* Skip P-frames if we do not have a reference frame or

                     * we have an invalid header. */

                    if (s2->pict_type == AV_PICTURE_TYPE_P && !s->sync) {

                        skip_frame = 1;

                        break;

                    }

                }

                if ((avctx->skip_frame >= AVDISCARD_NONREF &&

                     s2->pict_type == AV_PICTURE_TYPE_B) ||

                    (avctx->skip_frame >= AVDISCARD_NONKEY &&

                     s2->pict_type != AV_PICTURE_TYPE_I) ||

                    avctx->skip_frame >= AVDISCARD_ALL) {

                    skip_frame = 1;

                    break;

                }

                if (!s->mpeg_enc_ctx_allocated)

                    break;

                if (s2->codec_id == AV_CODEC_ID_MPEG2VIDEO) {

                    if (mb_y < avctx->skip_top ||

                        mb_y >= s2->mb_height - avctx->skip_bottom)

                        break;

                }

                if (!s2->pict_type) {

                    av_log(avctx, AV_LOG_ERROR, "Missing picture start code\n");

                    if (avctx->err_recognition & AV_EF_EXPLODE)

                        return AVERROR_INVALIDDATA;

                    break;

                }

                if (s->first_slice) {

                    skip_frame     = 0;

                    s->first_slice = 0;

                    if (mpeg_field_start(s2, buf, buf_size) < 0)

                        return -1;

                }

                if (!s2->current_picture_ptr) {

                    av_log(avctx, AV_LOG_ERROR,

                           "current_picture not initialized\n");

                    return AVERROR_INVALIDDATA;

                }

                if (HAVE_THREADS &&

                    (avctx->active_thread_type & FF_THREAD_SLICE) &&

                    !avctx->hwaccel) {

                    int threshold = (s2->mb_height * s->slice_count +

                                     s2->slice_context_count / 2) /

                                    s2->slice_context_count;

                    if (threshold <= mb_y) {

                        MpegEncContext *thread_context = s2->thread_context[s->slice_count];

                        thread_context->start_mb_y = mb_y;

                        thread_context->end_mb_y   = s2->mb_height;

                        if (s->slice_count) {

                            s2->thread_context[s->slice_count - 1]->end_mb_y = mb_y;

                            ret = ff_update_duplicate_context(thread_context, s2);

                            if (ret < 0)

                                return ret;

                        }

                        init_get_bits(&thread_context->gb, buf_ptr, input_size * 8);

                        s->slice_count++;

                    }

                    buf_ptr += 2; // FIXME add minimum number of bytes per slice

                } else {

                    ret = mpeg_decode_slice(s2, mb_y, &buf_ptr, input_size);

                    emms_c();

                    if (ret < 0) {

                        if (avctx->err_recognition & AV_EF_EXPLODE)

                            return ret;

                        if (s2->resync_mb_x >= 0 && s2->resync_mb_y >= 0)

                            ff_er_add_slice(&s2->er, s2->resync_mb_x,

                                            s2->resync_mb_y, s2->mb_x, s2->mb_y,

                                            ER_AC_ERROR | ER_DC_ERROR | ER_MV_ERROR);

                    } else {

                        ff_er_add_slice(&s2->er, s2->resync_mb_x,

                                        s2->resync_mb_y, s2->mb_x - 1, s2->mb_y,

                                        ER_AC_END | ER_DC_END | ER_MV_END);

                    }

                }

            }

            break;

        }

    }

}


void cpu_loop(CPUPPCState *env)

{

    target_siginfo_t info;

    int trapnr;

    uint32_t ret;

    for(;;) {

        trapnr = cpu_ppc_exec(env);

        switch(trapnr) {

        case POWERPC_EXCP_NONE:

            /* Just go on */

            break;

        case POWERPC_EXCP_CRITICAL: /* Critical input                        */

            cpu_abort(env, "Critical interrupt while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_MCHECK:   /* Machine check exception               */

            cpu_abort(env, "Machine check exception while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_DSI:      /* Data storage exception                */

            EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",

                      env->spr[SPR_DAR]);

            /* XXX: check this. Seems bugged */

            switch (env->error_code & 0xFF000000) {

            case 0x40000000:

                info.si_signo = TARGET_SIGSEGV;

                info.si_errno = 0;

                info.si_code = TARGET_SEGV_MAPERR;

                break;

            case 0x04000000:

                info.si_signo = TARGET_SIGILL;

                info.si_errno = 0;

                info.si_code = TARGET_ILL_ILLADR;

                break;

            case 0x08000000:

                info.si_signo = TARGET_SIGSEGV;

                info.si_errno = 0;

                info.si_code = TARGET_SEGV_ACCERR;

                break;

            default:

                /* Let's send a regular segfault... */

                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",

                          env->error_code);

                info.si_signo = TARGET_SIGSEGV;

                info.si_errno = 0;

                info.si_code = TARGET_SEGV_MAPERR;

                break;

            }

            info._sifields._sigfault._addr = env->nip;

            queue_signal(info.si_signo, &info);

            break;

        case POWERPC_EXCP_ISI:      /* Instruction storage exception         */

            EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",

                      env->spr[SPR_SRR0]);

            /* XXX: check this */

            switch (env->error_code & 0xFF000000) {

            case 0x40000000:

                info.si_signo = TARGET_SIGSEGV;

            info.si_errno = 0;

                info.si_code = TARGET_SEGV_MAPERR;

                break;

            case 0x10000000:

            case 0x08000000:

                info.si_signo = TARGET_SIGSEGV;

                info.si_errno = 0;

                info.si_code = TARGET_SEGV_ACCERR;

                break;

            default:

                /* Let's send a regular segfault... */

                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",

                          env->error_code);

                info.si_signo = TARGET_SIGSEGV;

                info.si_errno = 0;

                info.si_code = TARGET_SEGV_MAPERR;

                break;

            }

            info._sifields._sigfault._addr = env->nip - 4;

            queue_signal(info.si_signo, &info);

            break;

        case POWERPC_EXCP_EXTERNAL: /* External input                        */

            cpu_abort(env, "External interrupt while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */

            EXCP_DUMP(env, "Unaligned memory access\n");

            /* XXX: check this */

            info.si_signo = TARGET_SIGBUS;

            info.si_errno = 0;

            info.si_code = TARGET_BUS_ADRALN;

            info._sifields._sigfault._addr = env->nip - 4;

            queue_signal(info.si_signo, &info);

            break;

        case POWERPC_EXCP_PROGRAM:  /* Program exception                     */

            /* XXX: check this */

            switch (env->error_code & ~0xF) {

            case POWERPC_EXCP_FP:

                EXCP_DUMP(env, "Floating point program exception\n");

                info.si_signo = TARGET_SIGFPE;

                info.si_errno = 0;

                switch (env->error_code & 0xF) {

                case POWERPC_EXCP_FP_OX:

                    info.si_code = TARGET_FPE_FLTOVF;

                    break;

                case POWERPC_EXCP_FP_UX:

                    info.si_code = TARGET_FPE_FLTUND;

                    break;

                case POWERPC_EXCP_FP_ZX:

                case POWERPC_EXCP_FP_VXZDZ:

                    info.si_code = TARGET_FPE_FLTDIV;

                    break;

                case POWERPC_EXCP_FP_XX:

                    info.si_code = TARGET_FPE_FLTRES;

                    break;

                case POWERPC_EXCP_FP_VXSOFT:

                    info.si_code = TARGET_FPE_FLTINV;

                    break;

                case POWERPC_EXCP_FP_VXSNAN:

                case POWERPC_EXCP_FP_VXISI:

                case POWERPC_EXCP_FP_VXIDI:

                case POWERPC_EXCP_FP_VXIMZ:

                case POWERPC_EXCP_FP_VXVC:

                case POWERPC_EXCP_FP_VXSQRT:

                case POWERPC_EXCP_FP_VXCVI:

                    info.si_code = TARGET_FPE_FLTSUB;

                    break;

                default:

                    EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",

                              env->error_code);

                    break;

                }

                break;

            case POWERPC_EXCP_INVAL:

                EXCP_DUMP(env, "Invalid instruction\n");

                info.si_signo = TARGET_SIGILL;

                info.si_errno = 0;

                switch (env->error_code & 0xF) {

                case POWERPC_EXCP_INVAL_INVAL:

                    info.si_code = TARGET_ILL_ILLOPC;

                    break;

                case POWERPC_EXCP_INVAL_LSWX:

                    info.si_code = TARGET_ILL_ILLOPN;

                    break;

                case POWERPC_EXCP_INVAL_SPR:

                    info.si_code = TARGET_ILL_PRVREG;

                    break;

                case POWERPC_EXCP_INVAL_FP:

                    info.si_code = TARGET_ILL_COPROC;

                    break;

                default:

                    EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",

                              env->error_code & 0xF);

                    info.si_code = TARGET_ILL_ILLADR;

                    break;

                }

                break;

            case POWERPC_EXCP_PRIV:

                EXCP_DUMP(env, "Privilege violation\n");

                info.si_signo = TARGET_SIGILL;

                info.si_errno = 0;

                switch (env->error_code & 0xF) {

                case POWERPC_EXCP_PRIV_OPC:

                    info.si_code = TARGET_ILL_PRVOPC;

                    break;

                case POWERPC_EXCP_PRIV_REG:

                    info.si_code = TARGET_ILL_PRVREG;

                    break;

                default:

                    EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",

                              env->error_code & 0xF);

                    info.si_code = TARGET_ILL_PRVOPC;

                    break;

                }

                break;

            case POWERPC_EXCP_TRAP:

                cpu_abort(env, "Tried to call a TRAP\n");

                break;

            default:

                /* Should not happen ! */

                cpu_abort(env, "Unknown program exception (%02x)\n",

                          env->error_code);

                break;

            }

            info._sifields._sigfault._addr = env->nip - 4;

            queue_signal(info.si_signo, &info);

            break;

        case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */

            EXCP_DUMP(env, "No floating point allowed\n");

            info.si_signo = TARGET_SIGILL;

            info.si_errno = 0;

            info.si_code = TARGET_ILL_COPROC;

            info._sifields._sigfault._addr = env->nip - 4;

            queue_signal(info.si_signo, &info);

            break;

        case POWERPC_EXCP_SYSCALL:  /* System call exception                 */

            cpu_abort(env, "Syscall exception while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */

            EXCP_DUMP(env, "No APU instruction allowed\n");

            info.si_signo = TARGET_SIGILL;

            info.si_errno = 0;

            info.si_code = TARGET_ILL_COPROC;

            info._sifields._sigfault._addr = env->nip - 4;

            queue_signal(info.si_signo, &info);

            break;

        case POWERPC_EXCP_DECR:     /* Decrementer exception                 */

            cpu_abort(env, "Decrementer interrupt while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */

            cpu_abort(env, "Fix interval timer interrupt while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */

            cpu_abort(env, "Watchdog timer interrupt while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_DTLB:     /* Data TLB error                        */

            cpu_abort(env, "Data TLB exception while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */

            cpu_abort(env, "Instruction TLB exception while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_DEBUG:    /* Debug interrupt                       */

            /* XXX: check this */

            {

                int sig;

                sig = gdb_handlesig(env, TARGET_SIGTRAP);

                if (sig) {

                    info.si_signo = sig;

                    info.si_errno = 0;

                    info.si_code = TARGET_TRAP_BRKPT;

                    queue_signal(info.si_signo, &info);

                  }

            }

            break;

        case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */

            EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");

            info.si_signo = TARGET_SIGILL;

            info.si_errno = 0;

            info.si_code = TARGET_ILL_COPROC;

            info._sifields._sigfault._addr = env->nip - 4;

            queue_signal(info.si_signo, &info);

            break;

        case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */

            cpu_abort(env, "Embedded floating-point data IRQ not handled\n");

            break;

        case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */

            cpu_abort(env, "Embedded floating-point round IRQ not handled\n");

            break;

        case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */

            cpu_abort(env, "Performance monitor exception not handled\n");

            break;

        case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */

            cpu_abort(env, "Doorbell interrupt while in user mode. "

                       "Aborting\n");

            break;

        case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */

            cpu_abort(env, "Doorbell critical interrupt while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_RESET:    /* System reset exception                */

            cpu_abort(env, "Reset interrupt while in user mode. "

                      "Aborting\n");

            break;

#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) /* PowerPC 64 */

        case POWERPC_EXCP_DSEG:     /* Data segment exception                */

            cpu_abort(env, "Data segment exception while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */

            cpu_abort(env, "Instruction segment exception "

                      "while in user mode. Aborting\n");

            break;

#endif /* defined(TARGET_PPC64) && !defined(TARGET_ABI32) */

#if defined(TARGET_PPC64H) && !defined(TARGET_ABI32)

        /* PowerPC 64 with hypervisor mode support */

        case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */

            cpu_abort(env, "Hypervisor decrementer interrupt "

                      "while in user mode. Aborting\n");

            break;

#endif /* defined(TARGET_PPC64H) && !defined(TARGET_ABI32) */

        case POWERPC_EXCP_TRACE:    /* Trace exception                       */

            /* Nothing to do:

             * we use this exception to emulate step-by-step execution mode.

             */

            break;

#if defined(TARGET_PPC64H) && !defined(TARGET_ABI32)

        /* PowerPC 64 with hypervisor mode support */

        case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */

            cpu_abort(env, "Hypervisor data storage exception "

                      "while in user mode. Aborting\n");

            break;

        case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */

            cpu_abort(env, "Hypervisor instruction storage exception "

                      "while in user mode. Aborting\n");

            break;

        case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */

            cpu_abort(env, "Hypervisor data segment exception "

                      "while in user mode. Aborting\n");

            break;

        case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */

            cpu_abort(env, "Hypervisor instruction segment exception "

                      "while in user mode. Aborting\n");

            break;

#endif /* defined(TARGET_PPC64H) && !defined(TARGET_ABI32) */

        case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */

            EXCP_DUMP(env, "No Altivec instructions allowed\n");

            info.si_signo = TARGET_SIGILL;

            info.si_errno = 0;

            info.si_code = TARGET_ILL_COPROC;

            info._sifields._sigfault._addr = env->nip - 4;

            queue_signal(info.si_signo, &info);

            break;

        case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */

            cpu_abort(env, "Programable interval timer interrupt "

                      "while in user mode. Aborting\n");

            break;

        case POWERPC_EXCP_IO:       /* IO error exception                    */

            cpu_abort(env, "IO error exception while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_RUNM:     /* Run mode exception                    */

            cpu_abort(env, "Run mode exception while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */

            cpu_abort(env, "Emulation trap exception not handled\n");

            break;

        case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */

            cpu_abort(env, "Instruction fetch TLB exception "

                      "while in user-mode. Aborting");

            break;

        case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */

            cpu_abort(env, "Data load TLB exception while in user-mode. "

                      "Aborting");

            break;

        case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */

            cpu_abort(env, "Data store TLB exception while in user-mode. "

                      "Aborting");

            break;

        case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */

            cpu_abort(env, "Floating-point assist exception not handled\n");

            break;

        case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */

            cpu_abort(env, "Instruction address breakpoint exception "

                      "not handled\n");

            break;

        case POWERPC_EXCP_SMI:      /* System management interrupt           */

            cpu_abort(env, "System management interrupt while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */

            cpu_abort(env, "Thermal interrupt interrupt while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_PERFM:   /* Embedded performance monitor IRQ      */

            cpu_abort(env, "Performance monitor exception not handled\n");

            break;

        case POWERPC_EXCP_VPUA:     /* Vector assist exception               */

            cpu_abort(env, "Vector assist exception not handled\n");

            break;

        case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */

            cpu_abort(env, "Soft patch exception not handled\n");

            break;

        case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */

            cpu_abort(env, "Maintenance exception while in user mode. "

                      "Aborting\n");

            break;

        case POWERPC_EXCP_STOP:     /* stop translation                      */

            /* We did invalidate the instruction cache. Go on */

            break;

        case POWERPC_EXCP_BRANCH:   /* branch instruction:                   */

            /* We just stopped because of a branch. Go on */

            break;

        case POWERPC_EXCP_SYSCALL_USER:

            /* system call in user-mode emulation */

            /* WARNING:

             * PPC ABI uses overflow flag in cr0 to signal an error

             * in syscalls.

             */

#if 0

            printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],

                   env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);

#endif

            env->crf[0] &= ~0x1;

            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],

                             env->gpr[5], env->gpr[6], env->gpr[7],

                             env->gpr[8]);

            if (ret > (uint32_t)(-515)) {

                env->crf[0] |= 0x1;

                ret = -ret;

            }

            env->gpr[3] = ret;

#if 0

            printf("syscall returned 0x%08x (%d)\n", ret, ret);

#endif

            break;

        case EXCP_INTERRUPT:

            /* just indicate that signals should be handled asap */

            break;

        default:

            cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);

            break;

        }

        process_pending_signals(env);

    }

}


static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)

{

    BDRVBochsState *s = bs->opaque;

    int64_t offset = sector_num * 512;

    int64_t extent_index, extent_offset, bitmap_offset, block_offset;

    char bitmap_entry;

    // seek to sector

    extent_index = offset / s->extent_size;

    extent_offset = (offset % s->extent_size) / 512;

    if (s->catalog_bitmap[extent_index] == 0xffffffff)

    {

//	fprintf(stderr, "page not allocated [%x - %x:%x]\n",

//	    sector_num, extent_index, extent_offset);

	return -1; // not allocated

    }

    bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *

	(s->extent_blocks + s->bitmap_blocks));

    block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));

//    fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",

//	sector_num, extent_index, extent_offset,

//	le32_to_cpu(s->catalog_bitmap[extent_index]),

//	bitmap_offset, block_offset);

    // read in bitmap for current extent

    lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET);

    if (read(s->fd, &bitmap_entry, 1) != 1)

        return -1;

    if (!((bitmap_entry >> (extent_offset % 8)) & 1))

    {

//	fprintf(stderr, "sector (%x) in bitmap not allocated\n",

//	    sector_num);

	return -1; // not allocated

    }

    lseek(s->fd, block_offset, SEEK_SET);

    return 0;

}


static void vnc_handshake_io(void *opaque) {

    struct VncState *vs = (struct VncState *)opaque;

    VNC_DEBUG("Handshake IO continue\n");

    vnc_continue_handshake(vs);

}


static int local_remove(FsContext *ctx, const char *path)

{

    int err;

    struct stat stbuf;

    char buffer[PATH_MAX];

    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {

        err =  lstat(rpath(ctx, path, buffer), &stbuf);

        if (err) {

            goto err_out;

        }

        /*

         * If directory remove .virtfs_metadata contained in the

         * directory

         */

        if (S_ISDIR(stbuf.st_mode)) {

            snprintf(buffer, ARRAY_SIZE(buffer), "%s/%s/%s",

                     ctx->fs_root, path, VIRTFS_META_DIR);

            err = remove(buffer);

            if (err < 0 && errno != ENOENT) {

                /*

                 * We didn't had the .virtfs_metadata file. May be file created

                 * in non-mapped mode ?. Ignore ENOENT.

                 */

                goto err_out;

            }

        }

        /*

         * Now remove the name from parent directory

         * .virtfs_metadata directory

         */

        err = remove(local_mapped_attr_path(ctx, path, buffer));

        if (err < 0 && errno != ENOENT) {

            /*

             * We didn't had the .virtfs_metadata file. May be file created

             * in non-mapped mode ?. Ignore ENOENT.

             */

            goto err_out;

        }

    }

    return remove(rpath(ctx, path, buffer));

err_out:

    return err;

}


static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)

{

    assert(s->allocating_write_reqs_plugged);

    s->allocating_write_reqs_plugged = false;

    qemu_co_enter_next(&s->allocating_write_reqs);

}


static int xen_pt_bar_reg_init(XenPCIPassthroughState *s, XenPTRegInfo *reg,

                               uint32_t real_offset, uint32_t *data)

{

    uint32_t reg_field = 0;

    int index;

    index = xen_pt_bar_offset_to_index(reg->offset);

    if (index < 0 || index >= PCI_NUM_REGIONS) {

        XEN_PT_ERR(&s->dev, "Internal error: Invalid BAR index [%d].\n", index);

        return -1;

    }

    /* set BAR flag */

    s->bases[index].bar_flag = xen_pt_bar_reg_parse(s, reg);

    if (s->bases[index].bar_flag == XEN_PT_BAR_FLAG_UNUSED) {

        reg_field = XEN_PT_INVALID_REG;

    }

    *data = reg_field;

    return 0;

}


static void ehci_frame_timer(void *opaque)

{

    EHCIState *ehci = opaque;

    int schedules = 0;

    int64_t expire_time, t_now;

    uint64_t ns_elapsed;

    int frames;

    int i;

    int skipped_frames = 0;

    t_now = qemu_get_clock_ns(vm_clock);

    ns_elapsed = t_now - ehci->last_run_ns;

    frames = ns_elapsed / FRAME_TIMER_NS;

    if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) {

        schedules++;

        expire_time = t_now + (get_ticks_per_sec() / FRAME_TIMER_FREQ);

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

            ehci_update_frindex(ehci, 1);

            if (frames - i > ehci->maxframes) {

                skipped_frames++;

            } else {

                ehci_advance_periodic_state(ehci);

            }

            ehci->last_run_ns += FRAME_TIMER_NS;

        }

    } else {

        if (ehci->async_stepdown < ehci->maxframes / 2) {

            ehci->async_stepdown++;

        }

        expire_time = t_now + (get_ticks_per_sec()

                               * ehci->async_stepdown / FRAME_TIMER_FREQ);

        ehci_update_frindex(ehci, frames);

        ehci->last_run_ns += FRAME_TIMER_NS * frames;

    }

#if 0

    if (skipped_frames) {

        DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);

    }

#endif

    /*  Async is not inside loop since it executes everything it can once

     *  called

     */

    if (ehci_async_enabled(ehci) || ehci->astate != EST_INACTIVE) {

        schedules++;

        qemu_bh_schedule(ehci->async_bh);

    }

    if (schedules) {

        qemu_mod_timer(ehci->frame_timer, expire_time);

    }

}