diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/9pfs/virtio-9p-local.c | 14 | ||||
-rw-r--r-- | hw/ccid-card-passthru.c | 1 | ||||
-rw-r--r-- | hw/eepro100.c | 10 | ||||
-rw-r--r-- | hw/pci-hotplug.c | 3 | ||||
-rw-r--r-- | hw/rtl8139.c | 14 | ||||
-rw-r--r-- | hw/s390-virtio-bus.c | 5 | ||||
-rw-r--r-- | hw/scsi-bus.c | 11 | ||||
-rw-r--r-- | hw/scsi-generic.c | 5 | ||||
-rw-r--r-- | hw/scsi.h | 2 | ||||
-rw-r--r-- | hw/syborg_virtio.c | 4 | ||||
-rw-r--r-- | hw/usb-bt.c | 3 | ||||
-rw-r--r-- | hw/usb-bus.c | 29 | ||||
-rw-r--r-- | hw/usb-ehci.c | 58 | ||||
-rw-r--r-- | hw/usb-hub.c | 22 | ||||
-rw-r--r-- | hw/usb-msd.c | 4 | ||||
-rw-r--r-- | hw/virtio-blk.c | 7 | ||||
-rw-r--r-- | hw/virtio-pci.c | 9 | ||||
-rw-r--r-- | hw/virtio.c | 24 | ||||
-rw-r--r-- | hw/virtio.h | 1 |
19 files changed, 142 insertions, 84 deletions
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 7f1c089..99ef0cd 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -583,8 +583,7 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path, char buffer[PATH_MAX]; char *path = fs_path->data; - return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf, - AT_SYMLINK_NOFOLLOW); + return qemu_utimens(rpath(s, path, buffer), buf); } static int local_remove(FsContext *ctx, const char *path) @@ -694,6 +693,7 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { int err; +#ifdef FS_IOC_GETVERSION V9fsFidOpenState fid_open; /* @@ -709,15 +709,22 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, } err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); local_close(ctx, &fid_open); +#else + err = -ENOTTY; +#endif return err; } static int local_init(FsContext *ctx) { - int err; + int err = 0; struct statfs stbuf; ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; +#ifdef FS_IOC_GETVERSION + /* + * use ioc_getversion only if the iocl is definied + */ err = statfs(ctx->fs_root, &stbuf); if (!err) { switch (stbuf.f_type) { @@ -729,6 +736,7 @@ static int local_init(FsContext *ctx) break; } } +#endif return err; } diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c index 2cbc81b..9f51c6c 100644 --- a/hw/ccid-card-passthru.c +++ b/hw/ccid-card-passthru.c @@ -150,6 +150,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card, error_report("ATR size exceeds spec, ignoring"); ccid_card_vscard_send_error(card, scr_msg_header->reader_id, VSC_GENERAL_ERROR); + break; } memcpy(card->atr, data, scr_msg_header->length); card->atr_length = scr_msg_header->length; diff --git a/hw/eepro100.c b/hw/eepro100.c index 7d59e71..29ec5b4 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -976,7 +976,15 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) case CU_STATSADDR: /* Load dump counters address. */ s->statsaddr = e100_read_reg4(s, SCBPointer); - TRACE(OTHER, logout("val=0x%02x (status address)\n", val)); + TRACE(OTHER, logout("val=0x%02x (dump counters address)\n", val)); + if (s->statsaddr & 3) { + /* Memory must be Dword aligned. */ + logout("unaligned dump counters address\n"); + /* Handling of misaligned addresses is undefined. + * Here we align the address by ignoring the lower bits. */ + /* TODO: Test unaligned dump counter address on real hardware. */ + s->statsaddr &= ~3; + } break; case CU_SHOWSTATS: /* Dump statistical counters. */ diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index b59be2a..12f61fe 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -91,7 +91,8 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, */ dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); dinfo->bus = scsibus->busnr; - scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, false); + scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, + false, -1); if (!scsidev) { return -1; } diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 4c37993..aa8ed0a 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -1971,7 +1971,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) cplus_tx_ring_desc += 16 * descriptor; DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at " - "%08x0x%08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1], + "%08x %08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc); uint32_t val, txdw0,txdw1,txbufLO,txbufHI; @@ -2713,8 +2713,6 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val) { RTL8139State *s = opaque; - addr &= 0xff; - switch (addr) { case MAC0 ... MAC0+5: @@ -2800,8 +2798,6 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val) { RTL8139State *s = opaque; - addr &= 0xfe; - switch (addr) { case IntrMask: @@ -2900,8 +2896,6 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val) { RTL8139State *s = opaque; - addr &= 0xfc; - switch (addr) { case RxMissed: @@ -2969,8 +2963,6 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr) RTL8139State *s = opaque; int ret; - addr &= 0xff; - switch (addr) { case MAC0 ... MAC0+5: @@ -3043,8 +3035,6 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr) RTL8139State *s = opaque; uint32_t ret; - addr &= 0xfe; /* mask lower bit */ - switch (addr) { case IntrMask: @@ -3120,8 +3110,6 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr) RTL8139State *s = opaque; uint32_t ret; - addr &= 0xfc; /* also mask low 2 bits */ - switch (addr) { case RxMissed: diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 0ce6406..c4b9a99 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -254,10 +254,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev) /* Update guest supported feature bitmap */ features = bswap32(ldl_be_phys(dev->feat_offs)); - if (vdev->set_features) { - vdev->set_features(vdev, features); - } - vdev->guest_features = features; + virtio_set_features(vdev, features); } VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 3a2a7bb..64e709e 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -162,7 +162,7 @@ void scsi_qdev_register(SCSIDeviceInfo *info) /* handle legacy '-drive if=scsi,...' cmd line args */ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable) + int unit, bool removable, int bootindex) { const char *driver; DeviceState *dev; @@ -170,6 +170,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk"; dev = qdev_create(&bus->qbus, driver); qdev_prop_set_uint32(dev, "scsi-id", unit); + if (bootindex >= 0) { + qdev_prop_set_int32(dev, "bootindex", bootindex); + } if (qdev_prop_exists(dev, "removable")) { qdev_prop_set_bit(dev, "removable", removable); } @@ -195,7 +198,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) continue; } qemu_opts_loc_restore(dinfo->opts); - if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false)) { + if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) { res = -1; break; } @@ -1367,8 +1370,8 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev) SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev); char path[100]; - snprintf(path, sizeof(path), "%s@%d,%d,%d", qdev_fw_name(dev), - d->channel, d->id, d->lun); + snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel, + qdev_fw_name(dev), d->id, d->lun); return strdup(path); } diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 9594cc1..e62044f 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -413,6 +413,10 @@ static int scsi_generic_initfn(SCSIDevice *s) /* define device state */ s->type = scsiid.scsi_type; DPRINTF("device type %d\n", s->type); + if (s->type == TYPE_DISK || s->type == TYPE_ROM) { + add_boot_device_path(s->conf.bootindex, &s->qdev, NULL); + } + switch (s->type) { case TYPE_TAPE: s->blocksize = get_stream_blocksize(s->conf.bs); @@ -459,6 +463,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, static SCSIDeviceInfo scsi_generic_info = { .qdev.name = "scsi-generic", + .qdev.fw_name = "disk", .qdev.desc = "pass through generic scsi device (/dev/sg*)", .qdev.size = sizeof(SCSIDevice), .qdev.reset = scsi_generic_reset, @@ -128,7 +128,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) } SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable); + int unit, bool removable, int bootindex); int scsi_bus_legacy_handle_cmdline(SCSIBus *bus); /* diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c index 3bb10b5..96a0ee6 100644 --- a/hw/syborg_virtio.c +++ b/hw/syborg_virtio.c @@ -132,9 +132,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset, } switch (offset >> 2) { case SYBORG_VIRTIO_GUEST_FEATURES: - if (vdev->set_features) - vdev->set_features(vdev, value); - vdev->guest_features = value; + virtio_set_features(vdev, value); break; case SYBORG_VIRTIO_QUEUE_BASE: if (value == 0) diff --git a/hw/usb-bt.c b/hw/usb-bt.c index 529fa33..f30eec1 100644 --- a/hw/usb-bt.c +++ b/hw/usb-bt.c @@ -528,6 +528,9 @@ USBDevice *usb_bt_init(HCIInfo *hci) if (!hci) return NULL; dev = usb_create_simple(NULL /* FIXME */, "usb-bt-dongle"); + if (!dev) { + return NULL; + } s = DO_UPCAST(struct USBBtState, dev, dev); s->dev.opaque = s; diff --git a/hw/usb-bus.c b/hw/usb-bus.c index 93f640d..8cafb76 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -9,6 +9,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); static char *usb_get_dev_path(DeviceState *dev); static char *usb_get_fw_dev_path(DeviceState *qdev); +static int usb_qdev_exit(DeviceState *qdev); static struct BusInfo usb_bus_info = { .name = "USB", @@ -75,12 +76,23 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) dev->auto_attach = 1; QLIST_INIT(&dev->strings); rc = usb_claim_port(dev); - if (rc == 0) { - rc = dev->info->init(dev); + if (rc != 0) { + goto err; } - if (rc == 0 && dev->auto_attach) { + rc = dev->info->init(dev); + if (rc != 0) { + goto err; + } + if (dev->auto_attach) { rc = usb_device_attach(dev); + if (rc != 0) { + goto err; + } } + return 0; + +err: + usb_qdev_exit(qdev); return rc; } @@ -139,10 +151,17 @@ USBDevice *usb_create(USBBus *bus, const char *name) USBDevice *usb_create_simple(USBBus *bus, const char *name) { USBDevice *dev = usb_create(bus, name); + int rc; + if (!dev) { - hw_error("Failed to create USB device '%s'\n", name); + error_report("Failed to create USB device '%s'\n", name); + return NULL; + } + rc = qdev_init(&dev->qdev); + if (rc < 0) { + error_report("Failed to initialize USB device '%s'\n", name); + return NULL; } - qdev_init_nofail(&dev->qdev); return dev; } diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index 3eea94d..a946e1d 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -437,37 +437,39 @@ struct EHCIState { } while(0) static const char *ehci_state_names[] = { - [ EST_INACTIVE ] = "INACTIVE", - [ EST_ACTIVE ] = "ACTIVE", - [ EST_EXECUTING ] = "EXECUTING", - [ EST_SLEEPING ] = "SLEEPING", - [ EST_WAITLISTHEAD ] = "WAITLISTHEAD", - [ EST_FETCHENTRY ] = "FETCH ENTRY", - [ EST_FETCHQH ] = "FETCH QH", - [ EST_FETCHITD ] = "FETCH ITD", - [ EST_ADVANCEQUEUE ] = "ADVANCEQUEUE", - [ EST_FETCHQTD ] = "FETCH QTD", - [ EST_EXECUTE ] = "EXECUTE", - [ EST_WRITEBACK ] = "WRITEBACK", - [ EST_HORIZONTALQH ] = "HORIZONTALQH", + [EST_INACTIVE] = "INACTIVE", + [EST_ACTIVE] = "ACTIVE", + [EST_EXECUTING] = "EXECUTING", + [EST_SLEEPING] = "SLEEPING", + [EST_WAITLISTHEAD] = "WAITLISTHEAD", + [EST_FETCHENTRY] = "FETCH ENTRY", + [EST_FETCHQH] = "FETCH QH", + [EST_FETCHITD] = "FETCH ITD", + [EST_ADVANCEQUEUE] = "ADVANCEQUEUE", + [EST_FETCHQTD] = "FETCH QTD", + [EST_EXECUTE] = "EXECUTE", + [EST_WRITEBACK] = "WRITEBACK", + [EST_HORIZONTALQH] = "HORIZONTALQH", }; static const char *ehci_mmio_names[] = { - [ CAPLENGTH ] = "CAPLENGTH", - [ HCIVERSION ] = "HCIVERSION", - [ HCSPARAMS ] = "HCSPARAMS", - [ HCCPARAMS ] = "HCCPARAMS", - [ USBCMD ] = "USBCMD", - [ USBSTS ] = "USBSTS", - [ USBINTR ] = "USBINTR", - [ FRINDEX ] = "FRINDEX", - [ PERIODICLISTBASE ] = "P-LIST BASE", - [ ASYNCLISTADDR ] = "A-LIST ADDR", - [ PORTSC_BEGIN ] = "PORTSC #0", - [ PORTSC_BEGIN + 4] = "PORTSC #1", - [ PORTSC_BEGIN + 8] = "PORTSC #2", - [ PORTSC_BEGIN + 12] = "PORTSC #3", - [ CONFIGFLAG ] = "CONFIGFLAG", + [CAPLENGTH] = "CAPLENGTH", + [HCIVERSION] = "HCIVERSION", + [HCSPARAMS] = "HCSPARAMS", + [HCCPARAMS] = "HCCPARAMS", + [USBCMD] = "USBCMD", + [USBSTS] = "USBSTS", + [USBINTR] = "USBINTR", + [FRINDEX] = "FRINDEX", + [PERIODICLISTBASE] = "P-LIST BASE", + [ASYNCLISTADDR] = "A-LIST ADDR", + [PORTSC_BEGIN] = "PORTSC #0", + [PORTSC_BEGIN + 4] = "PORTSC #1", + [PORTSC_BEGIN + 8] = "PORTSC #2", + [PORTSC_BEGIN + 12] = "PORTSC #3", + [PORTSC_BEGIN + 16] = "PORTSC #4", + [PORTSC_BEGIN + 20] = "PORTSC #5", + [CONFIGFLAG] = "CONFIGFLAG", }; static const char *nr2str(const char **n, size_t len, uint32_t nr) diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 3eb0f1a..e195937 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -171,6 +171,8 @@ static void usb_hub_detach(USBPort *port1) USBHubState *s = port1->opaque; USBHubPort *port = &s->ports[port1->index]; + usb_wakeup(&s->dev); + /* Let upstream know the device on this port is gone */ s->dev.port->ops->child_detach(s->dev.port, port1->dev); @@ -220,7 +222,22 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet) static void usb_hub_handle_reset(USBDevice *dev) { - /* XXX: do it */ + USBHubState *s = DO_UPCAST(USBHubState, dev, dev); + USBHubPort *port; + int i; + + for (i = 0; i < NUM_PORTS; i++) { + port = s->ports + i; + port->wPortStatus = PORT_STAT_POWER; + port->wPortChange = 0; + if (port->port.dev && port->port.dev->attached) { + port->wPortStatus |= PORT_STAT_CONNECTION; + port->wPortChange |= PORT_STAT_C_CONNECTION; + if (port->port.dev->speed == USB_SPEED_LOW) { + port->wPortStatus |= PORT_STAT_LOW_SPEED; + } + } + } } static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, @@ -495,9 +512,8 @@ static int usb_hub_initfn(USBDevice *dev) &port->port, s, i, &usb_hub_port_ops, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); usb_port_location(&port->port, dev->port, i+1); - port->wPortStatus = PORT_STAT_POWER; - port->wPortChange = 0; } + usb_hub_handle_reset(dev); return 0; } diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 68e3756..4c06950 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -546,7 +546,8 @@ static int usb_msd_initfn(USBDevice *dev) usb_desc_init(dev); scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info); - s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable); + s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, + s->conf.bootindex); if (!s->scsi_dev) { return -1; } @@ -562,7 +563,6 @@ static int usb_msd_initfn(USBDevice *dev) } } - add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0"); return 0; } diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 19e89e7..d6d1f87 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -485,6 +485,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) struct virtio_blk_config blkcfg; uint64_t capacity; int cylinders, heads, secs; + int blk_size = s->conf->logical_block_size; bdrv_get_geometry(s->bs, &capacity); bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs); @@ -492,14 +493,14 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) stq_raw(&blkcfg.capacity, capacity); stl_raw(&blkcfg.seg_max, 128 - 2); stw_raw(&blkcfg.cylinders, cylinders); + stl_raw(&blkcfg.blk_size, blk_size); + stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size); + stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size); blkcfg.heads = heads; blkcfg.sectors = secs & ~s->sector_mask; - blkcfg.blk_size = s->conf->logical_block_size; blkcfg.size_max = 0; blkcfg.physical_block_exp = get_physical_block_exp(s->conf); blkcfg.alignment_offset = 0; - blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size; - blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size; memcpy(config, &blkcfg, sizeof(struct virtio_blk_config)); } diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index ca5923c..64c6a94 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -285,14 +285,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) case VIRTIO_PCI_GUEST_FEATURES: /* Guest does not negotiate properly? We have to assume nothing. */ if (val & (1 << VIRTIO_F_BAD_FEATURE)) { - if (vdev->bad_features) - val = proxy->host_features & vdev->bad_features(vdev); - else - val = 0; + val = vdev->bad_features ? vdev->bad_features(vdev) : 0; } - if (vdev->set_features) - vdev->set_features(vdev, val); - vdev->guest_features = val; + virtio_set_features(vdev, val); break; case VIRTIO_PCI_QUEUE_PFN: pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; diff --git a/hw/virtio.c b/hw/virtio.c index 7011b5b..81ecc40 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -763,12 +763,25 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) } } +int virtio_set_features(VirtIODevice *vdev, uint32_t val) +{ + uint32_t supported_features = + vdev->binding->get_features(vdev->binding_opaque); + bool bad = (val & ~supported_features) != 0; + + val &= supported_features; + if (vdev->set_features) { + vdev->set_features(vdev, val); + } + vdev->guest_features = val; + return bad ? -1 : 0; +} + int virtio_load(VirtIODevice *vdev, QEMUFile *f) { int num, i, ret; uint32_t features; - uint32_t supported_features = - vdev->binding->get_features(vdev->binding_opaque); + uint32_t supported_features; if (vdev->binding->load_config) { ret = vdev->binding->load_config(vdev->binding_opaque, f); @@ -780,14 +793,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) qemu_get_8s(f, &vdev->isr); qemu_get_be16s(f, &vdev->queue_sel); qemu_get_be32s(f, &features); - if (features & ~supported_features) { + + if (virtio_set_features(vdev, features) < 0) { + supported_features = vdev->binding->get_features(vdev->binding_opaque); error_report("Features 0x%x unsupported. Allowed features: 0x%x", features, supported_features); return -1; } - if (vdev->set_features) - vdev->set_features(vdev, features); - vdev->guest_features = features; vdev->config_len = qemu_get_be32(f); qemu_get_buffer(f, vdev->config, vdev->config_len); diff --git a/hw/virtio.h b/hw/virtio.h index 2d18209..25f5564 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -185,6 +185,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); void virtio_set_status(VirtIODevice *vdev, uint8_t val); void virtio_reset(void *opaque); void virtio_update_irq(VirtIODevice *vdev); +int virtio_set_features(VirtIODevice *vdev, uint32_t val); void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, void *opaque); |