static int decode_pce(AACContext *ac, enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],

                      GetBitContext *gb)

{

    int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc, sampling_index;

    skip_bits(gb, 2);  // object_type

    sampling_index = get_bits(gb, 4);

    if (ac->m4ac.sampling_index != sampling_index)

        av_log(ac->avccontext, AV_LOG_WARNING, "Sample rate index in program config element does not match the sample rate index configured by the container.\n");

    num_front       = get_bits(gb, 4);

    num_side        = get_bits(gb, 4);

    num_back        = get_bits(gb, 4);

    num_lfe         = get_bits(gb, 2);

    num_assoc_data  = get_bits(gb, 3);

    num_cc          = get_bits(gb, 4);

    if (get_bits1(gb))

        skip_bits(gb, 4); // mono_mixdown_tag

    if (get_bits1(gb))

        skip_bits(gb, 4); // stereo_mixdown_tag

    if (get_bits1(gb))

        skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround

    decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_FRONT, gb, num_front);

    decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_SIDE,  gb, num_side );

    decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_BACK,  gb, num_back );

    decode_channel_map(NULL,                  new_che_pos[TYPE_LFE], AAC_CHANNEL_LFE,   gb, num_lfe  );

    skip_bits_long(gb, 4 * num_assoc_data);

    decode_channel_map(new_che_pos[TYPE_CCE], new_che_pos[TYPE_CCE], AAC_CHANNEL_CC,    gb, num_cc   );

    align_get_bits(gb);

    /* comment field, first byte is length */

    skip_bits_long(gb, 8 * get_bits(gb, 8));

    return 0;

}


static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)

{

    abi_long raddr;

    void *host_raddr;

    struct shmid_ds shm_info;

    int i,ret;

    /* find out the length of the shared memory segment */

    ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));

    if (is_error(ret)) {

        /* can't get length, bail out */

        return ret;

    }

    mmap_lock();

    if (shmaddr)

        host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);

    else {

        abi_ulong mmap_start;

        mmap_start = mmap_find_vma(0, shm_info.shm_segsz);

        if (mmap_start == -1) {

            errno = ENOMEM;

            host_raddr = (void *)-1;

        } else

            host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);

    }

    if (host_raddr == (void *)-1) {

        mmap_unlock();

        return get_errno((long)host_raddr);

    }

    raddr=h2g((unsigned long)host_raddr);

    page_set_flags(raddr, raddr + shm_info.shm_segsz,

                   PAGE_VALID | PAGE_READ |

                   ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));

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

        if (!shm_regions[i].in_use) {

            shm_regions[i].in_use = true;

            shm_regions[i].start = raddr;

            shm_regions[i].size = shm_info.shm_segsz;

            break;

        }

    }

    mmap_unlock();

    return raddr;

}


static void gif_fill_rect(AVFrame *picture, uint32_t color, int l, int t, int w, int h)

{

    const int linesize = picture->linesize[0] / sizeof(uint32_t);

    const uint32_t *py = (uint32_t *)picture->data[0] + t * linesize;

    const uint32_t *pr, *pb = py + (t + h) * linesize;

    uint32_t *px;

    for (; py < pb; py += linesize) {

        px = (uint32_t *)py + l;

        pr = px + w;

        for (; px < pr; px++)

            *px = color;

    }

}


void helper_divl_EAX_T0(void)

{

    unsigned int den, q, r;

    uint64_t num;

    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);

    den = T0;

    if (den == 0) {

        raise_exception(EXCP00_DIVZ);

    }

#ifdef BUGGY_GCC_DIV64

    r = div32(&q, num, den);

#else

    q = (num / den);

    r = (num % den);

#endif

    EAX = (uint32_t)q;

    EDX = (uint32_t)r;

}


static int mmap_init(AVFormatContext *ctx)

{

    int i, res;

    struct video_data *s = ctx->priv_data;

    struct v4l2_requestbuffers req = {

        .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,

        .count  = desired_video_buffers,

        .memory = V4L2_MEMORY_MMAP

    };

    res = ioctl(s->fd, VIDIOC_REQBUFS, &req);

    if (res < 0) {

        if (errno == EINVAL) {

            av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");

        } else {

            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");

        }

        return AVERROR(errno);

    }

    if (req.count < 2) {

        av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");

        return AVERROR(ENOMEM);

    }

    s->buffers = req.count;

    s->buf_start = av_malloc(sizeof(void *) * s->buffers);

    if (s->buf_start == NULL) {

        av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");

        return AVERROR(ENOMEM);

    }

    s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);

    if (s->buf_len == NULL) {

        av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");

        av_free(s->buf_start);

        return AVERROR(ENOMEM);

    }

    for (i = 0; i < req.count; i++) {

        struct v4l2_buffer buf = {

            .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,

            .index  = i,

            .memory = V4L2_MEMORY_MMAP

        };

        res = ioctl(s->fd, VIDIOC_QUERYBUF, &buf);

        if (res < 0) {

            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");

            return AVERROR(errno);

        }

        s->buf_len[i] = buf.length;

        if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {

            av_log(ctx, AV_LOG_ERROR,

                   "Buffer len [%d] = %d != %d\n",

                   i, s->buf_len[i], s->frame_size);

            return -1;

        }

        s->buf_start[i] = mmap(NULL, buf.length,

                               PROT_READ | PROT_WRITE, MAP_SHARED,

                               s->fd, buf.m.offset);

        if (s->buf_start[i] == MAP_FAILED) {

            av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));

            return AVERROR(errno);

        }

    }

    return 0;

}


static void adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch)

{

    ADXChannelState *prev = &c->prev[ch];

    GetBitContext gb;

    int scale = AV_RB16(in);

    int i;

    int s0, s1, s2, d;

    init_get_bits(&gb, in + 2, (18 - 2) * 8);

    s1 = prev->s1;

    s2 = prev->s2;

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

        d  = get_sbits(&gb, 4);

        s0 = (BASEVOL * d * scale + SCALE1 * s1 - SCALE2 * s2) >> 14;

        s2 = s1;

        s1 = av_clip_int16(s0);

        *out = s1;

        out += c->channels;

    }

    prev->s1 = s1;

    prev->s2 = s2;

}


void ide_exec_cmd(IDEBus *bus, uint32_t val)

{

    uint16_t *identify_data;

    IDEState *s;

    int n;

    int lba48 = 0;

#if defined(DEBUG_IDE)

    printf("ide: CMD=%02x\n", val);

#endif

    s = idebus_active_if(bus);

    /* ignore commands to non existent slave */

    if (s != bus->ifs && !s->bs)

        return;

    /* Only DEVICE RESET is allowed while BSY or/and DRQ are set */

    if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET)

        return;

    if (!ide_cmd_permitted(s, val)) {

        goto abort_cmd;

    }

    if (ide_cmd_table[val].handler != NULL) {

        bool complete;

        s->status = READY_STAT | BUSY_STAT;

        s->error = 0;

        complete = ide_cmd_table[val].handler(s, val);

        if (complete) {

            s->status &= ~BUSY_STAT;

            assert(!!s->error == !!(s->status & ERR_STAT));

            if ((ide_cmd_table[val].flags & SET_DSC) && !s->error) {

                s->status |= SEEK_STAT;

            }

            ide_set_irq(s->bus);

        }

        return;

    }

    switch(val) {

    case WIN_SETMULT:

        if (s->drive_kind == IDE_CFATA && s->nsector == 0) {

            /* Disable Read and Write Multiple */

            s->mult_sectors = 0;

            s->status = READY_STAT | SEEK_STAT;

        } else if ((s->nsector & 0xff) != 0 &&

            ((s->nsector & 0xff) > MAX_MULT_SECTORS ||

             (s->nsector & (s->nsector - 1)) != 0)) {

            ide_abort_command(s);

        } else {

            s->mult_sectors = s->nsector & 0xff;

            s->status = READY_STAT | SEEK_STAT;

        }

        ide_set_irq(s->bus);

        break;

    case WIN_VERIFY_EXT:

        lba48 = 1;

        /* fall through */

    case WIN_VERIFY:

    case WIN_VERIFY_ONCE:

        /* do sector number check ? */

	ide_cmd_lba48_transform(s, lba48);

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case WIN_READ_EXT:

        lba48 = 1;

        /* fall through */

    case WIN_READ:

    case WIN_READ_ONCE:

        if (s->drive_kind == IDE_CD) {

            ide_set_signature(s); /* odd, but ATA4 8.27.5.2 requires it */

            goto abort_cmd;

        }

        if (!s->bs) {

            goto abort_cmd;

        }

	ide_cmd_lba48_transform(s, lba48);

        s->req_nb_sectors = 1;

        ide_sector_read(s);

        break;

    case WIN_WRITE_EXT:

        lba48 = 1;

        /* fall through */

    case WIN_WRITE:

    case WIN_WRITE_ONCE:

    case CFA_WRITE_SECT_WO_ERASE:

    case WIN_WRITE_VERIFY:

        if (!s->bs) {

            goto abort_cmd;

        }

	ide_cmd_lba48_transform(s, lba48);

        s->error = 0;

        s->status = SEEK_STAT | READY_STAT;

        s->req_nb_sectors = 1;

        ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);

        s->media_changed = 1;

        break;

    case WIN_MULTREAD_EXT:

        lba48 = 1;

        /* fall through */

    case WIN_MULTREAD:

        if (!s->bs) {

            goto abort_cmd;

        }

        if (!s->mult_sectors) {

            goto abort_cmd;

        }

	ide_cmd_lba48_transform(s, lba48);

        s->req_nb_sectors = s->mult_sectors;

        ide_sector_read(s);

        break;

    case WIN_MULTWRITE_EXT:

        lba48 = 1;

        /* fall through */

    case WIN_MULTWRITE:

    case CFA_WRITE_MULTI_WO_ERASE:

        if (!s->bs) {

            goto abort_cmd;

        }

        if (!s->mult_sectors) {

            goto abort_cmd;

        }

	ide_cmd_lba48_transform(s, lba48);

        s->error = 0;

        s->status = SEEK_STAT | READY_STAT;

        s->req_nb_sectors = s->mult_sectors;

        n = s->nsector;

        if (n > s->req_nb_sectors)

            n = s->req_nb_sectors;

        ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);

        s->media_changed = 1;

        break;

    case WIN_READDMA_EXT:

        lba48 = 1;

        /* fall through */

    case WIN_READDMA:

    case WIN_READDMA_ONCE:

        if (!s->bs) {

            goto abort_cmd;

        }

	ide_cmd_lba48_transform(s, lba48);

        ide_sector_start_dma(s, IDE_DMA_READ);

        break;

    case WIN_WRITEDMA_EXT:

        lba48 = 1;

        /* fall through */

    case WIN_WRITEDMA:

    case WIN_WRITEDMA_ONCE:

        if (!s->bs) {

            goto abort_cmd;

        }

	ide_cmd_lba48_transform(s, lba48);

        ide_sector_start_dma(s, IDE_DMA_WRITE);

        s->media_changed = 1;

        break;

    case WIN_READ_NATIVE_MAX_EXT:

        lba48 = 1;

        /* fall through */

    case WIN_READ_NATIVE_MAX:

        /* Refuse if no sectors are addressable (e.g. medium not inserted) */

        if (s->nb_sectors == 0) {

            goto abort_cmd;

        }

	ide_cmd_lba48_transform(s, lba48);

        ide_set_sector(s, s->nb_sectors - 1);

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case WIN_CHECKPOWERMODE1:

    case WIN_CHECKPOWERMODE2:

        s->error = 0;

        s->nsector = 0xff; /* device active or idle */

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case WIN_SETFEATURES:

        if (!s->bs)

            goto abort_cmd;

        /* XXX: valid for CDROM ? */

        switch(s->feature) {

        case 0x02: /* write cache enable */

            bdrv_set_enable_write_cache(s->bs, true);

            identify_data = (uint16_t *)s->identify_data;

            put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1);

            s->status = READY_STAT | SEEK_STAT;

            ide_set_irq(s->bus);

            break;

        case 0x82: /* write cache disable */

            bdrv_set_enable_write_cache(s->bs, false);

            identify_data = (uint16_t *)s->identify_data;

            put_le16(identify_data + 85, (1 << 14) | 1);

            ide_flush_cache(s);

            break;

        case 0xcc: /* reverting to power-on defaults enable */

        case 0x66: /* reverting to power-on defaults disable */

        case 0xaa: /* read look-ahead enable */

        case 0x55: /* read look-ahead disable */

        case 0x05: /* set advanced power management mode */

        case 0x85: /* disable advanced power management mode */

        case 0x69: /* NOP */

        case 0x67: /* NOP */

        case 0x96: /* NOP */

        case 0x9a: /* NOP */

        case 0x42: /* enable Automatic Acoustic Mode */

        case 0xc2: /* disable Automatic Acoustic Mode */

            s->status = READY_STAT | SEEK_STAT;

            ide_set_irq(s->bus);

            break;

        case 0x03: { /* set transfer mode */

		uint8_t val = s->nsector & 0x07;

		identify_data = (uint16_t *)s->identify_data;

		switch (s->nsector >> 3) {

		case 0x00: /* pio default */

		case 0x01: /* pio mode */

			put_le16(identify_data + 62,0x07);

			put_le16(identify_data + 63,0x07);

			put_le16(identify_data + 88,0x3f);

			break;

                case 0x02: /* sigle word dma mode*/

			put_le16(identify_data + 62,0x07 | (1 << (val + 8)));

			put_le16(identify_data + 63,0x07);

			put_le16(identify_data + 88,0x3f);

			break;

		case 0x04: /* mdma mode */

			put_le16(identify_data + 62,0x07);

			put_le16(identify_data + 63,0x07 | (1 << (val + 8)));

			put_le16(identify_data + 88,0x3f);

			break;

		case 0x08: /* udma mode */

			put_le16(identify_data + 62,0x07);

			put_le16(identify_data + 63,0x07);

			put_le16(identify_data + 88,0x3f | (1 << (val + 8)));

			break;

		default:

			goto abort_cmd;

		}

            s->status = READY_STAT | SEEK_STAT;

            ide_set_irq(s->bus);

            break;

	}

        default:

            goto abort_cmd;

        }

        break;

    case WIN_FLUSH_CACHE:

    case WIN_FLUSH_CACHE_EXT:

        ide_flush_cache(s);

        break;

    case WIN_SEEK:

        /* XXX: Check that seek is within bounds */

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

        /* ATAPI commands */

    case WIN_PIDENTIFY:

        ide_atapi_identify(s);

        s->status = READY_STAT | SEEK_STAT;

        ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);

        ide_set_irq(s->bus);

        break;

    case WIN_DIAGNOSE:

        ide_set_signature(s);

        if (s->drive_kind == IDE_CD)

            s->status = 0; /* ATAPI spec (v6) section 9.10 defines packet

                            * devices to return a clear status register

                            * with READY_STAT *not* set. */

        else

            s->status = READY_STAT | SEEK_STAT;

        s->error = 0x01; /* Device 0 passed, Device 1 passed or not

                          * present.

                          */

        ide_set_irq(s->bus);

        break;

    case WIN_DEVICE_RESET:

        ide_set_signature(s);

        s->status = 0x00; /* NOTE: READY is _not_ set */

        s->error = 0x01;

        break;

    case WIN_PACKETCMD:

        /* overlapping commands not supported */

        if (s->feature & 0x02)

            goto abort_cmd;

        s->status = READY_STAT | SEEK_STAT;

        s->atapi_dma = s->feature & 1;

        s->nsector = 1;

        ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,

                           ide_atapi_cmd);

        break;

    /* CF-ATA commands */

    case CFA_REQ_EXT_ERROR_CODE:

        s->error = 0x09;    /* miscellaneous error */

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case CFA_ERASE_SECTORS:

    case CFA_WEAR_LEVEL:

#if 0

    /* This one has the same ID as CFA_WEAR_LEVEL and is required for

       Windows 8 to work with AHCI */

    case WIN_SECURITY_FREEZE_LOCK:

#endif

        if (val == CFA_WEAR_LEVEL)

            s->nsector = 0;

        if (val == CFA_ERASE_SECTORS)

            s->media_changed = 1;

        s->error = 0x00;

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case CFA_TRANSLATE_SECTOR:

        s->error = 0x00;

        s->status = READY_STAT | SEEK_STAT;

        memset(s->io_buffer, 0, 0x200);

        s->io_buffer[0x00] = s->hcyl;			/* Cyl MSB */

        s->io_buffer[0x01] = s->lcyl;			/* Cyl LSB */

        s->io_buffer[0x02] = s->select;			/* Head */

        s->io_buffer[0x03] = s->sector;			/* Sector */

        s->io_buffer[0x04] = ide_get_sector(s) >> 16;	/* LBA MSB */

        s->io_buffer[0x05] = ide_get_sector(s) >> 8;	/* LBA */

        s->io_buffer[0x06] = ide_get_sector(s) >> 0;	/* LBA LSB */

        s->io_buffer[0x13] = 0x00;				/* Erase flag */

        s->io_buffer[0x18] = 0x00;				/* Hot count */

        s->io_buffer[0x19] = 0x00;				/* Hot count */

        s->io_buffer[0x1a] = 0x01;				/* Hot count */

        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

        ide_set_irq(s->bus);

        break;

    case CFA_ACCESS_METADATA_STORAGE:

        switch (s->feature) {

        case 0x02:	/* Inquiry Metadata Storage */

            ide_cfata_metadata_inquiry(s);

            break;

        case 0x03:	/* Read Metadata Storage */

            ide_cfata_metadata_read(s);

            break;

        case 0x04:	/* Write Metadata Storage */

            ide_cfata_metadata_write(s);

            break;

        default:

            goto abort_cmd;

        }

        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

        s->status = 0x00; /* NOTE: READY is _not_ set */

        ide_set_irq(s->bus);

        break;

    case IBM_SENSE_CONDITION:

        switch (s->feature) {

        case 0x01:  /* sense temperature in device */

            s->nsector = 0x50;      /* +20 C */

            break;

        default:

            goto abort_cmd;

        }

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case WIN_SMART:

	if (s->hcyl != 0xc2 || s->lcyl != 0x4f)

		goto abort_cmd;

	if (!s->smart_enabled && s->feature != SMART_ENABLE)

		goto abort_cmd;

	switch (s->feature) {

	case SMART_DISABLE:

		s->smart_enabled = 0;

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

	case SMART_ENABLE:

		s->smart_enabled = 1;

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

	case SMART_ATTR_AUTOSAVE:

		switch (s->sector) {

		case 0x00:

		s->smart_autosave = 0;

		break;

		case 0xf1:

		s->smart_autosave = 1;

		break;

		default:

		goto abort_cmd;

		}

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

	case SMART_STATUS:

		if (!s->smart_errors) {

		s->hcyl = 0xc2;

		s->lcyl = 0x4f;

		} else {

		s->hcyl = 0x2c;

		s->lcyl = 0xf4;

		}

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

	case SMART_READ_THRESH:

		memset(s->io_buffer, 0, 0x200);

		s->io_buffer[0] = 0x01; /* smart struct version */

		for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {

		s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];

		s->io_buffer[2+1+(n*12)] = smart_attributes[n][11];

		}

		for (n=0; n<511; n++) /* checksum */

		s->io_buffer[511] += s->io_buffer[n];

		s->io_buffer[511] = 0x100 - s->io_buffer[511];

		s->status = READY_STAT | SEEK_STAT;

		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

		ide_set_irq(s->bus);

		break;

	case SMART_READ_DATA:

		memset(s->io_buffer, 0, 0x200);

		s->io_buffer[0] = 0x01; /* smart struct version */

		for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {

		    int i;

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

			s->io_buffer[2+i+(n*12)] = smart_attributes[n][i];

		    }

		}

		s->io_buffer[362] = 0x02 | (s->smart_autosave?0x80:0x00);

		if (s->smart_selftest_count == 0) {

		s->io_buffer[363] = 0;

		} else {

		s->io_buffer[363] =

			s->smart_selftest_data[3 +

					   (s->smart_selftest_count - 1) *

					   24];

		}

		s->io_buffer[364] = 0x20;

		s->io_buffer[365] = 0x01;

		/* offline data collection capacity: execute + self-test*/

		s->io_buffer[367] = (1<<4 | 1<<3 | 1);

		s->io_buffer[368] = 0x03; /* smart capability (1) */

		s->io_buffer[369] = 0x00; /* smart capability (2) */

		s->io_buffer[370] = 0x01; /* error logging supported */

		s->io_buffer[372] = 0x02; /* minutes for poll short test */

		s->io_buffer[373] = 0x36; /* minutes for poll ext test */

		s->io_buffer[374] = 0x01; /* minutes for poll conveyance */

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

		s->io_buffer[511] += s->io_buffer[n];

		s->io_buffer[511] = 0x100 - s->io_buffer[511];

		s->status = READY_STAT | SEEK_STAT;

		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

		ide_set_irq(s->bus);

		break;

	case SMART_READ_LOG:

		switch (s->sector) {

		case 0x01: /* summary smart error log */

		memset(s->io_buffer, 0, 0x200);

		s->io_buffer[0] = 0x01;

		s->io_buffer[1] = 0x00; /* no error entries */

		s->io_buffer[452] = s->smart_errors & 0xff;

		s->io_buffer[453] = (s->smart_errors & 0xff00) >> 8;

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

			s->io_buffer[511] += s->io_buffer[n];

		s->io_buffer[511] = 0x100 - s->io_buffer[511];

		break;

		case 0x06: /* smart self test log */

		memset(s->io_buffer, 0, 0x200);

		s->io_buffer[0] = 0x01;

		if (s->smart_selftest_count == 0) {

			s->io_buffer[508] = 0;

		} else {

			s->io_buffer[508] = s->smart_selftest_count;

			for (n=2; n<506; n++)

			s->io_buffer[n] = s->smart_selftest_data[n];

		}

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

			s->io_buffer[511] += s->io_buffer[n];

		s->io_buffer[511] = 0x100 - s->io_buffer[511];

		break;

		default:

		goto abort_cmd;

		}

		s->status = READY_STAT | SEEK_STAT;

		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

		ide_set_irq(s->bus);

		break;

	case SMART_EXECUTE_OFFLINE:

		switch (s->sector) {

		case 0: /* off-line routine */

		case 1: /* short self test */

		case 2: /* extended self test */

		s->smart_selftest_count++;

		if(s->smart_selftest_count > 21)

			s->smart_selftest_count = 0;

		n = 2 + (s->smart_selftest_count - 1) * 24;

		s->smart_selftest_data[n] = s->sector;

		s->smart_selftest_data[n+1] = 0x00; /* OK and finished */

		s->smart_selftest_data[n+2] = 0x34; /* hour count lsb */

		s->smart_selftest_data[n+3] = 0x12; /* hour count msb */

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

		default:

		goto abort_cmd;

		}

		break;

	default:

		goto abort_cmd;

	}

	break;

    default:

        /* should not be reachable */

    abort_cmd:

        ide_abort_command(s);

        ide_set_irq(s->bus);

        break;

    }

}


av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth,

                             const int chroma_format_idc)

{

#undef FUNC

#define FUNC(a, depth) a ## _ ## depth ## _c

#define ADDPX_DSP(depth) \

    c->h264_add_pixels4_clear = FUNC(ff_h264_add_pixels4, depth);\

    c->h264_add_pixels8_clear = FUNC(ff_h264_add_pixels8, depth)

    if (bit_depth > 8 && bit_depth <= 16) {

        ADDPX_DSP(16);

    } else {

        ADDPX_DSP(8);

    }

#define H264_DSP(depth) \

    c->h264_idct_add= FUNC(ff_h264_idct_add, depth);\

    c->h264_idct8_add= FUNC(ff_h264_idct8_add, depth);\

    c->h264_idct_dc_add= FUNC(ff_h264_idct_dc_add, depth);\

    c->h264_idct8_dc_add= FUNC(ff_h264_idct8_dc_add, depth);\

    c->h264_idct_add16     = FUNC(ff_h264_idct_add16, depth);\

    c->h264_idct8_add4     = FUNC(ff_h264_idct8_add4, depth);\

    if (chroma_format_idc == 1)\

        c->h264_idct_add8  = FUNC(ff_h264_idct_add8, depth);\

    else\

        c->h264_idct_add8  = FUNC(ff_h264_idct_add8_422, depth);\

    c->h264_idct_add16intra= FUNC(ff_h264_idct_add16intra, depth);\

    c->h264_luma_dc_dequant_idct= FUNC(ff_h264_luma_dc_dequant_idct, depth);\

    if (chroma_format_idc == 1)\

        c->h264_chroma_dc_dequant_idct= FUNC(ff_h264_chroma_dc_dequant_idct, depth);\

    else\

        c->h264_chroma_dc_dequant_idct= FUNC(ff_h264_chroma422_dc_dequant_idct, depth);\

\

    c->weight_h264_pixels_tab[0]= FUNC(weight_h264_pixels16, depth);\

    c->weight_h264_pixels_tab[1]= FUNC(weight_h264_pixels8, depth);\

    c->weight_h264_pixels_tab[2]= FUNC(weight_h264_pixels4, depth);\

    c->weight_h264_pixels_tab[3]= FUNC(weight_h264_pixels2, depth);\

    c->biweight_h264_pixels_tab[0]= FUNC(biweight_h264_pixels16, depth);\

    c->biweight_h264_pixels_tab[1]= FUNC(biweight_h264_pixels8, depth);\

    c->biweight_h264_pixels_tab[2]= FUNC(biweight_h264_pixels4, depth);\

    c->biweight_h264_pixels_tab[3]= FUNC(biweight_h264_pixels2, depth);\

\

    c->h264_v_loop_filter_luma= FUNC(h264_v_loop_filter_luma, depth);\

    c->h264_h_loop_filter_luma= FUNC(h264_h_loop_filter_luma, depth);\

    c->h264_h_loop_filter_luma_mbaff= FUNC(h264_h_loop_filter_luma_mbaff, depth);\

    c->h264_v_loop_filter_luma_intra= FUNC(h264_v_loop_filter_luma_intra, depth);\

    c->h264_h_loop_filter_luma_intra= FUNC(h264_h_loop_filter_luma_intra, depth);\

    c->h264_h_loop_filter_luma_mbaff_intra= FUNC(h264_h_loop_filter_luma_mbaff_intra, depth);\

    c->h264_v_loop_filter_chroma= FUNC(h264_v_loop_filter_chroma, depth);\

    if (chroma_format_idc == 1)\

        c->h264_h_loop_filter_chroma= FUNC(h264_h_loop_filter_chroma, depth);\

    else\

        c->h264_h_loop_filter_chroma= FUNC(h264_h_loop_filter_chroma422, depth);\

    if (chroma_format_idc == 1)\

        c->h264_h_loop_filter_chroma_mbaff= FUNC(h264_h_loop_filter_chroma_mbaff, depth);\

    else\

        c->h264_h_loop_filter_chroma_mbaff= FUNC(h264_h_loop_filter_chroma422_mbaff, depth);\

    c->h264_v_loop_filter_chroma_intra= FUNC(h264_v_loop_filter_chroma_intra, depth);\

    if (chroma_format_idc == 1)\

        c->h264_h_loop_filter_chroma_intra= FUNC(h264_h_loop_filter_chroma_intra, depth);\

    else\

        c->h264_h_loop_filter_chroma_intra= FUNC(h264_h_loop_filter_chroma422_intra, depth);\

    if (chroma_format_idc == 1)\

        c->h264_h_loop_filter_chroma_mbaff_intra= FUNC(h264_h_loop_filter_chroma_mbaff_intra, depth);\

    else\

        c->h264_h_loop_filter_chroma_mbaff_intra= FUNC(h264_h_loop_filter_chroma422_mbaff_intra, depth);\

    c->h264_loop_filter_strength= NULL;

    switch (bit_depth) {

    case 9:

        H264_DSP(9);

        break;

    case 10:

        H264_DSP(10);

        break;

    default:

        H264_DSP(8);

        break;

    }

    c->h264_find_start_code_candidate = h264_find_start_code_candidate_c;

    if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc);

    if (ARCH_PPC) ff_h264dsp_init_ppc(c, bit_depth, chroma_format_idc);

    if (ARCH_X86) ff_h264dsp_init_x86(c, bit_depth, chroma_format_idc);

}


static void gen_slbia(DisasContext *ctx)

{

#if defined(CONFIG_USER_ONLY)

    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);

#else

    if (unlikely(ctx->pr)) {

        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);

        return;

    }

    gen_helper_slbia(cpu_env);

#endif

}


int nbd_client_init(BlockDriverState *bs,

                    QIOChannelSocket *sioc,

                    const char *export,

                    QCryptoTLSCreds *tlscreds,

                    const char *hostname,

                    Error **errp)

{

    NbdClientSession *client = nbd_get_client_session(bs);

    int ret;

    /* NBD handshake */

    logout("session init %s\n", export);

    qio_channel_set_blocking(QIO_CHANNEL(sioc), true, NULL);

    ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), export,

                                &client->nbdflags,

                                tlscreds, hostname,

                                &client->ioc,

                                &client->size, errp);

    if (ret < 0) {

        logout("Failed to negotiate with the NBD server\n");

        return ret;

    }

    if (client->nbdflags & NBD_FLAG_SEND_FUA) {

        bs->supported_write_flags = BDRV_REQ_FUA;

    }

    qemu_co_mutex_init(&client->send_mutex);

    qemu_co_mutex_init(&client->free_sema);

    client->sioc = sioc;

    object_ref(OBJECT(client->sioc));

    if (!client->ioc) {

        client->ioc = QIO_CHANNEL(sioc);

        object_ref(OBJECT(client->ioc));

    }

    /* Now that we're connected, set the socket to be non-blocking and

     * kick the reply mechanism.  */

    qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL);

    nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs));

    logout("Established connection with NBD server\n");

    return 0;

}


static inline void rgtc_block_internal(uint8_t *dst, ptrdiff_t stride,

                                       const uint8_t *block,

                                       const int *color_tab)

{

    uint8_t indices[16];

    int x, y;

    decompress_indices(indices, block + 2);

    /* Only one or two channels are stored at most, since it only used to

     * compress specular (black and white) or normal (red and green) maps.

     * Although the standard says to zero out unused components, many

     * implementations fill all of them with the same value. */

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

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

            int i = indices[x + y * 4];

            /* Interval expansion from [-1 1] or [0 1] to [0 255]. */

            int c = color_tab[i];

            uint32_t pixel = RGBA(c, c, c, 255);

            AV_WL32(dst + x * 4 + y * stride, pixel);

        }

    }

}


int sclp_service_call(uint64_t sccb, uint32_t code)

{

    int r = 0;

    SCCB work_sccb;

    hwaddr sccb_len = sizeof(SCCB);

    /* first some basic checks on program checks */

    if (cpu_physical_memory_is_io(sccb)) {

        r = -PGM_ADDRESSING;

        goto out;

    }

    if (sccb & ~0x7ffffff8ul) {

        r = -PGM_SPECIFICATION;

        goto out;

    }

    /*

     * we want to work on a private copy of the sccb, to prevent guests

     * from playing dirty tricks by modifying the memory content after

     * the host has checked the values

     */

    cpu_physical_memory_read(sccb, &work_sccb, sccb_len);

    /* Valid sccb sizes */

    if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader) ||

        be16_to_cpu(work_sccb.h.length) > SCCB_SIZE) {

        r = -PGM_SPECIFICATION;

        goto out;

    }

    sclp_execute((SCCB *)&work_sccb, code);

    cpu_physical_memory_write(sccb, &work_sccb,

                              be16_to_cpu(work_sccb.h.length));

    sclp_service_interrupt(sccb);

out:

    return r;

}


unsigned avutil_version(void)
{
    av_assert0(AV_PIX_FMT_VDA_VLD == 81); //check if the pix fmt enum has not had anything inserted or removed by mistake
    av_assert0(AV_SAMPLE_FMT_DBLP == 9);
    av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4);
    av_assert0(AV_PICTURE_TYPE_BI == 7);
    av_assert0(LIBAVUTIL_VERSION_MICRO >= 100);
    av_assert0(HAVE_MMX2 == HAVE_MMXEXT);
    return LIBAVUTIL_VERSION_INT;


static CharDriverState *qemu_chr_open_tty_fd(int fd,

                                             ChardevCommon *backend,

                                             Error **errp)

{

    CharDriverState *chr;

    tty_serial_init(fd, 115200, 'N', 8, 1);

    chr = qemu_chr_open_fd(fd, fd, backend, errp);

    chr->chr_ioctl = tty_serial_ioctl;

    chr->chr_close = qemu_chr_close_tty;

    return chr;


static int vhost_user_set_owner(struct vhost_dev *dev)

{

    VhostUserMsg msg = {

        .request = VHOST_USER_SET_OWNER,

        .flags = VHOST_USER_VERSION,

    };

    vhost_user_write(dev, &msg, NULL, 0);

    return 0;

}


static int mxf_read_source_clip(MXFStructuralComponent *source_clip, ByteIOContext *pb, int tag)

{

    switch(tag) {

    case 0x0202:

        source_clip->duration = get_be64(pb);

        break;

    case 0x1201:

        source_clip->start_position = get_be64(pb);

        break;

    case 0x1101:

        /* UMID, only get last 16 bytes */

        url_fskip(pb, 16);

        get_buffer(pb, source_clip->source_package_uid, 16);

        break;

    case 0x1102:

        source_clip->source_track_id = get_be32(pb);

        break;

    }

    return 0;

}


static void adlib_realizefn (DeviceState *dev, Error **errp)

{

    AdlibState *s = ADLIB(dev);

    PortioList *port_list = g_new(PortioList, 1);

    struct audsettings as;

    if (glob_adlib) {

        error_setg (errp, "Cannot create more than 1 adlib device");

        return;

    }

    glob_adlib = s;

#ifdef HAS_YMF262

    if (YMF262Init (1, 14318180, s->freq)) {

        error_setg (errp, "YMF262Init %d failed", s->freq);

        return;

    }

    else {

        YMF262SetTimerHandler (0, timer_handler, 0);

        s->enabled = 1;

    }

#else

    s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, s->freq);

    if (!s->opl) {

        error_setg (errp, "OPLCreate %d failed", s->freq);

        return;

    }

    else {

        OPLSetTimerHandler (s->opl, timer_handler, 0);

        s->enabled = 1;

    }

#endif

    as.freq = s->freq;

    as.nchannels = SHIFT;

    as.fmt = AUD_FMT_S16;

    as.endianness = AUDIO_HOST_ENDIANNESS;

    AUD_register_card ("adlib", &s->card);

    s->voice = AUD_open_out (

        &s->card,

        s->voice,

        "adlib",

        s,

        adlib_callback,

        &as

        );

    if (!s->voice) {

        Adlib_fini (s);

        error_setg (errp, "Initializing audio voice failed");

        return;

    }

    s->samples = AUD_get_buffer_size_out (s->voice) >> SHIFT;

    s->mixbuf = g_malloc0 (s->samples << SHIFT);

    adlib_portio_list[0].offset = s->port;

    adlib_portio_list[1].offset = s->port + 8;

    portio_list_init (port_list, OBJECT(s), adlib_portio_list, s, "adlib");

    portio_list_add (port_list, isa_address_space_io(&s->parent_obj), 0);

}


static int lag_decode_arith_plane(LagarithContext *l, uint8_t *dst,

                                  int width, int height, int stride,

                                  const uint8_t *src, int src_size)

{

    int i = 0;

    int read = 0;

    uint32_t length;

    uint32_t offset = 1;

    int esc_count = src[0];

    GetBitContext gb;

    lag_rac rac;

    rac.avctx = l->avctx;

    l->zeros = 0;

    if (esc_count < 4) {

        length = width * height;

        if (esc_count && AV_RL32(src + 1) < length) {

            length = AV_RL32(src + 1);

            offset += 4;

        }

        init_get_bits(&gb, src + offset, src_size * 8);

        if (lag_read_prob_header(&rac, &gb) < 0)

            return -1;

        ff_lag_rac_init(&rac, &gb, length - stride);

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

            read += lag_decode_line(l, &rac, dst + (i * stride), width,

                                    stride, esc_count);

        if (read > length)

            av_log(l->avctx, AV_LOG_WARNING,

                   "Output more bytes than length (%d of %d)\n", read,

                   length);

    } else if (esc_count < 8) {

        esc_count -= 4;

        if (esc_count > 0) {

            /* Zero run coding only, no range coding. */

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

                src += lag_decode_zero_run_line(l, dst + (i * stride), src,

                                                width, esc_count);

        } else {

            /* Plane is stored uncompressed */

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

                memcpy(dst + (i * stride), src, width);

                src += width;

            }

        }

    } else if (esc_count == 0xff) {

        /* Plane is a solid run of given value */

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

            memset(dst + i * stride, src[1], width);

        /* Do not apply prediction.

           Note: memset to 0 above, setting first value to src[1]

           and applying prediction gives the same result. */

        return 0;

    } else {

        av_log(l->avctx, AV_LOG_ERROR,

               "Invalid zero run escape code! (%#x)\n", esc_count);

        return -1;

    }

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

        lag_pred_line(l, dst, width, stride, i);

        dst += stride;

    }

    return 0;

}


static void check_pred16x16(H264PredContext *h, uint8_t *buf0, uint8_t *buf1,

                            int codec, int chroma_format, int bit_depth)

{

    if (chroma_format == 1) {

        int pred_mode;

        declare_func(void, uint8_t *src, ptrdiff_t stride);

        for (pred_mode = 0; pred_mode < 9; pred_mode++) {

            if (check_pred_func(h->pred16x16[pred_mode], "16x16", pred16x16_modes[codec][pred_mode])) {

                randomize_buffers();

                call_ref(src0, 48);

                call_new(src1, 48);

                if (memcmp(buf0, buf1, BUF_SIZE))

                    fail();

                bench_new(src1, 48);

            }

        }

    }

}


int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size)

{

    if (size < 0 || avpkt->size < 0 || size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) {

        av_log(avctx, AV_LOG_ERROR, "Size %d invalid\n", size);

        return AVERROR(EINVAL);

    }

    if (avctx) {

        av_assert0(!avpkt->data || avpkt->data != avctx->internal->byte_buffer);

        if (!avpkt->data || avpkt->size < size) {

            av_fast_padded_malloc(&avctx->internal->byte_buffer, &avctx->internal->byte_buffer_size, size);

            avpkt->data = avctx->internal->byte_buffer;

            avpkt->size = avctx->internal->byte_buffer_size;

            avpkt->destruct = NULL;

        }

    }

    if (avpkt->data) {

        AVBufferRef *buf = avpkt->buf;

#if FF_API_DESTRUCT_PACKET

        void *destruct = avpkt->destruct;

#endif

        if (avpkt->size < size) {

            av_log(avctx, AV_LOG_ERROR, "User packet is too small (%d < %d)\n", avpkt->size, size);

            return AVERROR(EINVAL);

        }

        av_init_packet(avpkt);

#if FF_API_DESTRUCT_PACKET

        avpkt->destruct = destruct;

#endif

        avpkt->buf      = buf;

        avpkt->size     = size;

        return 0;

    } else {

        int ret = av_new_packet(avpkt, size);

        if (ret < 0)

            av_log(avctx, AV_LOG_ERROR, "Failed to allocate packet of size %d\n", size);

        return ret;

    }

}


static int sort_stt(FFV1Context *s, uint8_t stt[256])

{

    int i, i2, changed, print = 0;

    do {

        changed = 0;

        for (i = 12; i < 244; i++) {

            for (i2 = i + 1; i2 < 245 && i2 < i + 4; i2++) {

#define COST(old, new)                                      \

    s->rc_stat[old][0] * -log2((256 - (new)) / 256.0) +     \

    s->rc_stat[old][1] * -log2((new)         / 256.0)

#define COST2(old, new)                         \

    COST(old, new) + COST(256 - (old), 256 - (new))

                double size0 = COST2(i,  i) + COST2(i2, i2);

                double sizeX = COST2(i, i2) + COST2(i2, i);

                if (sizeX < size0 && i != 128 && i2 != 128) {

                    int j;

                    FFSWAP(int, stt[i], stt[i2]);

                    FFSWAP(int, s->rc_stat[i][0], s->rc_stat[i2][0]);

                    FFSWAP(int, s->rc_stat[i][1], s->rc_stat[i2][1]);

                    if (i != 256 - i2) {

                        FFSWAP(int, stt[256 - i], stt[256 - i2]);

                        FFSWAP(int, s->rc_stat[256 - i][0], s->rc_stat[256 - i2][0]);

                        FFSWAP(int, s->rc_stat[256 - i][1], s->rc_stat[256 - i2][1]);

                    }

                    for (j = 1; j < 256; j++) {

                        if (stt[j] == i)

                            stt[j] = i2;

                        else if (stt[j] == i2)

                            stt[j] = i;

                        if (i != 256 - i2) {

                            if (stt[256 - j] == 256 - i)

                                stt[256 - j] = 256 - i2;

                            else if (stt[256 - j] == 256 - i2)

                                stt[256 - j] = 256 - i;

                        }

                    }

                    print = changed = 1;

                }

            }

        }

    } while (changed);

    return print;

}


static void dvbsub_parse_object_segment(AVCodecContext *avctx,

                                        const uint8_t *buf, int buf_size)

{

    DVBSubContext *ctx = avctx->priv_data;

    const uint8_t *buf_end = buf + buf_size;

    const uint8_t *block;

    int object_id;

    DVBSubObject *object;

    DVBSubObjectDisplay *display;

    int top_field_len, bottom_field_len;

    int coding_method, non_modifying_color;

    object_id = AV_RB16(buf);

    buf += 2;

    object = get_object(ctx, object_id);

    if (!object)

        return;

    coding_method = ((*buf) >> 2) & 3;

    non_modifying_color = ((*buf++) >> 1) & 1;

    if (coding_method == 0) {

        top_field_len = AV_RB16(buf);

        buf += 2;

        bottom_field_len = AV_RB16(buf);

        buf += 2;

        if (buf + top_field_len + bottom_field_len > buf_end) {

            av_log(avctx, AV_LOG_ERROR, "Field data size too large\n");

            return;

        }

        for (display = object->display_list; display; display = display->object_list_next) {

            block = buf;

            dvbsub_parse_pixel_data_block(avctx, display, block, top_field_len, 0,

                                            non_modifying_color);

            if (bottom_field_len > 0)

                block = buf + top_field_len;

            else

                bottom_field_len = top_field_len;

            dvbsub_parse_pixel_data_block(avctx, display, block, bottom_field_len, 1,

                                            non_modifying_color);

        }

/*  } else if (coding_method == 1) {*/

    } else {

        av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method);

    }

}


static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt,

                             const AVFrame *pict, int *got_packet)

{

    SVQ1EncContext *const s = avctx->priv_data;

    AVFrame *const p        = avctx->coded_frame;

    int i, ret;

    if (!pkt->data &&

        (ret = av_new_packet(pkt, s->y_block_width * s->y_block_height *

                             MAX_MB_BYTES * 3 + FF_MIN_BUFFER_SIZE)) < 0) {

        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");

        return ret;

    }

    if (avctx->pix_fmt != AV_PIX_FMT_YUV410P) {

        av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");

        return -1;

    }

    if (!s->current_picture->data[0]) {

        ret = ff_get_buffer(avctx, s->current_picture, 0);

        if (ret < 0)

            return ret;

    }

    if (!s->last_picture->data[0]) {

        ret = ff_get_buffer(avctx, s->last_picture, 0);

        if (ret < 0)

            return ret;

    }

    if (!s->scratchbuf) {

        s->scratchbuf = av_malloc(s->current_picture->linesize[0] * 16 * 2);

        if (!s->scratchbuf)

            return AVERROR(ENOMEM);

    }

    FFSWAP(AVFrame*, s->current_picture, s->last_picture);

    init_put_bits(&s->pb, pkt->data, pkt->size);

    p->pict_type = avctx->gop_size && avctx->frame_number % avctx->gop_size ?

                   AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;

    p->key_frame = p->pict_type == AV_PICTURE_TYPE_I;

    p->quality   = pict->quality;

    svq1_write_header(s, p->pict_type);

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

        if (svq1_encode_plane(s, i,

                              pict->data[i],

                              s->last_picture->data[i],

                              s->current_picture->data[i],

                              s->frame_width  / (i ? 4 : 1),

                              s->frame_height / (i ? 4 : 1),

                              pict->linesize[i],

                              s->current_picture->linesize[i]) < 0)

            return -1;

    // avpriv_align_put_bits(&s->pb);

    while (put_bits_count(&s->pb) & 31)

        put_bits(&s->pb, 1, 0);

    flush_put_bits(&s->pb);

    pkt->size = put_bits_count(&s->pb) / 8;

    if (p->pict_type == AV_PICTURE_TYPE_I)

        pkt->flags |= AV_PKT_FLAG_KEY;

    *got_packet = 1;

    return 0;

}


static inline void RENAME(rgb32to16)(const uint8_t *src, uint8_t *dst, unsigned src_size)

{

	const uint8_t *s = src;

	const uint8_t *end;

#ifdef HAVE_MMX

	const uint8_t *mm_end;

#endif

	uint16_t *d = (uint16_t *)dst;

	end = s + src_size;

#ifdef HAVE_MMX

	mm_end = end - 15;

#if 1 //is faster only if multiplies are reasonable fast (FIXME figure out on which cpus this is faster, on Athlon its slightly faster)

	asm volatile(

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

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

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

		".balign 16			\n\t"

		"1:				\n\t"

		PREFETCH" 32(%1)		\n\t"

		"movd	(%1), %%mm0		\n\t"

		"movd	4(%1), %%mm3		\n\t"

		"punpckldq 8(%1), %%mm0		\n\t"

		"punpckldq 12(%1), %%mm3	\n\t"

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

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

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

		"pand %%mm6, %%mm3		\n\t"

		"pmaddwd %%mm7, %%mm0		\n\t"

		"pmaddwd %%mm7, %%mm3		\n\t"

		"pand %%mm5, %%mm1		\n\t"

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

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

		"por %%mm4, %%mm3		\n\t"

		"psrld $5, %%mm0		\n\t"

		"pslld $11, %%mm3		\n\t"

		"por %%mm3, %%mm0		\n\t"

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

		"addl $16, %1			\n\t"

		"addl $8, %0			\n\t"

		"cmpl %2, %1			\n\t"

		" jb 1b				\n\t"

		: "+r" (d), "+r"(s)

		: "r" (mm_end), "m" (mask3216g), "m" (mask3216br), "m" (mul3216)

	);

#else

	__asm __volatile(PREFETCH"	%0"::"m"(*src):"memory");

	__asm __volatile(

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

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

	    ::"m"(red_16mask),"m"(green_16mask));

	while(s < mm_end)

	{

	    __asm __volatile(

		PREFETCH" 32%1\n\t"

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

		"movd	4%1, %%mm3\n\t"

		"punpckldq 8%1, %%mm0\n\t"

		"punpckldq 12%1, %%mm3\n\t"

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

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

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

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

		"psrlq	$3, %%mm0\n\t"

		"psrlq	$3, %%mm3\n\t"

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

		"pand	%2, %%mm3\n\t"

		"psrlq	$5, %%mm1\n\t"

		"psrlq	$5, %%mm4\n\t"

		"pand	%%mm6, %%mm1\n\t"

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

		"psrlq	$8, %%mm2\n\t"

		"psrlq	$8, %%mm5\n\t"

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

		"pand	%%mm7, %%mm5\n\t"

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

		"por	%%mm4, %%mm3\n\t"

		"por	%%mm2, %%mm0\n\t"

		"por	%%mm5, %%mm3\n\t"

		"psllq	$16, %%mm3\n\t"

		"por	%%mm3, %%mm0\n\t"

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

		:"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");

		d += 4;

		s += 16;

	}

#endif

	__asm __volatile(SFENCE:::"memory");

	__asm __volatile(EMMS:::"memory");

#endif

	while(s < end)

	{

		const int src= *((uint32_t*)s)++;

		*d++ = ((src&0xFF)>>3) + ((src&0xFC00)>>5) + ((src&0xF80000)>>8);

//		*d++ = ((src>>3)&0x1F) + ((src>>5)&0x7E0) + ((src>>8)&0xF800);

	}

}


static int decode_frame(AVCodecContext *avctx,

                        void *data, int *data_size,

                        uint8_t *buf, int buf_size)

{

    MDECContext * const a = avctx->priv_data;

    AVFrame *picture = data;

    AVFrame * const p= (AVFrame*)&a->picture;

    int i;

    /* special case for last picture */

    if (buf_size == 0) {

        return 0;

    }

    if(p->data[0])

        avctx->release_buffer(avctx, p);

    p->reference= 0;

    if(avctx->get_buffer(avctx, p) < 0){

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

        return -1;

    }

    p->pict_type= I_TYPE;

    p->key_frame= 1;

    a->last_dc[0]=

    a->last_dc[1]=

    a->last_dc[2]= 0;

    a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);

    for(i=0; i<buf_size; i+=2){

        a->bitstream_buffer[i]  = buf[i+1];

        a->bitstream_buffer[i+1]= buf[i  ];

    }

    init_get_bits(&a->gb, a->bitstream_buffer, buf_size*8);

    /* skip over 4 preamble bytes in stream (typically 0xXX 0xXX 0x00 0x38) */

    skip_bits(&a->gb, 32);

    a->qscale=  get_bits(&a->gb, 16);

    a->version= get_bits(&a->gb, 16);

//    printf("qscale:%d (0x%X), version:%d (0x%X)\n", a->qscale, a->qscale, a->version, a->version);

    for(a->mb_x=0; a->mb_x<a->mb_width; a->mb_x++){

        for(a->mb_y=0; a->mb_y<a->mb_height; a->mb_y++){

            if( decode_mb(a, a->block) <0)

                return -1;

            idct_put(a, a->mb_x, a->mb_y);

        }

    }

//    p->quality= (32 + a->inv_qscale/2)/a->inv_qscale;

//    memset(p->qscale_table, p->quality, p->qstride*a->mb_height);

    *picture= *(AVFrame*)&a->picture;

    *data_size = sizeof(AVPicture);

    emms_c();

    return (get_bits_count(&a->gb)+31)/32*4;

}


void OPPROTO op_srli_T0 (void)

{

    T0 = T0 >> PARAM1;

    RETURN();

}


static void bdrv_qed_invalidate_cache(BlockDriverState *bs)
{
    BDRVQEDState *s = bs->opaque;
    bdrv_qed_close(bs);
    memset(s, 0, sizeof(BDRVQEDState));
    bdrv_qed_open(bs, NULL, bs->open_flags, NULL);
}


void syscall_init(void)
{
    IOCTLEntry *ie;
    const argtype *arg_type;
    int size;
    int i;
#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
#include "syscall_types.h"
#undef STRUCT
#undef STRUCT_SPECIAL
    /* Build target_to_host_errno_table[] table from
     * host_to_target_errno_table[]. */
    for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
        target_to_host_errno_table[host_to_target_errno_table[i]] = i;
    }
    /* we patch the ioctl size if necessary. We rely on the fact that
       no ioctl has all the bits at '1' in the size field */
    ie = ioctl_entries;
    while (ie->target_cmd != 0) {
        if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
            TARGET_IOC_SIZEMASK) {
            arg_type = ie->arg_type;
            if (arg_type[0] != TYPE_PTR) {
                fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
                        ie->target_cmd);
                exit(1);
            }
            arg_type++;
            size = thunk_type_size(arg_type, 0);
            ie->target_cmd = (ie->target_cmd &
                              ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
                (size << TARGET_IOC_SIZESHIFT);
        }
        /* automatic consistency check if same arch */
#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
    (defined(__x86_64__) && defined(TARGET_X86_64))
        if (unlikely(ie->target_cmd != ie->host_cmd)) {
            fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
                    ie->name, ie->target_cmd, ie->host_cmd);
        }
#endif
        ie++;
    }
}


static void null_end_frame(AVFilterLink *inlink) { }


void qemu_init_vcpu(void *_env)

{

    CPUState *env = _env;

    int r;

    env->nr_cores = smp_cores;

    env->nr_threads = smp_threads;

    if (kvm_enabled()) {

        r = kvm_init_vcpu(env);

        if (r < 0) {

            fprintf(stderr, "kvm_init_vcpu failed: %s\n", strerror(-r));

            exit(1);

        }

        qemu_kvm_init_cpu_signals(env);

    } else {

        qemu_tcg_init_cpu_signals();

    }

}


static void migrate_finish_set_state(MigrationState *s, int new_state)

{

    if (atomic_cmpxchg(&s->state, MIG_STATE_ACTIVE, new_state) == new_state) {

        trace_migrate_set_state(new_state);

    }

}


static void ohci_reset(OHCIState *ohci)

{

    OHCIPort *port;

    int i;

    ohci->ctl = 0;

    ohci->old_ctl = 0;

    ohci->status = 0;

    ohci->intr_status = 0;

    ohci->intr = OHCI_INTR_MIE;

    ohci->hcca = 0;

    ohci->ctrl_head = ohci->ctrl_cur = 0;

    ohci->bulk_head = ohci->bulk_cur = 0;

    ohci->per_cur = 0;

    ohci->done = 0;

    ohci->done_count = 7;

    /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?

     * I took the value linux sets ...

     */

    ohci->fsmps = 0x2778;

    ohci->fi = 0x2edf;

    ohci->fit = 0;

    ohci->frt = 0;

    ohci->frame_number = 0;

    ohci->pstart = 0;

    ohci->lst = OHCI_LS_THRESH;

    ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;

    ohci->rhdesc_b = 0x0; /* Impl. specific */

    ohci->rhstatus = 0;

    for (i = 0; i < ohci->num_ports; i++)

      {

        port = &ohci->rhport[i];

        port->ctrl = 0;

        if (port->port.dev)

            ohci_attach(&port->port, port->port.dev);

      }

    if (ohci->async_td) {

        usb_cancel_packet(&ohci->usb_packet);

        ohci->async_td = 0;

    }

    dprintf("usb-ohci: Reset %s\n", ohci->name);

}


static int qxl_init_primary(PCIDevice *dev)

{

    PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);

    VGACommonState *vga = &qxl->vga;

    PortioList *qxl_vga_port_list = g_new(PortioList, 1);

    int rc;

    qxl->id = 0;

    qxl_init_ramsize(qxl);

    vga->vram_size_mb = qxl->vga.vram_size >> 20;

    vga_common_init(vga, OBJECT(dev), true);

    vga_init(vga, OBJECT(dev),

             pci_address_space(dev), pci_address_space_io(dev), false);

    portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,

                     vga, "vga");

    portio_list_set_flush_coalesced(qxl_vga_port_list);

    portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);

    vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);

    qemu_spice_display_init_common(&qxl->ssd);

    rc = qxl_init_common(qxl);

    if (rc != 0) {

        return rc;

    }

    qxl->ssd.dcl.ops = &display_listener_ops;

    qxl->ssd.dcl.con = vga->con;

    register_displaychangelistener(&qxl->ssd.dcl);

    return rc;

}


static void nbd_trip(void *opaque)

{

    NBDClient *client = opaque;

    NBDExport *exp = client->exp;

    NBDRequest *req;

    struct nbd_request request;

    struct nbd_reply reply;

    ssize_t ret;

    uint32_t command;

    TRACE("Reading request.");

    if (client->closing) {

        return;

    }

    req = nbd_request_get(client);

    ret = nbd_co_receive_request(req, &request);

    if (ret == -EAGAIN) {

        goto done;

    }

    if (ret == -EIO) {

        goto out;

    }

    reply.handle = request.handle;

    reply.error = 0;

    if (ret < 0) {

        reply.error = -ret;

        goto error_reply;

    }

    command = request.type & NBD_CMD_MASK_COMMAND;

    if (command != NBD_CMD_DISC && (request.from + request.len) > exp->size) {

            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64

            ", Offset: %" PRIu64 "\n",

                    request.from, request.len,

                    (uint64_t)exp->size, (uint64_t)exp->dev_offset);

        LOG("requested operation past EOF--bad client?");

        goto invalid_request;

    }

    if (client->closing) {

        /*

         * The client may be closed when we are blocked in

         * nbd_co_receive_request()

         */

        goto done;

    }

    switch (command) {

    case NBD_CMD_READ:

        TRACE("Request type is READ");

        if (request.type & NBD_CMD_FLAG_FUA) {

            ret = blk_co_flush(exp->blk);

            if (ret < 0) {

                LOG("flush failed");

                reply.error = -ret;

                goto error_reply;

            }

        }

        ret = blk_read(exp->blk,

                       (request.from + exp->dev_offset) / BDRV_SECTOR_SIZE,

                       req->data, request.len / BDRV_SECTOR_SIZE);

        if (ret < 0) {

            LOG("reading from file failed");

            reply.error = -ret;

            goto error_reply;

        }

        TRACE("Read %u byte(s)", request.len);

        if (nbd_co_send_reply(req, &reply, request.len) < 0)

            goto out;

        break;

    case NBD_CMD_WRITE:

        TRACE("Request type is WRITE");

        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {

            TRACE("Server is read-only, return error");

            reply.error = EROFS;

            goto error_reply;

        }

        TRACE("Writing to device");

        ret = blk_write(exp->blk,

                        (request.from + exp->dev_offset) / BDRV_SECTOR_SIZE,

                        req->data, request.len / BDRV_SECTOR_SIZE);

        if (ret < 0) {

            LOG("writing to file failed");

            reply.error = -ret;

            goto error_reply;

        }

        if (request.type & NBD_CMD_FLAG_FUA) {

            ret = blk_co_flush(exp->blk);

            if (ret < 0) {

                LOG("flush failed");

                reply.error = -ret;

                goto error_reply;

            }

        }

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    case NBD_CMD_DISC:

        TRACE("Request type is DISCONNECT");

        errno = 0;

        goto out;

    case NBD_CMD_FLUSH:

        TRACE("Request type is FLUSH");

        ret = blk_co_flush(exp->blk);

        if (ret < 0) {

            LOG("flush failed");

            reply.error = -ret;

        }

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    case NBD_CMD_TRIM:

        TRACE("Request type is TRIM");

        ret = blk_co_discard(exp->blk, (request.from + exp->dev_offset)

                                       / BDRV_SECTOR_SIZE,

                             request.len / BDRV_SECTOR_SIZE);

        if (ret < 0) {

            LOG("discard failed");

            reply.error = -ret;

        }

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    default:

        LOG("invalid request type (%u) received", request.type);

    invalid_request:

        reply.error = EINVAL;

    error_reply:

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    }

    TRACE("Request/Reply complete");

done:

    nbd_request_put(req);

    return;

out:

    nbd_request_put(req);

    client_close(client);

}


bool memory_region_is_unassigned(MemoryRegion *mr)

{

    return mr != &io_mem_ram && mr != &io_mem_rom

        && mr != &io_mem_notdirty && !mr->rom_device

        && mr != &io_mem_watch;

}


static void setup_rt_frame(int sig, struct target_sigaction *ka,

                           target_siginfo_t *info,

			   target_sigset_t *set, CPUState *env)

{

    fprintf(stderr, "setup_rt_frame: not implemented\n");

}


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

{

    unsigned int head;

    /* Grab the next descriptor number they're advertising, and increment

     * the index we've seen. */

    head = vring_avail_ring(vq, idx % vq->vring.num);

    /* If their number is silly, that's a fatal mistake. */

    if (head >= vq->vring.num) {

        error_report("Guest says index %u is available", head);

        exit(1);

    }

    return head;

}


int kvm_has_sync_mmu(void)

{

#ifdef KVM_CAP_SYNC_MMU

    KVMState *s = kvm_state;

    return kvm_check_extension(s, KVM_CAP_SYNC_MMU);

#else

    return 0;

#endif

}


static void ff_wmv2_idct_add_c(uint8_t *dest, int line_size, DCTELEM *block)

{

    ff_wmv2_idct_c(block);

    add_pixels_clamped_c(block, dest, line_size);

}


static void vc1_decode_b_blocks(VC1Context *v)

{

    MpegEncContext *s = &v->s;

    /* select codingmode used for VLC tables selection */

    switch(v->c_ac_table_index){

    case 0:

        v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;

        break;

    case 1:

        v->codingset = CS_HIGH_MOT_INTRA;

        break;

    case 2:

        v->codingset = CS_MID_RATE_INTRA;

        break;

    }

    switch(v->c_ac_table_index){

    case 0:

        v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER;

        break;

    case 1:

        v->codingset2 = CS_HIGH_MOT_INTER;

        break;

    case 2:

        v->codingset2 = CS_MID_RATE_INTER;

        break;

    }

    s->first_slice_line = 1;

    for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {

        for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {

            ff_init_block_index(s);

            ff_update_block_index(s);

            s->dsp.clear_blocks(s->block[0]);

            vc1_decode_b_mb(v);

            if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {

                ff_er_add_slice(s, 0, 0, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END));

                av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y);

                return;

            }

            if(v->s.loop_filter) vc1_loop_filter_iblk(s, s->current_picture.qscale_table[s->mb_x + s->mb_y *s->mb_stride]);

        }

        ff_draw_horiz_band(s, s->mb_y * 16, 16);

        s->first_slice_line = 0;

    }

    ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));

}


static float ppp_pvq_search_c(float *X, int *y, int K, int N)

{

    int i, y_norm = 0;

    float res = 0.0f, xy_norm = 0.0f;

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

        res += FFABS(X[i]);

    res = K/(res + FLT_EPSILON);

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

        y[i] = lrintf(res*X[i]);

        y_norm  += y[i]*y[i];

        xy_norm += y[i]*X[i];

        K -= FFABS(y[i]);

    }

    while (K) {

        int max_idx = 0, max_den = 1, phase = FFSIGN(K);

        float max_num = 0.0f;

        y_norm += 1.0f;

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

            /* If the sum has been overshot and the best place has 0 pulses allocated

             * to it, attempting to decrease it further will actually increase the

             * sum. Prevent this by disregarding any 0 positions when decrementing. */

            const int ca = 1 ^ ((y[i] == 0) & (phase < 0));

            const int y_new = y_norm  + 2*phase*FFABS(y[i]);

            float xy_new = xy_norm + 1*phase*FFABS(X[i]);

            xy_new = xy_new * xy_new;

            if (ca && (max_den*xy_new) > (y_new*max_num)) {

                max_den = y_new;

                max_num = xy_new;

                max_idx = i;

            }

        }

        K -= phase;

        phase *= FFSIGN(X[max_idx]);

        xy_norm += 1*phase*X[max_idx];

        y_norm  += 2*phase*y[max_idx];

        y[max_idx] += phase;

    }

    return (float)y_norm;

}


uint32_t do_arm_semihosting(CPUARMState *env)

{

    ARMCPU *cpu = arm_env_get_cpu(env);

    CPUState *cs = CPU(cpu);

    target_ulong args;

    target_ulong arg0, arg1, arg2, arg3;

    char * s;

    int nr;

    uint32_t ret;

    uint32_t len;

#ifdef CONFIG_USER_ONLY

    TaskState *ts = cs->opaque;

#else

    CPUARMState *ts = env;

#endif

    nr = env->regs[0];

    args = env->regs[1];

    switch (nr) {

    case TARGET_SYS_OPEN:

        GET_ARG(0);

        GET_ARG(1);

        GET_ARG(2);

        s = lock_user_string(arg0);

        if (!s) {

            /* FIXME - should this error code be -TARGET_EFAULT ? */

            return (uint32_t)-1;

        }

        if (arg1 >= 12) {

            unlock_user(s, arg0, 0);

            return (uint32_t)-1;

        }

        if (strcmp(s, ":tt") == 0) {

            int result_fileno = arg1 < 4 ? STDIN_FILENO : STDOUT_FILENO;

            unlock_user(s, arg0, 0);

            return result_fileno;

        }

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", arg0,

                           (int)arg2+1, gdb_open_modeflags[arg1]);

            ret = env->regs[0];

        } else {

            ret = set_swi_errno(ts, open(s, open_modeflags[arg1], 0644));

        }

        unlock_user(s, arg0, 0);

        return ret;

    case TARGET_SYS_CLOSE:

        GET_ARG(0);

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_cb, "close,%x", arg0);

            return env->regs[0];

        } else {

            return set_swi_errno(ts, close(arg0));

        }

    case TARGET_SYS_WRITEC:

        {

          char c;

          if (get_user_u8(c, args))

              /* FIXME - should this error code be -TARGET_EFAULT ? */

              return (uint32_t)-1;

          /* Write to debug console.  stderr is near enough.  */

          if (use_gdb_syscalls()) {

                gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);

                return env->regs[0];

          } else {

                return write(STDERR_FILENO, &c, 1);

          }

        }

    case TARGET_SYS_WRITE0:

        if (!(s = lock_user_string(args)))

            /* FIXME - should this error code be -TARGET_EFAULT ? */

            return (uint32_t)-1;

        len = strlen(s);

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);

            ret = env->regs[0];

        } else {

            ret = write(STDERR_FILENO, s, len);

        }

        unlock_user(s, args, 0);

        return ret;

    case TARGET_SYS_WRITE:

        GET_ARG(0);

        GET_ARG(1);

        GET_ARG(2);

        len = arg2;

        if (use_gdb_syscalls()) {

            arm_semi_syscall_len = len;

            gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", arg0, arg1, len);

            return env->regs[0];

        } else {

            s = lock_user(VERIFY_READ, arg1, len, 1);

            if (!s) {

                /* FIXME - should this error code be -TARGET_EFAULT ? */

                return (uint32_t)-1;

            }

            ret = set_swi_errno(ts, write(arg0, s, len));

            unlock_user(s, arg1, 0);

            if (ret == (uint32_t)-1)

                return -1;

            return len - ret;

        }

    case TARGET_SYS_READ:

        GET_ARG(0);

        GET_ARG(1);

        GET_ARG(2);

        len = arg2;

        if (use_gdb_syscalls()) {

            arm_semi_syscall_len = len;

            gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", arg0, arg1, len);

            return env->regs[0];

        } else {

            s = lock_user(VERIFY_WRITE, arg1, len, 0);

            if (!s) {

                /* FIXME - should this error code be -TARGET_EFAULT ? */

                return (uint32_t)-1;

            }

            do {

                ret = set_swi_errno(ts, read(arg0, s, len));

            } while (ret == -1 && errno == EINTR);

            unlock_user(s, arg1, len);

            if (ret == (uint32_t)-1)

                return -1;

            return len - ret;

        }

    case TARGET_SYS_READC:

       /* XXX: Read from debug console. Not implemented.  */

        return 0;

    case TARGET_SYS_ISTTY:

        GET_ARG(0);

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_cb, "isatty,%x", arg0);

            return env->regs[0];

        } else {

            return isatty(arg0);

        }

    case TARGET_SYS_SEEK:

        GET_ARG(0);

        GET_ARG(1);

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", arg0, arg1);

            return env->regs[0];

        } else {

            ret = set_swi_errno(ts, lseek(arg0, arg1, SEEK_SET));

            if (ret == (uint32_t)-1)

              return -1;

            return 0;

        }

    case TARGET_SYS_FLEN:

        GET_ARG(0);

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x",

                           arg0, env->regs[13]-64);

            return env->regs[0];

        } else {

            struct stat buf;

            ret = set_swi_errno(ts, fstat(arg0, &buf));

            if (ret == (uint32_t)-1)

                return -1;

            return buf.st_size;

        }

    case TARGET_SYS_TMPNAM:

        /* XXX: Not implemented.  */

        return -1;

    case TARGET_SYS_REMOVE:

        GET_ARG(0);

        GET_ARG(1);

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_cb, "unlink,%s", arg0, (int)arg1+1);

            ret = env->regs[0];

        } else {

            s = lock_user_string(arg0);

            if (!s) {

                /* FIXME - should this error code be -TARGET_EFAULT ? */

                return (uint32_t)-1;

            }

            ret =  set_swi_errno(ts, remove(s));

            unlock_user(s, arg0, 0);

        }

        return ret;

    case TARGET_SYS_RENAME:

        GET_ARG(0);

        GET_ARG(1);

        GET_ARG(2);

        GET_ARG(3);

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_cb, "rename,%s,%s",

                           arg0, (int)arg1+1, arg2, (int)arg3+1);

            return env->regs[0];

        } else {

            char *s2;

            s = lock_user_string(arg0);

            s2 = lock_user_string(arg2);

            if (!s || !s2)

                /* FIXME - should this error code be -TARGET_EFAULT ? */

                ret = (uint32_t)-1;

            else

                ret = set_swi_errno(ts, rename(s, s2));

            if (s2)

                unlock_user(s2, arg2, 0);

            if (s)

                unlock_user(s, arg0, 0);

            return ret;

        }

    case TARGET_SYS_CLOCK:

        return clock() / (CLOCKS_PER_SEC / 100);

    case TARGET_SYS_TIME:

        return set_swi_errno(ts, time(NULL));

    case TARGET_SYS_SYSTEM:

        GET_ARG(0);

        GET_ARG(1);

        if (use_gdb_syscalls()) {

            gdb_do_syscall(arm_semi_cb, "system,%s", arg0, (int)arg1+1);

            return env->regs[0];

        } else {

            s = lock_user_string(arg0);

            if (!s) {

                /* FIXME - should this error code be -TARGET_EFAULT ? */

                return (uint32_t)-1;

            }

            ret = set_swi_errno(ts, system(s));

            unlock_user(s, arg0, 0);

            return ret;

        }

    case TARGET_SYS_ERRNO:

#ifdef CONFIG_USER_ONLY

        return ts->swi_errno;

#else

        return syscall_err;

#endif

    case TARGET_SYS_GET_CMDLINE:

        {

            /* Build a command-line from the original argv.

             *

             * The inputs are:

             *     * arg0, pointer to a buffer of at least the size

             *               specified in arg1.

             *     * arg1, size of the buffer pointed to by arg0 in

             *               bytes.

             *

             * The outputs are:

             *     * arg0, pointer to null-terminated string of the

             *               command line.

             *     * arg1, length of the string pointed to by arg0.

             */

            char *output_buffer;

            size_t input_size;

            size_t output_size;

            int status = 0;

            GET_ARG(0);

            GET_ARG(1);

            input_size = arg1;

            /* Compute the size of the output string.  */

#if !defined(CONFIG_USER_ONLY)

            output_size = strlen(ts->boot_info->kernel_filename)

                        + 1  /* Separating space.  */

                        + strlen(ts->boot_info->kernel_cmdline)

                        + 1; /* Terminating null byte.  */

#else

            unsigned int i;

            output_size = ts->info->arg_end - ts->info->arg_start;

            if (!output_size) {

                /* We special-case the "empty command line" case (argc==0).

                   Just provide the terminating 0. */

                output_size = 1;

            }

#endif

            if (output_size > input_size) {

                 /* Not enough space to store command-line arguments.  */

                return -1;

            }

            /* Adjust the command-line length.  */

            if (SET_ARG(1, output_size - 1)) {

                /* Couldn't write back to argument block */

                return -1;

            }

            /* Lock the buffer on the ARM side.  */

            output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);

            if (!output_buffer) {

                return -1;

            }

            /* Copy the command-line arguments.  */

#if !defined(CONFIG_USER_ONLY)

            pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);

            pstrcat(output_buffer, output_size, " ");

            pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);

#else

            if (output_size == 1) {

                /* Empty command-line.  */

                output_buffer[0] = '\0';

                goto out;

            }

            if (copy_from_user(output_buffer, ts->info->arg_start,

                               output_size)) {

                status = -1;

                goto out;

            }

            /* Separate arguments by white spaces.  */

            for (i = 0; i < output_size - 1; i++) {

                if (output_buffer[i] == 0) {

                    output_buffer[i] = ' ';

                }

            }

        out:

#endif

            /* Unlock the buffer on the ARM side.  */

            unlock_user(output_buffer, arg0, output_size);

            return status;

        }

    case TARGET_SYS_HEAPINFO:

        {

            uint32_t *ptr;

            uint32_t limit;

            GET_ARG(0);

#ifdef CONFIG_USER_ONLY

            /* Some C libraries assume the heap immediately follows .bss, so

               allocate it using sbrk.  */

            if (!ts->heap_limit) {

                abi_ulong ret;

                ts->heap_base = do_brk(0);

                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;

                /* Try a big heap, and reduce the size if that fails.  */

                for (;;) {

                    ret = do_brk(limit);

                    if (ret >= limit) {

                        break;

                    }

                    limit = (ts->heap_base >> 1) + (limit >> 1);

                }

                ts->heap_limit = limit;

            }

            ptr = lock_user(VERIFY_WRITE, arg0, 16, 0);

            if (!ptr) {

                /* FIXME - should this error code be -TARGET_EFAULT ? */

                return (uint32_t)-1;

            }

            ptr[0] = tswap32(ts->heap_base);

            ptr[1] = tswap32(ts->heap_limit);

            ptr[2] = tswap32(ts->stack_base);

            ptr[3] = tswap32(0); /* Stack limit.  */

            unlock_user(ptr, arg0, 16);

#else

            limit = ram_size;

            ptr = lock_user(VERIFY_WRITE, arg0, 16, 0);

            if (!ptr) {

                /* FIXME - should this error code be -TARGET_EFAULT ? */

                return (uint32_t)-1;

            }

            /* TODO: Make this use the limit of the loaded application.  */

            ptr[0] = tswap32(limit / 2);

            ptr[1] = tswap32(limit);

            ptr[2] = tswap32(limit); /* Stack base */

            ptr[3] = tswap32(0); /* Stack limit.  */

            unlock_user(ptr, arg0, 16);

#endif

            return 0;

        }

    case TARGET_SYS_EXIT:

        gdb_exit(env, 0);

        exit(0);

    default:

        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);

        cpu_dump_state(cs, stderr, fprintf, 0);

        abort();

    }

}


static int openfile(char *name, int flags, QDict *opts)

{

    Error *local_err = NULL;

    BlockDriverState *bs;

    if (qemuio_blk) {

        error_report("file open already, try 'help close'");

        QDECREF(opts);

        return 1;

    }

    qemuio_blk = blk_new_open(name, NULL, opts, flags, &local_err);

    if (!qemuio_blk) {

        error_reportf_err(local_err, "can't open%s%s: ",

                          name ? " device " : "", name ?: "");

        return 1;

    }

    bs = blk_bs(qemuio_blk);

    if (bdrv_is_encrypted(bs)) {

        char password[256];

        printf("Disk image '%s' is encrypted.\n", name);

        if (qemu_read_password(password, sizeof(password)) < 0) {

            error_report("No password given");

            goto error;

        }

        if (bdrv_set_key(bs, password) < 0) {

            error_report("invalid password");

            goto error;

        }

    }

    return 0;

 error:

    blk_unref(qemuio_blk);

    qemuio_blk = NULL;

    return 1;

}


static void *worker_thread(void *opaque)

{

    ThreadPool *pool = opaque;

    qemu_mutex_lock(&pool->lock);

    pool->pending_threads--;

    do_spawn_thread(pool);

    while (!pool->stopping) {

        ThreadPoolElement *req;

        int ret;

        do {

            pool->idle_threads++;

            qemu_mutex_unlock(&pool->lock);

            ret = qemu_sem_timedwait(&pool->sem, 10000);

            qemu_mutex_lock(&pool->lock);

            pool->idle_threads--;

        } while (ret == -1 && !QTAILQ_EMPTY(&pool->request_list));

        if (ret == -1 || pool->stopping) {

            break;

        }

        req = QTAILQ_FIRST(&pool->request_list);

        QTAILQ_REMOVE(&pool->request_list, req, reqs);

        req->state = THREAD_ACTIVE;

        qemu_mutex_unlock(&pool->lock);

        ret = req->func(req->arg);

        req->ret = ret;

        /* Write ret before state.  */

        smp_wmb();

        req->state = THREAD_DONE;

        qemu_mutex_lock(&pool->lock);

        qemu_bh_schedule(pool->completion_bh);

    }

    pool->cur_threads--;

    qemu_cond_signal(&pool->worker_stopped);

    qemu_mutex_unlock(&pool->lock);

    return NULL;

}


void qemu_aio_wait(void)

{

    int ret;

    if (qemu_bh_poll())

        return;

    do {

        AioHandler *node;

        fd_set rdfds, wrfds;

        int max_fd = -1;

        walking_handlers = 1;

        FD_ZERO(&rdfds);

        FD_ZERO(&wrfds);

        /* fill fd sets */

        LIST_FOREACH(node, &aio_handlers, node) {

            /* If there aren't pending AIO operations, don't invoke callbacks.

             * Otherwise, if there are no AIO requests, qemu_aio_wait() would

             * wait indefinitely.

             */

            if (node->io_flush && node->io_flush(node->opaque) == 0)

                continue;

            if (!node->deleted && node->io_read) {

                FD_SET(node->fd, &rdfds);

                max_fd = MAX(max_fd, node->fd + 1);

            }

            if (!node->deleted && node->io_write) {

                FD_SET(node->fd, &wrfds);

                max_fd = MAX(max_fd, node->fd + 1);

            }

        }

        walking_handlers = 0;

        /* No AIO operations?  Get us out of here */

        if (max_fd == -1)

            break;

        /* wait until next event */

        ret = select(max_fd, &rdfds, &wrfds, NULL, NULL);

        if (ret == -1 && errno == EINTR)

            continue;

        /* if we have any readable fds, dispatch event */

        if (ret > 0) {

            walking_handlers = 1;

            /* we have to walk very carefully in case

             * qemu_aio_set_fd_handler is called while we're walking */

            node = LIST_FIRST(&aio_handlers);

            while (node) {

                AioHandler *tmp;

                if (!node->deleted &&

                    FD_ISSET(node->fd, &rdfds) &&

                    node->io_read) {

                    node->io_read(node->opaque);

                }

                if (!node->deleted &&

                    FD_ISSET(node->fd, &wrfds) &&

                    node->io_write) {

                    node->io_write(node->opaque);

                }

                tmp = node;

                node = LIST_NEXT(node, node);

                if (tmp->deleted) {

                    LIST_REMOVE(tmp, node);

                    qemu_free(tmp);

                }

            }

            walking_handlers = 0;

        }

    } while (ret == 0);

}


void hotplug_handler_post_plug(HotplugHandler *plug_handler,

                               DeviceState *plugged_dev,

                               Error **errp)

{

    HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);

    if (hdc->post_plug) {

        hdc->post_plug(plug_handler, plugged_dev, errp);

    }

}


static void kvm_openpic_realize(DeviceState *dev, Error **errp)

{

    SysBusDevice *d = SYS_BUS_DEVICE(dev);

    KVMOpenPICState *opp = KVM_OPENPIC(dev);

    KVMState *s = kvm_state;

    int kvm_openpic_model;

    struct kvm_create_device cd = {0};

    int ret, i;

    if (!kvm_check_extension(s, KVM_CAP_DEVICE_CTRL)) {

        error_setg(errp, "Kernel is lacking Device Control API");

        return;

    }

    switch (opp->model) {

    case OPENPIC_MODEL_FSL_MPIC_20:

        kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_20;

        break;

    case OPENPIC_MODEL_FSL_MPIC_42:

        kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_42;

        break;

    default:

        error_setg(errp, "Unsupported OpenPIC model %" PRIu32, opp->model);

        return;

    }

    cd.type = kvm_openpic_model;

    ret = kvm_vm_ioctl(s, KVM_CREATE_DEVICE, &cd);

    if (ret < 0) {

        error_setg(errp, "Can't create device %d: %s",

                   cd.type, strerror(errno));

        return;

    }

    opp->fd = cd.fd;

    sysbus_init_mmio(d, &opp->mem);

    qdev_init_gpio_in(dev, kvm_openpic_set_irq, OPENPIC_MAX_IRQ);

    opp->mem_listener.region_add = kvm_openpic_region_add;

    opp->mem_listener.region_del = kvm_openpic_region_del;

    memory_listener_register(&opp->mem_listener, &address_space_memory);

    /* indicate pic capabilities */

    msi_supported = true;

    kvm_kernel_irqchip = true;

    kvm_async_interrupts_allowed = true;

    /* set up irq routing */

    kvm_init_irq_routing(kvm_state);

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

        kvm_irqchip_add_irq_route(kvm_state, i, 0, i);

    }

    kvm_irqfds_allowed = true;

    kvm_msi_via_irqfd_allowed = true;

    kvm_gsi_routing_allowed = true;

    kvm_irqchip_commit_routes(s);

}


static int get_free_io_mem_idx(void)

{

    int i;

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

        if (!io_mem_used[i]) {

            io_mem_used[i] = 1;

            return i;

        }

    return -1;

}


void parse_options(int argc, char **argv, const OptionDef *options,

                   void (* parse_arg_function)(const char*))

{

    const char *opt, *arg;

    int optindex, handleoptions=1;

    const OptionDef *po;

    /* parse options */

    optindex = 1;

    while (optindex < argc) {

        opt = argv[optindex++];

        if (handleoptions && opt[0] == '-' && opt[1] != '\0') {

            int bool_val = 1;

            if (opt[1] == '-' && opt[2] == '\0') {

                handleoptions = 0;

                continue;

            }

            opt++;

            po= find_option(options, opt);

            if (!po->name && opt[0] == 'n' && opt[1] == 'o') {

                /* handle 'no' bool option */

                po = find_option(options, opt + 2);

                if (!(po->name && (po->flags & OPT_BOOL)))

                    goto unknown_opt;

                bool_val = 0;

            }

            if (!po->name)

                po= find_option(options, "default");

            if (!po->name) {

unknown_opt:

                fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt);

                exit(1);

            }

            arg = NULL;

            if (po->flags & HAS_ARG) {

                arg = argv[optindex++];

                if (!arg) {

                    fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt);

                    exit(1);

                }

            }

            if (po->flags & OPT_STRING) {

                char *str;

                str = av_strdup(arg);

                *po->u.str_arg = str;

            } else if (po->flags & OPT_BOOL) {

                *po->u.int_arg = bool_val;

            } else if (po->flags & OPT_INT) {

                *po->u.int_arg = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);

            } else if (po->flags & OPT_INT64) {

                *po->u.int64_arg = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);

            } else if (po->flags & OPT_FLOAT) {

                *po->u.float_arg = parse_number_or_die(opt, arg, OPT_FLOAT, -1.0/0.0, 1.0/0.0);

            } else if (po->flags & OPT_FUNC2) {

                if(po->u.func2_arg(opt, arg)<0)

                    goto unknown_opt;

            } else {

                po->u.func_arg(arg);

            }

            if(po->flags & OPT_EXIT)

                exit(0);

        } else {

            if (parse_arg_function)

                parse_arg_function(opt);

        }

    }

}


static int dma_buf_rw(BMDMAState *bm, int is_write)

{

    IDEState *s = bmdma_active_if(bm);

    struct {

        uint32_t addr;

        uint32_t size;

    } prd;

    int l, len;

    for(;;) {

        l = s->io_buffer_size - s->io_buffer_index;

        if (l <= 0)

            break;

        if (bm->cur_prd_len == 0) {

            /* end of table (with a fail safe of one page) */

            if (bm->cur_prd_last ||

                (bm->cur_addr - bm->addr) >= 4096)

                return 0;

            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);

            bm->cur_addr += 8;

            prd.addr = le32_to_cpu(prd.addr);

            prd.size = le32_to_cpu(prd.size);

            len = prd.size & 0xfffe;

            if (len == 0)

                len = 0x10000;

            bm->cur_prd_len = len;

            bm->cur_prd_addr = prd.addr;

            bm->cur_prd_last = (prd.size & 0x80000000);

        }

        if (l > bm->cur_prd_len)

            l = bm->cur_prd_len;

        if (l > 0) {

            if (is_write) {

                cpu_physical_memory_write(bm->cur_prd_addr,

                                          s->io_buffer + s->io_buffer_index, l);

            } else {

                cpu_physical_memory_read(bm->cur_prd_addr,

                                          s->io_buffer + s->io_buffer_index, l);

            }

            bm->cur_prd_addr += l;

            bm->cur_prd_len -= l;

            s->io_buffer_index += l;

        }

    }

    return 1;

}


static void eepro100_cu_command(EEPRO100State * s, uint8_t val)

{

    eepro100_tx_t tx;

    uint32_t cb_address;

    switch (val) {

    case CU_NOP:

        /* No operation. */

        break;

    case CU_START:

        if (get_cu_state(s) != cu_idle) {

            /* Intel documentation says that CU must be idle for the CU

             * start command. Intel driver for Linux also starts the CU

             * from suspended state. */

            logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle);

            //~ assert(!"wrong CU state");

        }

        set_cu_state(s, cu_active);

        s->cu_offset = s->pointer;

      next_command:

        cb_address = s->cu_base + s->cu_offset;

        cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx));

        uint16_t status = le16_to_cpu(tx.status);

        uint16_t command = le16_to_cpu(tx.command);

        logout

            ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",

             val, status, command, tx.link);

        bool bit_el = ((command & 0x8000) != 0);

        bool bit_s = ((command & 0x4000) != 0);

        bool bit_i = ((command & 0x2000) != 0);

        bool bit_nc = ((command & 0x0010) != 0);

        bool success = true;

        //~ bool bit_sf = ((command & 0x0008) != 0);

        uint16_t cmd = command & 0x0007;

        s->cu_offset = le32_to_cpu(tx.link);

        switch (cmd) {

        case CmdNOp:

            /* Do nothing. */

            break;

        case CmdIASetup:

            cpu_physical_memory_read(cb_address + 8, &s->macaddr[0], 6);

            TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)));

            break;

        case CmdConfigure:

            cpu_physical_memory_read(cb_address + 8, &s->configuration[0],

                                     sizeof(s->configuration));

            TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)));

            break;

        case CmdMulticastList:

            //~ missing("multicast list");

            break;

        case CmdTx:

            (void)0;

            uint32_t tbd_array = le32_to_cpu(tx.tx_desc_addr);

            uint16_t tcb_bytes = (le16_to_cpu(tx.tcb_bytes) & 0x3fff);

            TRACE(RXTX, logout

                ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",

                 tbd_array, tcb_bytes, tx.tbd_count));

            if (bit_nc) {

                missing("CmdTx: NC = 0");

                success = false;

                break;

            }

            //~ assert(!bit_sf);

            if (tcb_bytes > 2600) {

                logout("TCB byte count too large, using 2600\n");

                tcb_bytes = 2600;

            }

            /* Next assertion fails for local configuration. */

            //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));

            if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {

                logout

                    ("illegal values of TBD array address and TCB byte count!\n");

            }

            // sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes

            uint8_t buf[2600];

            uint16_t size = 0;

            uint32_t tbd_address = cb_address + 0x10;

            assert(tcb_bytes <= sizeof(buf));

            while (size < tcb_bytes) {

                uint32_t tx_buffer_address = ldl_phys(tbd_address);

                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);

                //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);

                tbd_address += 8;

                TRACE(RXTX, logout

                    ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",

                     tx_buffer_address, tx_buffer_size));

                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);

                cpu_physical_memory_read(tx_buffer_address, &buf[size],

                                         tx_buffer_size);

                size += tx_buffer_size;

            }

            if (tbd_array == 0xffffffff) {

                /* Simplified mode. Was already handled by code above. */

            } else {

                /* Flexible mode. */

                uint8_t tbd_count = 0;

                if (device_supports_eTxCB(s) && !(s->configuration[6] & BIT(4))) {

                    /* Extended Flexible TCB. */

                    for (; tbd_count < 2; tbd_count++) {

                        uint32_t tx_buffer_address = ldl_phys(tbd_address);

                        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);

                        uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);

                        tbd_address += 8;

                        TRACE(RXTX, logout

                            ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",

                             tx_buffer_address, tx_buffer_size));

                        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);

                        cpu_physical_memory_read(tx_buffer_address, &buf[size],

                                                 tx_buffer_size);

                        size += tx_buffer_size;

                        if (tx_buffer_el & 1) {

                            break;

                        }

                    }

                }

                tbd_address = tbd_array;

                for (; tbd_count < tx.tbd_count; tbd_count++) {

                    uint32_t tx_buffer_address = ldl_phys(tbd_address);

                    uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);

                    uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);

                    tbd_address += 8;

                    TRACE(RXTX, logout

                        ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",

                         tx_buffer_address, tx_buffer_size));

                    tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);

                    cpu_physical_memory_read(tx_buffer_address, &buf[size],

                                             tx_buffer_size);

                    size += tx_buffer_size;

                    if (tx_buffer_el & 1) {

                        break;

                    }

                }

            }

            TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));

            qemu_send_packet(s->vc, buf, size);

            s->statistics.tx_good_frames++;

            /* Transmit with bad status would raise an CX/TNO interrupt.

             * (82557 only). Emulation never has bad status. */

            //~ eepro100_cx_interrupt(s);

            break;

        case CmdTDR:

            TRACE(OTHER, logout("load microcode\n"));

            /* Starting with offset 8, the command contains

             * 64 dwords microcode which we just ignore here. */

            break;

        default:

            missing("undefined command");

            success = false;

            break;

        }

        /* Write new status. */

        stw_phys(cb_address, status | 0x8000 | (success ? 0x2000 : 0));

        if (bit_i) {

            /* CU completed action. */

            eepro100_cx_interrupt(s);

        }

        if (bit_el) {

            /* CU becomes idle. Terminate command loop. */

            set_cu_state(s, cu_idle);

            eepro100_cna_interrupt(s);

        } else if (bit_s) {

            /* CU becomes suspended. */

            set_cu_state(s, cu_suspended);

            eepro100_cna_interrupt(s);

        } else {

            /* More entries in list. */

            TRACE(OTHER, logout("CU list with at least one more entry\n"));

            goto next_command;

        }

        TRACE(OTHER, logout("CU list empty\n"));

        /* List is empty. Now CU is idle or suspended. */

        break;

    case CU_RESUME:

        if (get_cu_state(s) != cu_suspended) {

            logout("bad CU resume from CU state %u\n", get_cu_state(s));

            /* Workaround for bad Linux eepro100 driver which resumes

             * from idle state. */

            //~ missing("cu resume");

            set_cu_state(s, cu_suspended);

        }

        if (get_cu_state(s) == cu_suspended) {

            TRACE(OTHER, logout("CU resuming\n"));

            set_cu_state(s, cu_active);

            goto next_command;

        }

        break;

    case CU_STATSADDR:

        /* Load dump counters address. */

        s->statsaddr = s->pointer;

        TRACE(OTHER, logout("val=0x%02x (status address)\n", val));

        break;

    case CU_SHOWSTATS:

        /* Dump statistical counters. */

        TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val));

        dump_statistics(s);

        break;

    case CU_CMD_BASE:

        /* Load CU base. */

        TRACE(OTHER, logout("val=0x%02x (CU base address)\n", val));

        s->cu_base = s->pointer;

        break;

    case CU_DUMPSTATS:

        /* Dump and reset statistical counters. */

        TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val));

        dump_statistics(s);

        memset(&s->statistics, 0, sizeof(s->statistics));

        break;

    case CU_SRESUME:

        /* CU static resume. */

        missing("CU static resume");

        break;

    default:

        missing("Undefined CU command");

    }

}