NTSTATUS virtio_device_initialize(VirtIODevice *vdev, const VirtIOSystemOps *pSystemOps, PVOID DeviceContext, bool msix_used) { NTSTATUS status; RtlZeroMemory(vdev, sizeof(VirtIODevice)); vdev->DeviceContext = DeviceContext; vdev->system = pSystemOps; vdev->msix_used = msix_used; vdev->info = vdev->inline_info; vdev->maxQueues = ARRAYSIZE(vdev->inline_info); status = vio_modern_initialize(vdev); if (status == STATUS_DEVICE_NOT_CONNECTED) { /* fall back to legacy virtio device */ status = vio_legacy_initialize(vdev); } if (NT_SUCCESS(status)) { /* Always start by resetting the device */ virtio_device_reset(vdev); /* Acknowledge that we've seen the device. */ virtio_add_status(vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE); /* If we are here, we must have found a driver for the device */ virtio_add_status(vdev, VIRTIO_CONFIG_S_DRIVER); } return status; }
int virtio_device_restore(struct virtio_device *dev) { struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); int ret; /* We always start by resetting the device, in case a previous * driver messed it up. */ dev->config->reset(dev); /* Acknowledge that we've seen the device. */ virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); /* Maybe driver failed before freeze. * Restore the failed status, for debugging. */ if (dev->failed) virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); if (!drv) return 0; /* We have a driver! */ virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER); ret = virtio_finalize_features(dev); if (ret) goto err; if (drv->restore) { ret = drv->restore(dev); if (ret) goto err; } /* Finally, tell the device we're all set */ virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); virtio_config_enable(dev); return 0; err: virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); return ret; }
int register_virtio_device(struct virtio_device *dev) { int err; dev->dev.bus = &virtio_bus; /* Assign a unique device index and hence name. */ err = ida_simple_get(&virtio_index_ida, 0, 0, GFP_KERNEL); if (err < 0) goto out; dev->index = err; dev_set_name(&dev->dev, "virtio%u", dev->index); spin_lock_init(&dev->config_lock); dev->config_enabled = false; dev->config_change_pending = false; /* We always start by resetting the device, in case a previous * driver messed it up. This also tests that code path a little. */ dev->config->reset(dev); /* Acknowledge that we've seen the device. */ virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); INIT_LIST_HEAD(&dev->vqs); /* device_register() causes the bus infrastructure to look for a * matching driver. */ err = device_register(&dev->dev); if (err) ida_simple_remove(&virtio_index_ida, dev->index); out: if (err) virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); return err; }
static int virtio_dev_remove(struct device *_d) { struct virtio_device *dev = dev_to_virtio(_d); struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); virtio_config_disable(dev); drv->remove(dev); /* Driver should have reset device. */ WARN_ON_ONCE(dev->config->get_status(dev)); /* Acknowledge the device's existence again. */ virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); return 0; }
int virtio_finalize_features(struct virtio_device *dev) { int ret = dev->config->finalize_features(dev); unsigned status; if (ret) return ret; if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) return 0; virtio_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); status = dev->config->get_status(dev); if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { dev_err(&dev->dev, "virtio: device refuses features: %x\n", status); return -ENODEV; } return 0; }
NTSTATUS virtio_set_features(VirtIODevice *vdev, u64 features) { unsigned char dev_status; NTSTATUS status = vdev->device->set_features(vdev, features); if (!NT_SUCCESS(status)) { return status; } if (!virtio_is_feature_enabled(features, VIRTIO_F_VERSION_1)) { return status; } virtio_add_status(vdev, VIRTIO_CONFIG_S_FEATURES_OK); dev_status = vdev->device->get_status(vdev); if (!(dev_status & VIRTIO_CONFIG_S_FEATURES_OK)) { DPrintf(0, ("virtio: device refuses features: %x\n", dev_status)); status = STATUS_INVALID_PARAMETER; } return status; }
static int virtio_dev_probe(struct device *_d) { int err, i; struct virtio_device *dev = dev_to_virtio(_d); struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); u64 device_features; u64 driver_features; u64 driver_features_legacy; /* We have a driver! */ virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER); /* Figure out what features the device supports. */ device_features = dev->config->get_features(dev); /* Figure out what features the driver supports. */ driver_features = 0; for (i = 0; i < drv->feature_table_size; i++) { unsigned int f = drv->feature_table[i]; BUG_ON(f >= 64); driver_features |= (1ULL << f); } /* Some drivers have a separate feature table for virtio v1.0 */ if (drv->feature_table_legacy) { driver_features_legacy = 0; for (i = 0; i < drv->feature_table_size_legacy; i++) { unsigned int f = drv->feature_table_legacy[i]; BUG_ON(f >= 64); driver_features_legacy |= (1ULL << f); } } else { driver_features_legacy = driver_features; } if (device_features & (1ULL << VIRTIO_F_VERSION_1)) dev->features = driver_features & device_features; else dev->features = driver_features_legacy & device_features; /* Transport features always preserved to pass to finalize_features. */ for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) if (device_features & (1ULL << i)) __virtio_set_bit(dev, i); if (drv->validate) { err = drv->validate(dev); if (err) goto err; } err = virtio_finalize_features(dev); if (err) goto err; err = drv->probe(dev); if (err) goto err; /* If probe didn't do it, mark device DRIVER_OK ourselves. */ if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) virtio_device_ready(dev); if (drv->scan) drv->scan(dev); virtio_config_enable(dev); return 0; err: virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); return err; }