--- /dev/null
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/block/block.h"
+#include "sysemu/blockdev.h"
+#include "sysemu/iothread.h"
+#include "sysemu/block-backend.h"
+#include "hw/xen/xen_bus.h"
+#include "xen_blkif.h"
+#include "trace.h"
+
+#define TYPE_XEN_QDISK_BACKEND "xen-qdisk"
+#define XEN_QDISK_BACKEND(obj) \
+ OBJECT_CHECK(XenQdiskBackend, (obj), TYPE_XEN_QDISK_BACKEND)
+
+typedef struct XenQdiskBackend {
+ XenBackend xendev;
+ BlockConf conf;
+ bool discard_enable;
+ unsigned int max_ring_page_order;
+ BlockBackend *blk;
+} XenQdiskBackend;
+
+static void xen_qdisk_realize(XenBackend *dev, Error **errp)
+{
+ XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
+ DriveInfo *dinfo;
+ unsigned int info;
+ int64_t size;
+
+ if (!d->conf.blk) {
+ error_setg(errp, "drive property not set");
+ return;
+ }
+
+ if (!blk_is_inserted(d->conf.blk)) {
+ error_setg(errp, "Device needs media, but drive is empty");
+ return;
+ }
+
+ blkconf_blocksizes(&d->conf);
+
+ if (d->conf.logical_block_size >
+ d->conf.physical_block_size) {
+ error_setg(errp,
+ "logical_block_size > physical_block_size not supported");
+ return;
+ }
+
+ d->blk = d->conf.blk;
+ blk_set_guest_block_size(d->blk, d->conf.logical_block_size);
+
+ xenstore_backend_printf(dev, "feature-discard", "%u",
+ d->discard_enable);
+ xenstore_backend_printf(dev, "feature-flush-cache", "%u", 1);
+ xenstore_backend_printf(dev, "max-ring-page-order", "%u",
+ d->max_ring_page_order);
+
+ info = blk_is_read_only(d->blk) ? VDISK_READONLY : 0;
+
+ dinfo = blk_legacy_dinfo(d->blk);
+ info |= dinfo->media_cd ? VDISK_CDROM : 0;
+
+ xenstore_backend_printf(dev, "info", "%u", info);
+
+ size = blk_getlength(d->blk);
+ xenstore_backend_printf(dev, "sector-size", "%u",
+ d->conf.logical_block_size);
+ xenstore_backend_printf(dev, "sectors", "%lu",
+ size / d->conf.logical_block_size);
+}
+
+static void xen_qdisk_connect(XenBackend *dev, Error **errp)
+{
+}
+
+static void xen_qdisk_disconnect(XenBackend *dev, Error **errp)
+{
+}
+
+static void xen_qdisk_event(XenBackend *dev)
+{
+}
+
+static void xen_qdisk_unrealize(XenBackend *dev, Error **errp)
+{
+ XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
+
+ blockdev_mark_auto_del(d->blk);
+}
+
+static Property xen_qdisk_props[] = {
+ DEFINE_BLOCK_PROPERTIES(XenQdiskBackend, conf),
+ DEFINE_PROP_BOOL("discard-enable", XenQdiskBackend, discard_enable,
+ false),
+ DEFINE_PROP_UINT32("max-ring-page-order", XenQdiskBackend,
+ max_ring_page_order, 4),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void xen_qdisk_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ XenBackendClass *k = XEN_BACKEND_CLASS(klass);
+
+ k->type = "xen-qdisk";
+ k->device = "bar";
+ k->realize = xen_qdisk_realize;
+ k->connect = xen_qdisk_connect;
+ k->disconnect = xen_qdisk_disconnect;
+ k->event = xen_qdisk_event;
+ k->unrealize = xen_qdisk_unrealize;
+ dc->desc = "Xen Qdisk Backend";
+ dc->props = xen_qdisk_props;
+}
+
+static const TypeInfo xen_qdisk_type_info = {
+ .name = TYPE_XEN_QDISK_BACKEND,
+ .parent = TYPE_XEN_BACKEND,
+ .instance_size = sizeof(XenQdiskBackend),
+ .class_init = xen_qdisk_class_init,
+};
+
+static void xen_qdisk_register_types(void)
+{
+ type_register_static(&xen_qdisk_type_info);
+}
+
+type_init(xen_qdisk_register_types)