static void pci_indirect(void)

{

    QVirtioPCIDevice *dev;

    QPCIBus *bus;

    QVirtQueuePCI *vqpci;

    QGuestAllocator *alloc;

    QVirtioBlkReq req;

    QVRingIndirectDesc *indirect;

    void *addr;

    uint64_t req_addr;

    uint64_t capacity;

    uint32_t features;

    uint32_t free_head;

    uint8_t status;

    char *data;



    bus = test_start();



    dev = virtio_blk_init(bus);



    /* MSI-X is not enabled */

    addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX;



    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr);

    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);



    features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);

    g_assert_cmphex(features & QVIRTIO_F_RING_INDIRECT_DESC, !=, 0);

    features = features & ~(QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_EVENT_IDX |

                                                            QVIRTIO_BLK_F_SCSI);

    qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);



    alloc = pc_alloc_init();

    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,

                                                                    alloc, 0);

    qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);



    /* Write request */

    req.type = QVIRTIO_BLK_T_OUT;

    req.ioprio = 1;

    req.sector = 0;

    req.data = g_malloc0(512);

    strcpy(req.data, "TEST");



    req_addr = virtio_blk_request(alloc, &req, 512);



    g_free(req.data);



    indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);

    qvring_indirect_desc_add(indirect, req_addr, 528, false);

    qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);

    free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);

    qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);



    g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,

                                                        QVIRTIO_BLK_TIMEOUT));

    status = readb(req_addr + 528);

    g_assert_cmpint(status, ==, 0);



    g_free(indirect);

    guest_free(alloc, req_addr);



    /* Read request */

    req.type = QVIRTIO_BLK_T_IN;

    req.ioprio = 1;

    req.sector = 0;

    req.data = g_malloc0(512);

    strcpy(req.data, "TEST");



    req_addr = virtio_blk_request(alloc, &req, 512);



    g_free(req.data);



    indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);

    qvring_indirect_desc_add(indirect, req_addr, 16, false);

    qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);

    free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);

    qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);



    g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,

                                                        QVIRTIO_BLK_TIMEOUT));

    status = readb(req_addr + 528);

    g_assert_cmpint(status, ==, 0);



    data = g_malloc0(512);

    memread(req_addr + 16, data, 512);

    g_assert_cmpstr(data, ==, "TEST");

    g_free(data);



    g_free(indirect);

    guest_free(alloc, req_addr);



    /* End test */

    guest_free(alloc, vqpci->vq.desc);

    qvirtio_pci_device_disable(dev);

    g_free(dev);

    test_end();

}

static void pci_indirect(void)

{

    QVirtioPCIDevice *dev;

    QPCIBus *bus;

    QVirtQueuePCI *vqpci;

    QGuestAllocator *alloc;

    QVirtioBlkReq req;

    QVRingIndirectDesc *indirect;

    void *addr;

    uint64_t req_addr;

    uint64_t capacity;

    uint32_t features;

    uint32_t free_head;

    uint8_t status;

    char *data;



    bus = test_start();



    dev = virtio_blk_init(bus);



    

    addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX;



    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, addr);

    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);



    features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);

    g_assert_cmphex(features & QVIRTIO_F_RING_INDIRECT_DESC, !=, 0);

    features = features & ~(QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_EVENT_IDX |

                                                            QVIRTIO_BLK_F_SCSI);

    qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);



    alloc = pc_alloc_init();

    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,

                                                                    alloc, 0);

    qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);



    

    req.type = QVIRTIO_BLK_T_OUT;

    req.ioprio = 1;

    req.sector = 0;

    req.data = g_malloc0(512);

    strcpy(req.data, "TEST");



    req_addr = virtio_blk_request(alloc, &req, 512);



    g_free(req.data);



    indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);

    qvring_indirect_desc_add(indirect, req_addr, 528, false);

    qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);

    free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);

    qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);



    g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,

                                                        QVIRTIO_BLK_TIMEOUT));

    status = readb(req_addr + 528);

    g_assert_cmpint(status, ==, 0);



    g_free(indirect);

    guest_free(alloc, req_addr);



    

    req.type = QVIRTIO_BLK_T_IN;

    req.ioprio = 1;

    req.sector = 0;

    req.data = g_malloc0(512);

    strcpy(req.data, "TEST");



    req_addr = virtio_blk_request(alloc, &req, 512);



    g_free(req.data);



    indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);

    qvring_indirect_desc_add(indirect, req_addr, 16, false);

    qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);

    free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);

    qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);



    g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,

                                                        QVIRTIO_BLK_TIMEOUT));

    status = readb(req_addr + 528);

    g_assert_cmpint(status, ==, 0);



    data = g_malloc0(512);

    memread(req_addr + 16, data, 512);

    g_assert_cmpstr(data, ==, "TEST");

    g_free(data);



    g_free(indirect);

    guest_free(alloc, req_addr);



    

    guest_free(alloc, vqpci->vq.desc);

    qvirtio_pci_device_disable(dev);

    g_free(dev);

    test_end();

}

    g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));                                                         QVIRTIO_BLK_TIMEOUT));                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));     g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,                                                         QVIRTIO_BLK_TIMEOUT));
static void FUNC_0(void)

{

    QVirtioPCIDevice *dev;

    QPCIBus *bus;

    QVirtQueuePCI *vqpci;

    QGuestAllocator *alloc;

    QVirtioBlkReq req;

    QVRingIndirectDesc *indirect;

    void *VAR_0;

    uint64_t req_addr;

    uint64_t capacity;

    uint32_t features;

    uint32_t free_head;

    uint8_t status;

    char *VAR_1;



    bus = test_start();



    dev = virtio_blk_init(bus);



    

    VAR_0 = dev->VAR_0 + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX;



    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, VAR_0);

    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);



    features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);

    g_assert_cmphex(features & QVIRTIO_F_RING_INDIRECT_DESC, !=, 0);

    features = features & ~(QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_EVENT_IDX |

                                                            QVIRTIO_BLK_F_SCSI);

    qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);



    alloc = pc_alloc_init();

    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,

                                                                    alloc, 0);

    qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);



    

    req.type = QVIRTIO_BLK_T_OUT;

    req.ioprio = 1;

    req.sector = 0;

    req.VAR_1 = g_malloc0(512);

    strcpy(req.VAR_1, "TEST");



    req_addr = virtio_blk_request(alloc, &req, 512);



    g_free(req.VAR_1);



    indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);

    qvring_indirect_desc_add(indirect, req_addr, 528, false);

    qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);

    free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);

    qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);



    g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,

                                                        QVIRTIO_BLK_TIMEOUT));

    status = readb(req_addr + 528);

    g_assert_cmpint(status, ==, 0);



    g_free(indirect);

    guest_free(alloc, req_addr);



    

    req.type = QVIRTIO_BLK_T_IN;

    req.ioprio = 1;

    req.sector = 0;

    req.VAR_1 = g_malloc0(512);

    strcpy(req.VAR_1, "TEST");



    req_addr = virtio_blk_request(alloc, &req, 512);



    g_free(req.VAR_1);



    indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);

    qvring_indirect_desc_add(indirect, req_addr, 16, false);

    qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);

    free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);

    qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);



    g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,

                                                        QVIRTIO_BLK_TIMEOUT));

    status = readb(req_addr + 528);

    g_assert_cmpint(status, ==, 0);



    VAR_1 = g_malloc0(512);

    memread(req_addr + 16, VAR_1, 512);

    g_assert_cmpstr(VAR_1, ==, "TEST");

    g_free(VAR_1);



    g_free(indirect);

    guest_free(alloc, req_addr);



    

    guest_free(alloc, vqpci->vq.desc);

    qvirtio_pci_device_disable(dev);

    g_free(dev);

    test_end();

}

static void FUNC_0(void)
{ QVirtioPCIDevice *dev; QPCIBus *bus; QVirtQueuePCI *vqpci; QGuestAllocator *alloc; QVirtioBlkReq req; QVRingIndirectDesc *indirect; void *VAR_0; uint64_t req_addr; uint64_t capacity; uint32_t features; uint32_t free_head; uint8_t status; char *VAR_1; bus = test_start(); dev = virtio_blk_init(bus); VAR_0 = dev->VAR_0 + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX; capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, VAR_0); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); features = qvirtio_get_features(&qvirtio_pci, &dev->vdev); g_assert_cmphex(features & QVIRTIO_F_RING_INDIRECT_DESC, !=, 0); features = features & ~(QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_EVENT_IDX |
QVIRTIO_BLK_F_SCSI); qvirtio_set_features(&qvirtio_pci, &dev->vdev, features); alloc = pc_alloc_init(); vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
alloc, 0); qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev); req.type = QVIRTIO_BLK_T_OUT; req.ioprio = 1; req.sector = 0; req.VAR_1 = g_malloc0(512); strcpy(req.VAR_1, "TEST"); req_addr = virtio_blk_request(alloc, &req, 512); g_free(req.VAR_1); indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2); qvring_indirect_desc_add(indirect, req_addr, 528, false); qvring_indirect_desc_add(indirect, req_addr + 528, 1, true); free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect); qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
QVIRTIO_BLK_TIMEOUT)); status = readb(req_addr + 528); g_assert_cmpint(status, ==, 0); g_free(indirect); guest_free(alloc, req_addr); req.type = QVIRTIO_BLK_T_IN; req.ioprio = 1; req.sector = 0; req.VAR_1 = g_malloc0(512); strcpy(req.VAR_1, "TEST"); req_addr = virtio_blk_request(alloc, &req, 512); g_free(req.VAR_1); indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2); qvring_indirect_desc_add(indirect, req_addr, 16, false); qvring_indirect_desc_add(indirect, req_addr + 16, 513, true); free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect); qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head); g_assert(qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
QVIRTIO_BLK_TIMEOUT)); status = readb(req_addr + 528); g_assert_cmpint(status, ==, 0); VAR_1 = g_malloc0(512); memread(req_addr + 16, VAR_1, 512); g_assert_cmpstr(VAR_1, ==, "TEST"); g_free(VAR_1); g_free(indirect); guest_free(alloc, req_addr); guest_free(alloc, vqpci->vq.desc); qvirtio_pci_device_disable(dev); g_free(dev); test_end(); }