void *virtqueue_pop(VirtQueue *vq, size_t sz)

{

    unsigned int i, head, max;

    hwaddr desc_pa = vq->vring.desc;

    VirtIODevice *vdev = vq->vdev;

    VirtQueueElement *elem;

    unsigned out_num, in_num;

    hwaddr addr[VIRTQUEUE_MAX_SIZE];

    struct iovec iov[VIRTQUEUE_MAX_SIZE];

    VRingDesc desc;



    if (!virtqueue_num_heads(vq, vq->last_avail_idx)) {

        return NULL;

    }



    /* When we start there are none of either input nor output. */

    out_num = in_num = 0;



    max = vq->vring.num;



    i = head = virtqueue_get_head(vq, vq->last_avail_idx++);

    if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {

        vring_set_avail_event(vq, vq->last_avail_idx);

    }



    vring_desc_read(vdev, &desc, desc_pa, i);

    if (desc.flags & VRING_DESC_F_INDIRECT) {

        if (desc.len % sizeof(VRingDesc)) {

            error_report("Invalid size for indirect buffer table");

            exit(1);

        }



        /* loop over the indirect descriptor table */

        max = desc.len / sizeof(VRingDesc);

        desc_pa = desc.addr;

        i = 0;

        vring_desc_read(vdev, &desc, desc_pa, i);

    }



    /* Collect all the descriptors */

    do {

        if (desc.flags & VRING_DESC_F_WRITE) {

            virtqueue_map_desc(&in_num, addr + out_num, iov + out_num,

                               VIRTQUEUE_MAX_SIZE - out_num, true, desc.addr, desc.len);

        } else {

            if (in_num) {

                error_report("Incorrect order for descriptors");

                exit(1);

            }

            virtqueue_map_desc(&out_num, addr, iov,

                               VIRTQUEUE_MAX_SIZE, false, desc.addr, desc.len);

        }



        /* If we've got too many, that implies a descriptor loop. */

        if ((in_num + out_num) > max) {

            error_report("Looped descriptor");

            exit(1);

        }

    } while ((i = virtqueue_read_next_desc(vdev, &desc, desc_pa, max)) != max);



    /* Now copy what we have collected and mapped */

    elem = virtqueue_alloc_element(sz, out_num, in_num);

    elem->index = head;

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

        elem->out_addr[i] = addr[i];

        elem->out_sg[i] = iov[i];

    }

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

        elem->in_addr[i] = addr[out_num + i];

        elem->in_sg[i] = iov[out_num + i];

    }



    vq->inuse++;



    trace_virtqueue_pop(vq, elem, elem->in_num, elem->out_num);

    return elem;

}

void *virtqueue_pop(VirtQueue *vq, size_t sz)

{

    unsigned int i, head, max;

    hwaddr desc_pa = vq->vring.desc;

    VirtIODevice *vdev = vq->vdev;

    VirtQueueElement *elem;

    unsigned out_num, in_num;

    hwaddr addr[VIRTQUEUE_MAX_SIZE];

    struct iovec iov[VIRTQUEUE_MAX_SIZE];

    VRingDesc desc;



    if (!virtqueue_num_heads(vq, vq->last_avail_idx)) {

        return NULL;

    }



    

    out_num = in_num = 0;



    max = vq->vring.num;



    i = head = virtqueue_get_head(vq, vq->last_avail_idx++);

    if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {

        vring_set_avail_event(vq, vq->last_avail_idx);

    }



    vring_desc_read(vdev, &desc, desc_pa, i);

    if (desc.flags & VRING_DESC_F_INDIRECT) {

        if (desc.len % sizeof(VRingDesc)) {

            error_report("Invalid size for indirect buffer table");

            exit(1);

        }



        

        max = desc.len / sizeof(VRingDesc);

        desc_pa = desc.addr;

        i = 0;

        vring_desc_read(vdev, &desc, desc_pa, i);

    }



    

    do {

        if (desc.flags & VRING_DESC_F_WRITE) {

            virtqueue_map_desc(&in_num, addr + out_num, iov + out_num,

                               VIRTQUEUE_MAX_SIZE - out_num, true, desc.addr, desc.len);

        } else {

            if (in_num) {

                error_report("Incorrect order for descriptors");

                exit(1);

            }

            virtqueue_map_desc(&out_num, addr, iov,

                               VIRTQUEUE_MAX_SIZE, false, desc.addr, desc.len);

        }



        

        if ((in_num + out_num) > max) {

            error_report("Looped descriptor");

            exit(1);

        }

    } while ((i = virtqueue_read_next_desc(vdev, &desc, desc_pa, max)) != max);



    

    elem = virtqueue_alloc_element(sz, out_num, in_num);

    elem->index = head;

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

        elem->out_addr[i] = addr[i];

        elem->out_sg[i] = iov[i];

    }

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

        elem->in_addr[i] = addr[out_num + i];

        elem->in_sg[i] = iov[out_num + i];

    }



    vq->inuse++;



    trace_virtqueue_pop(vq, elem, elem->in_num, elem->out_num);

    return elem;

}

void *FUNC_0(VirtQueue *VAR_0, size_t VAR_1)

{

    unsigned int VAR_2, VAR_3, VAR_4;

    hwaddr desc_pa = VAR_0->vring.desc;

    VirtIODevice *vdev = VAR_0->vdev;

    VirtQueueElement *elem;

    unsigned VAR_5, VAR_6;

    hwaddr addr[VIRTQUEUE_MAX_SIZE];

    struct iovec VAR_7[VIRTQUEUE_MAX_SIZE];

    VRingDesc desc;



    if (!virtqueue_num_heads(VAR_0, VAR_0->last_avail_idx)) {

        return NULL;

    }



    

    VAR_5 = VAR_6 = 0;



    VAR_4 = VAR_0->vring.num;



    VAR_2 = VAR_3 = virtqueue_get_head(VAR_0, VAR_0->last_avail_idx++);

    if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {

        vring_set_avail_event(VAR_0, VAR_0->last_avail_idx);

    }



    vring_desc_read(vdev, &desc, desc_pa, VAR_2);

    if (desc.flags & VRING_DESC_F_INDIRECT) {

        if (desc.len % sizeof(VRingDesc)) {

            error_report("Invalid size for indirect buffer table");

            exit(1);

        }



        

        VAR_4 = desc.len / sizeof(VRingDesc);

        desc_pa = desc.addr;

        VAR_2 = 0;

        vring_desc_read(vdev, &desc, desc_pa, VAR_2);

    }



    

    do {

        if (desc.flags & VRING_DESC_F_WRITE) {

            virtqueue_map_desc(&VAR_6, addr + VAR_5, VAR_7 + VAR_5,

                               VIRTQUEUE_MAX_SIZE - VAR_5, true, desc.addr, desc.len);

        } else {

            if (VAR_6) {

                error_report("Incorrect order for descriptors");

                exit(1);

            }

            virtqueue_map_desc(&VAR_5, addr, VAR_7,

                               VIRTQUEUE_MAX_SIZE, false, desc.addr, desc.len);

        }



        

        if ((VAR_6 + VAR_5) > VAR_4) {

            error_report("Looped descriptor");

            exit(1);

        }

    } while ((VAR_2 = virtqueue_read_next_desc(vdev, &desc, desc_pa, VAR_4)) != VAR_4);



    

    elem = virtqueue_alloc_element(VAR_1, VAR_5, VAR_6);

    elem->index = VAR_3;

    for (VAR_2 = 0; VAR_2 < VAR_5; VAR_2++) {

        elem->out_addr[VAR_2] = addr[VAR_2];

        elem->out_sg[VAR_2] = VAR_7[VAR_2];

    }

    for (VAR_2 = 0; VAR_2 < VAR_6; VAR_2++) {

        elem->in_addr[VAR_2] = addr[VAR_5 + VAR_2];

        elem->in_sg[VAR_2] = VAR_7[VAR_5 + VAR_2];

    }



    VAR_0->inuse++;



    trace_virtqueue_pop(VAR_0, elem, elem->VAR_6, elem->VAR_5);

    return elem;

}

void *FUNC_0(VirtQueue *VAR_0, size_t VAR_1)
{ unsigned int VAR_2, VAR_3, VAR_4; hwaddr desc_pa = VAR_0->vring.desc; VirtIODevice *vdev = VAR_0->vdev; VirtQueueElement *elem; unsigned VAR_5, VAR_6; hwaddr addr[VIRTQUEUE_MAX_SIZE]; struct iovec VAR_7[VIRTQUEUE_MAX_SIZE]; VRingDesc desc; if (!virtqueue_num_heads(VAR_0, VAR_0->last_avail_idx)) { return NULL; } VAR_5 = VAR_6 = 0; VAR_4 = VAR_0->vring.num; VAR_2 = VAR_3 = virtqueue_get_head(VAR_0, VAR_0->last_avail_idx++); if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_set_avail_event(VAR_0, VAR_0->last_avail_idx); } vring_desc_read(vdev, &desc, desc_pa, VAR_2); if (desc.flags & VRING_DESC_F_INDIRECT) { if (desc.len % sizeof(VRingDesc)) { error_report("Invalid size for indirect buffer table"); exit(1); } VAR_4 = desc.len / sizeof(VRingDesc); desc_pa = desc.addr; VAR_2 = 0; vring_desc_read(vdev, &desc, desc_pa, VAR_2); } do { if (desc.flags & VRING_DESC_F_WRITE) { virtqueue_map_desc(&VAR_6, addr + VAR_5, VAR_7 + VAR_5,
VIRTQUEUE_MAX_SIZE - VAR_5, true, desc.addr, desc.len); } else { if (VAR_6) { error_report("Incorrect order for descriptors"); exit(1); } virtqueue_map_desc(&VAR_5, addr, VAR_7,
VIRTQUEUE_MAX_SIZE, false, desc.addr, desc.len); } if ((VAR_6 + VAR_5) > VAR_4) { error_report("Looped descriptor"); exit(1); } } while ((VAR_2 = virtqueue_read_next_desc(vdev, &desc, desc_pa, VAR_4)) != VAR_4); elem = virtqueue_alloc_element(VAR_1, VAR_5, VAR_6); elem->index = VAR_3; for (VAR_2 = 0; VAR_2 < VAR_5; VAR_2++) { elem->out_addr[VAR_2] = addr[VAR_2]; elem->out_sg[VAR_2] = VAR_7[VAR_2]; } for (VAR_2 = 0; VAR_2 < VAR_6; VAR_2++) { elem->in_addr[VAR_2] = addr[VAR_5 + VAR_2]; elem->in_sg[VAR_2] = VAR_7[VAR_5 + VAR_2]; } VAR_0->inuse++; trace_virtqueue_pop(VAR_0, elem, elem->VAR_6, elem->VAR_5); return elem; }