static void init_virtio_dev(TestServer *s, uint32_t features_mask) { uint32_t features; int i; s->bus = qpci_init_pc(global_qtest, NULL); g_assert_nonnull(s->bus); s->dev = qvirtio_pci_device_find(s->bus, VIRTIO_ID_NET); g_assert_nonnull(s->dev); qvirtio_pci_device_enable(s->dev); qvirtio_reset(&s->dev->vdev); qvirtio_set_acknowledge(&s->dev->vdev); qvirtio_set_driver(&s->dev->vdev); s->alloc = pc_alloc_init(global_qtest); for (i = 0; i < s->queues * 2; i++) { s->vq[i] = qvirtqueue_setup(&s->dev->vdev, s->alloc, i); } features = qvirtio_get_features(&s->dev->vdev); features = features & features_mask; qvirtio_set_features(&s->dev->vdev, features); qvirtio_set_driver_ok(&s->dev->vdev); }
static QVirtioPCIDevice *virtio_net_pci_init(QPCIBus *bus, int slot) { QVirtioPCIDevice *dev; dev = qvirtio_pci_device_find(bus, QVIRTIO_NET_DEVICE_ID); g_assert(dev != NULL); g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_NET_DEVICE_ID); qvirtio_pci_device_enable(dev); qvirtio_reset(&qvirtio_pci, &dev->vdev); qvirtio_set_acknowledge(&qvirtio_pci, &dev->vdev); qvirtio_set_driver(&qvirtio_pci, &dev->vdev); return dev; }
static QVirtIO9P *qvirtio_9p_pci_start(void) { QVirtIO9P *v9p = qvirtio_9p_start("virtio-9p-pci"); QVirtioPCIDevice *dev = qvirtio_pci_device_find(v9p->qs->pcibus, VIRTIO_ID_9P); g_assert_nonnull(dev); g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_9P); v9p->dev = (QVirtioDevice *) dev; qvirtio_pci_device_enable(dev); qvirtio_reset(v9p->dev); qvirtio_set_acknowledge(v9p->dev); qvirtio_set_driver(v9p->dev); v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0); return v9p; }
static QVirtIO9P *qvirtio_9p_pci_init(QOSState *qs) { QVirtIO9P *v9p; QVirtioPCIDevice *dev; v9p = g_new0(QVirtIO9P, 1); v9p->qs = qs; dev = qvirtio_pci_device_find(v9p->qs->pcibus, VIRTIO_ID_9P); g_assert_nonnull(dev); g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_9P); v9p->dev = (QVirtioDevice *) dev; qvirtio_pci_device_enable(dev); qvirtio_reset(v9p->dev); qvirtio_set_acknowledge(v9p->dev); qvirtio_set_driver(v9p->dev); v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0); return v9p; }
static void init_virtio_dev(TestServer *s) { QVirtioPCIDevice *dev; uint32_t features; s->bus = qpci_init_pc(NULL); g_assert_nonnull(s->bus); dev = qvirtio_pci_device_find(s->bus, VIRTIO_ID_NET); g_assert_nonnull(dev); qvirtio_pci_device_enable(dev); qvirtio_reset(&dev->vdev); qvirtio_set_acknowledge(&dev->vdev); qvirtio_set_driver(&dev->vdev); features = qvirtio_get_features(&dev->vdev); features = features & VIRTIO_NET_F_MAC; qvirtio_set_features(&dev->vdev, features); qvirtio_set_driver_ok(&dev->vdev); qvirtio_pci_device_free(dev); }
static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb, const uint8_t *data_in, size_t data_in_len, uint8_t *data_out, size_t data_out_len, struct virtio_scsi_cmd_resp *resp_out) { QVirtQueue *vq; struct virtio_scsi_cmd_req req = { { 0 } }; struct virtio_scsi_cmd_resp resp = { .response = 0xff, .status = 0xff }; uint64_t req_addr, resp_addr, data_in_addr = 0, data_out_addr = 0; uint8_t response; uint32_t free_head; vq = vs->vq[2]; req.lun[0] = 1; /* Select LUN */ req.lun[1] = 1; /* Select target 1 */ memcpy(req.cdb, cdb, VIRTIO_SCSI_CDB_SIZE); /* XXX: Fix endian if any multi-byte field in req/resp is used */ /* Add request header */ req_addr = qvirtio_scsi_alloc(vs, sizeof(req), &req); free_head = qvirtqueue_add(vq, req_addr, sizeof(req), false, true); if (data_out_len) { data_out_addr = qvirtio_scsi_alloc(vs, data_out_len, data_out); qvirtqueue_add(vq, data_out_addr, data_out_len, false, true); } /* Add response header */ resp_addr = qvirtio_scsi_alloc(vs, sizeof(resp), &resp); qvirtqueue_add(vq, resp_addr, sizeof(resp), true, !!data_in_len); if (data_in_len) { data_in_addr = qvirtio_scsi_alloc(vs, data_in_len, data_in); qvirtqueue_add(vq, data_in_addr, data_in_len, true, false); } qvirtqueue_kick(vs->dev, vq, free_head); qvirtio_wait_queue_isr(vs->dev, vq, QVIRTIO_SCSI_TIMEOUT_US); response = readb(resp_addr + offsetof(struct virtio_scsi_cmd_resp, response)); if (resp_out) { memread(resp_addr, resp_out, sizeof(*resp_out)); } guest_free(vs->qs->alloc, req_addr); guest_free(vs->qs->alloc, resp_addr); guest_free(vs->qs->alloc, data_in_addr); guest_free(vs->qs->alloc, data_out_addr); return response; } static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot) { const uint8_t test_unit_ready_cdb[VIRTIO_SCSI_CDB_SIZE] = {}; QVirtIOSCSI *vs; QVirtioPCIDevice *dev; struct virtio_scsi_cmd_resp resp; int i; vs = g_new0(QVirtIOSCSI, 1); vs->qs = qvirtio_scsi_start("-drive file=blkdebug::null-co://," "if=none,id=dr1,format=raw,file.align=4k " "-device scsi-hd,drive=dr1,lun=0,scsi-id=1"); dev = qvirtio_pci_device_find(vs->qs->pcibus, VIRTIO_ID_SCSI); vs->dev = (QVirtioDevice *)dev; g_assert(dev != NULL); g_assert_cmphex(vs->dev->device_type, ==, VIRTIO_ID_SCSI); qvirtio_pci_device_enable(dev); qvirtio_reset(vs->dev); qvirtio_set_acknowledge(vs->dev); qvirtio_set_driver(vs->dev); vs->num_queues = qvirtio_config_readl(vs->dev, 0); g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES); for (i = 0; i < vs->num_queues + 2; i++) { vs->vq[i] = qvirtqueue_setup(vs->dev, vs->qs->alloc, i); } /* Clear the POWER ON OCCURRED unit attention */ g_assert_cmpint(virtio_scsi_do_command(vs, test_unit_ready_cdb, NULL, 0, NULL, 0, &resp), ==, 0); g_assert_cmpint(resp.status, ==, CHECK_CONDITION); g_assert_cmpint(resp.sense[0], ==, 0x70); /* Fixed format sense buffer */ g_assert_cmpint(resp.sense[2], ==, UNIT_ATTENTION); g_assert_cmpint(resp.sense[12], ==, 0x29); /* POWER ON */ g_assert_cmpint(resp.sense[13], ==, 0x00); return vs; } /* Tests only initialization so far. TODO: Replace with functional tests */ static void pci_nop(void) { QOSState *qs; qs = qvirtio_scsi_start(NULL); qvirtio_scsi_stop(qs); }