diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/audio/pcspk.c | 17 | ||||
| -rw-r--r-- | hw/i386/kvmvapic.c | 1 | ||||
| -rw-r--r-- | hw/i386/pc.c | 18 | ||||
| -rw-r--r-- | hw/intc/apic.c | 26 | ||||
| -rw-r--r-- | hw/misc/ivshmem.c | 1 | ||||
| -rw-r--r-- | hw/nvram/fw_cfg.c | 4 | ||||
| -rw-r--r-- | hw/ppc/ppc405.h | 6 | ||||
| -rw-r--r-- | hw/s390x/sclp.c | 2 | ||||
| -rw-r--r-- | hw/s390x/virtio-ccw.h | 1 | ||||
| -rw-r--r-- | hw/scsi/mptsas.c | 6 | ||||
| -rw-r--r-- | hw/scsi/scsi-disk.c | 22 | ||||
| -rw-r--r-- | hw/scsi/virtio-scsi.c | 15 | ||||
| -rw-r--r-- | hw/scsi/vmw_pvscsi.c | 5 | ||||
| -rw-r--r-- | hw/sh4/shix.c | 2 | ||||
| -rw-r--r-- | hw/tricore/tricore_testboard.c | 2 | ||||
| -rw-r--r-- | hw/usb/dev-mtp.c | 197 | ||||
| -rw-r--r-- | hw/usb/hcd-xhci.c | 9 | ||||
| -rw-r--r-- | hw/usb/host-libusb.c | 7 | ||||
| -rw-r--r-- | hw/vfio/pci.c | 4 |
19 files changed, 277 insertions, 68 deletions
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 42a6f4885a..984534b2d1 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -52,8 +52,8 @@ typedef struct { unsigned int pit_count; unsigned int samples; unsigned int play_pos; - int data_on; - int dummy_refresh_clock; + uint8_t data_on; + uint8_t dummy_refresh_clock; } PCSpkState; static const char *s_spk = "pcspk"; @@ -187,6 +187,18 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) pcspk_state = s; } +static const VMStateDescription vmstate_spk = { + .name = "pcspk", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(data_on, PCSpkState), + VMSTATE_UINT8(dummy_refresh_clock, PCSpkState), + VMSTATE_END_OF_LIST() + } +}; + static Property pcspk_properties[] = { DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1), DEFINE_PROP_END_OF_LIST(), @@ -198,6 +210,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data) dc->realize = pcspk_realizefn; set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->vmsd = &vmstate_spk; dc->props = pcspk_properties; /* Reason: realize sets global pcspk_state */ dc->cannot_instantiate_with_device_add_yet = true; diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index 3bf1ddd976..a1cd9b5a29 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -768,6 +768,7 @@ static void kvmvapic_vm_state_change(void *opaque, int running, } qemu_del_vm_change_state_handler(s->vmsentry); + s->vmsentry = NULL; } static int vapic_post_load(void *opaque, int version_id) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e31f70f428..2d6d7920ff 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -161,13 +161,15 @@ int cpu_get_pic_interrupt(CPUX86State *env) X86CPU *cpu = x86_env_get_cpu(env); int intno; - intno = apic_get_interrupt(cpu->apic_state); - if (intno >= 0) { - return intno; - } - /* read the irq from the PIC */ - if (!apic_accept_pic_intr(cpu->apic_state)) { - return -1; + if (!kvm_irqchip_in_kernel()) { + intno = apic_get_interrupt(cpu->apic_state); + if (intno >= 0) { + return intno; + } + /* read the irq from the PIC */ + if (!apic_accept_pic_intr(cpu->apic_state)) { + return -1; + } } intno = pic_read_irq(isa_pic); @@ -180,7 +182,7 @@ static void pic_irq_request(void *opaque, int irq, int level) X86CPU *cpu = X86_CPU(cs); DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq); - if (cpu->apic_state) { + if (cpu->apic_state && !kvm_irqchip_in_kernel()) { CPU_FOREACH(cs) { cpu = X86_CPU(cs); if (apic_accept_pic_intr(cpu->apic_state)) { diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 45887d99c0..7bd1d279c4 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -39,6 +39,10 @@ static APICCommonState *local_apics[MAX_APICS + 1]; +#define TYPE_APIC "apic" +#define APIC(obj) \ + OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC) + static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode); static void apic_update_irq(APICCommonState *s); static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, @@ -163,7 +167,7 @@ static void apic_local_deliver(APICCommonState *s, int vector) void apic_deliver_pic_intr(DeviceState *dev, int level) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); if (level) { apic_local_deliver(s, APIC_LVT_LINT0); @@ -373,7 +377,7 @@ static void apic_update_irq(APICCommonState *s) void apic_poll_irq(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); apic_sync_vapic(s, SYNC_FROM_VAPIC); apic_update_irq(s); @@ -479,7 +483,7 @@ static void apic_startup(APICCommonState *s, int vector_num) void apic_sipi(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI); @@ -493,7 +497,7 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); uint32_t deliver_bitmask[MAX_APIC_WORDS]; int dest_shorthand = (s->icr[0] >> 18) & 3; APICCommonState *apic_iter; @@ -550,7 +554,7 @@ static bool apic_check_pic(APICCommonState *s) int apic_get_interrupt(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); int intno; /* if the APIC is installed or enabled, we let the 8259 handle the @@ -584,7 +588,7 @@ int apic_get_interrupt(DeviceState *dev) int apic_accept_pic_intr(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); uint32_t lvt0; if (!s) @@ -663,7 +667,7 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr) if (!dev) { return 0; } - s = APIC_COMMON(dev); + s = APIC(dev); index = (addr >> 4) & 0xff; switch(index) { @@ -766,7 +770,7 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) if (!dev) { return; } - s = APIC_COMMON(dev); + s = APIC(dev); trace_apic_mem_writel(addr, val); @@ -870,7 +874,7 @@ static const MemoryRegionOps apic_io_ops = { static void apic_realize(DeviceState *dev, Error **errp) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); if (s->id >= MAX_APICS) { error_setg(errp, "%s initialization failed. APIC ID %d is invalid", @@ -889,7 +893,7 @@ static void apic_realize(DeviceState *dev, Error **errp) static void apic_unrealize(DeviceState *dev, Error **errp) { - APICCommonState *s = APIC_COMMON(dev); + APICCommonState *s = APIC(dev); timer_del(s->timer); timer_free(s->timer); @@ -912,7 +916,7 @@ static void apic_class_init(ObjectClass *klass, void *data) } static const TypeInfo apic_info = { - .name = "apic", + .name = TYPE_APIC, .instance_size = sizeof(APICCommonState), .parent = TYPE_APIC_COMMON, .class_init = apic_class_init, diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 40a2ebca20..f803dfd5b3 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -628,7 +628,6 @@ static void ivshmem_read(void *opaque, const uint8_t *buf, int size) s->msg_buffered_bytes = 0; fd = qemu_chr_fe_get_msgfd(s->server_chr); - IVSHMEM_DPRINTF("posn is %" PRId64 ", fd is %d\n", msg, fd); process_msg(s, msg, fd, &err); if (err) { diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 6a68e594d5..1776b1b3c4 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -180,7 +180,7 @@ static void fw_cfg_bootsplash(FWCfgState *s) temp = qemu_opt_get(opts, "splash-time"); if (temp != NULL) { p = (char *)temp; - boot_splash_time = strtol(p, (char **)&p, 10); + boot_splash_time = strtol(p, &p, 10); } } @@ -240,7 +240,7 @@ static void fw_cfg_reboot(FWCfgState *s) temp = qemu_opt_get(opts, "reboot-timeout"); if (temp != NULL) { p = (char *)temp; - reboot_timeout = strtol(p, (char **)&p, 10); + reboot_timeout = strtol(p, &p, 10); } } /* validate the input */ diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index c67febca2f..a9ffc87f19 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -71,11 +71,5 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem, hwaddr ram_sizes[2], uint32_t sysclk, qemu_irq **picp, int do_init); -/* IBM STBxxx microcontrollers */ -CPUPPCState *ppc_stb025_init (MemoryRegion ram_memories[2], - hwaddr ram_bases[2], - hwaddr ram_sizes[2], - uint32_t sysclk, qemu_irq **picp, - ram_addr_t *offsetp); #endif /* PPC405_H */ diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index 48e38b2bbe..e741da1141 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -426,7 +426,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) goto out; } - sclp_c->execute(sclp, (SCCB *)&work_sccb, code); + sclp_c->execute(sclp, &work_sccb, code); cpu_physical_memory_write(sccb, &work_sccb, be16_to_cpu(work_sccb.h.length)); diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 904e357581..b58ab21d4c 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -183,7 +183,6 @@ typedef struct VirtIORNGCcw { VirtIORNG vdev; } VirtIORNGCcw; -void virtio_ccw_device_update_status(SubchDev *sch); VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch); #ifdef CONFIG_VIRTFS diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index 0e0a22f696..ad87e78fe2 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -304,7 +304,7 @@ static int mptsas_process_scsi_io_request(MPTSASState *s, goto bad; } - req = g_new(MPTSASRequest, 1); + req = g_new0(MPTSASRequest, 1); QTAILQ_INSERT_TAIL(&s->pending, req, next); req->scsi_io = *scsi_io; req->dev = s; @@ -1269,7 +1269,7 @@ static const struct SCSIBusInfo mptsas_scsi_info = { .load_request = mptsas_load_request, }; -static void mptsas_scsi_init(PCIDevice *dev, Error **errp) +static void mptsas_scsi_realize(PCIDevice *dev, Error **errp) { DeviceState *d = DEVICE(dev); MPTSASState *s = MPT_SAS(dev); @@ -1426,7 +1426,7 @@ static void mptsas1068_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); - pc->realize = mptsas_scsi_init; + pc->realize = mptsas_scsi_realize; pc->exit = mptsas_scsi_uninit; pc->romfile = 0; pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC; diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 77cba31e30..88beaf4bb8 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -396,7 +396,7 @@ static void scsi_read_data(SCSIRequest *req) return; } - if (s->tray_open) { + if (!blk_is_available(req->dev->conf.blk)) { scsi_read_complete(r, -ENOMEDIUM); return; } @@ -519,7 +519,7 @@ static void scsi_write_data(SCSIRequest *req) scsi_write_complete_noio(r, 0); return; } - if (s->tray_open) { + if (!blk_is_available(req->dev->conf.blk)) { scsi_write_complete_noio(r, -ENOMEDIUM); return; } @@ -792,10 +792,7 @@ static inline bool media_is_dvd(SCSIDiskState *s) if (s->qdev.type != TYPE_ROM) { return false; } - if (!blk_is_inserted(s->qdev.conf.blk)) { - return false; - } - if (s->tray_open) { + if (!blk_is_available(s->qdev.conf.blk)) { return false; } blk_get_geometry(s->qdev.conf.blk, &nb_sectors); @@ -808,10 +805,7 @@ static inline bool media_is_cd(SCSIDiskState *s) if (s->qdev.type != TYPE_ROM) { return false; } - if (!blk_is_inserted(s->qdev.conf.blk)) { - return false; - } - if (s->tray_open) { + if (!blk_is_available(s->qdev.conf.blk)) { return false; } blk_get_geometry(s->qdev.conf.blk, &nb_sectors); @@ -875,7 +869,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r, } if (format != 0xff) { - if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { + if (!blk_is_available(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return -1; } @@ -1857,7 +1851,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) break; default: - if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { + if (!blk_is_available(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return 0; } @@ -1886,7 +1880,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) memset(outbuf, 0, r->buflen); switch (req->cmd.buf[0]) { case TEST_UNIT_READY: - assert(!s->tray_open && blk_is_inserted(s->qdev.conf.blk)); + assert(blk_is_available(s->qdev.conf.blk)); break; case INQUIRY: buflen = scsi_disk_emulate_inquiry(req, outbuf); @@ -2126,7 +2120,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) command = buf[0]; - if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { + if (!blk_is_available(s->qdev.conf.blk)) { scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); return 0; } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index ce57ef6248..e596b64741 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -236,6 +236,13 @@ static void virtio_scsi_cancel_notify(Notifier *notifier, void *data) g_free(n); } +static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d) +{ + if (s->dataplane_started && d && blk_is_available(d->conf.blk)) { + assert(blk_get_aio_context(d->conf.blk) == s->ctx); + } +} + /* Return 0 if the request is ready to be completed and return to guest; * -EINPROGRESS if the request is submitted and will be completed later, in the * case of async cancellation. */ @@ -247,9 +254,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) int target; int ret = 0; - if (s->dataplane_started && d) { - assert(blk_get_aio_context(d->conf.blk) == s->ctx); - } + virtio_scsi_ctx_check(s, d); /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */ req->resp.tmf.response = VIRTIO_SCSI_S_OK; @@ -539,9 +544,7 @@ static bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req virtio_scsi_complete_cmd_req(req); return false; } - if (s->dataplane_started) { - assert(blk_get_aio_context(d->conf.blk) == s->ctx); - } + virtio_scsi_ctx_check(s, d); req->sreq = scsi_req_new(d, req->req.cmd.tag, virtio_scsi_get_lun(req->req.cmd.lun), req->req.cmd.cdb, req); diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index babac5a68a..a5ce7dea8e 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -247,8 +247,11 @@ static hwaddr pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr) { uint32_t ready_ptr = RS_GET_FIELD(mgr, reqProdIdx); + uint32_t ring_size = PVSCSI_MAX_NUM_PAGES_REQ_RING + * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE; - if (ready_ptr != mgr->consumed_ptr) { + if (ready_ptr != mgr->consumed_ptr + && ready_ptr - mgr->consumed_ptr < ring_size) { uint32_t next_ready_ptr = mgr->consumed_ptr++ & mgr->txr_len_mask; uint32_t next_ready_page = diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c index ccc9e75894..14d4007c1c 100644 --- a/hw/sh4/shix.c +++ b/hw/sh4/shix.c @@ -23,7 +23,7 @@ */ /* Shix 2.0 board by Alexis Polti, described at - http://perso.enst.fr/~polti/realisations/shix20/ + https://web.archive.org/web/20070917001736/perso.enst.fr/~polti/realisations/shix20 More information in target-sh4/README.sh4 */ diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c index 8d3520f5be..19dd587207 100644 --- a/hw/tricore/tricore_testboard.c +++ b/hw/tricore/tricore_testboard.c @@ -46,7 +46,7 @@ static void tricore_load_kernel(CPUTriCoreState *env) long kernel_size; kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL, - NULL, (uint64_t *)&entry, NULL, + NULL, &entry, NULL, NULL, 0, EM_TRICORE, 1, 0); if (kernel_size <= 0) { diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 1be85ae75a..58d95fffb2 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -48,6 +48,9 @@ enum mtp_code { CMD_GET_OBJECT_INFO = 0x1008, CMD_GET_OBJECT = 0x1009, CMD_GET_PARTIAL_OBJECT = 0x101b, + CMD_GET_OBJECT_PROPS_SUPPORTED = 0x9801, + CMD_GET_OBJECT_PROP_DESC = 0x9802, + CMD_GET_OBJECT_PROP_VALUE = 0x9803, /* response codes */ RES_OK = 0x2001, @@ -59,10 +62,12 @@ enum mtp_code { RES_INCOMPLETE_TRANSFER = 0x2007, RES_INVALID_STORAGE_ID = 0x2008, RES_INVALID_OBJECT_HANDLE = 0x2009, + RES_INVALID_OBJECT_FORMAT_CODE = 0x200b, RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014, RES_INVALID_PARENT_OBJECT = 0x201a, RES_INVALID_PARAMETER = 0x201d, RES_SESSION_ALREADY_OPEN = 0x201e, + RES_INVALID_OBJECT_PROP_CODE = 0xA801, /* format codes */ FMT_UNDEFINED_OBJECT = 0x3000, @@ -72,6 +77,22 @@ enum mtp_code { EVT_OBJ_ADDED = 0x4002, EVT_OBJ_REMOVED = 0x4003, EVT_OBJ_INFO_CHANGED = 0x4007, + + /* object properties */ + PROP_STORAGE_ID = 0xDC01, + PROP_OBJECT_FORMAT = 0xDC02, + PROP_OBJECT_COMPRESSED_SIZE = 0xDC04, + PROP_PARENT_OBJECT = 0xDC0B, + PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER = 0xDC41, + PROP_NAME = 0xDC44, +}; + +enum mtp_data_type { + DATA_TYPE_UINT16 = 0x0004, + DATA_TYPE_UINT32 = 0x0006, + DATA_TYPE_UINT64 = 0x0008, + DATA_TYPE_UINT128 = 0x000a, + DATA_TYPE_STRING = 0xffff, }; typedef struct { @@ -115,8 +136,8 @@ struct MTPControl { struct MTPData { uint16_t code; uint32_t trans; - uint32_t offset; - uint32_t length; + uint64_t offset; + uint64_t length; uint32_t alloc; uint8_t *data; bool first; @@ -778,6 +799,9 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c) CMD_GET_OBJECT_INFO, CMD_GET_OBJECT, CMD_GET_PARTIAL_OBJECT, + CMD_GET_OBJECT_PROPS_SUPPORTED, + CMD_GET_OBJECT_PROP_DESC, + CMD_GET_OBJECT_PROP_VALUE, }; static const uint16_t fmt[] = { FMT_UNDEFINED_OBJECT, @@ -883,7 +907,12 @@ static MTPData *usb_mtp_get_object_info(MTPState *s, MTPControl *c, usb_mtp_add_u32(d, QEMU_STORAGE_ID); usb_mtp_add_u16(d, o->format); usb_mtp_add_u16(d, 0); - usb_mtp_add_u32(d, o->stat.st_size); + + if (o->stat.st_size > 0xFFFFFFFF) { + usb_mtp_add_u32(d, 0xFFFFFFFF); + } else { + usb_mtp_add_u32(d, o->stat.st_size); + } usb_mtp_add_u16(d, 0); usb_mtp_add_u32(d, 0); @@ -966,6 +995,122 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c, return d; } +static MTPData *usb_mtp_get_object_props_supported(MTPState *s, MTPControl *c) +{ + static const uint16_t props[] = { + PROP_STORAGE_ID, + PROP_OBJECT_FORMAT, + PROP_OBJECT_COMPRESSED_SIZE, + PROP_PARENT_OBJECT, + PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER, + PROP_NAME, + }; + MTPData *d = usb_mtp_data_alloc(c); + usb_mtp_add_u16_array(d, ARRAY_SIZE(props), props); + + return d; +} + +static MTPData *usb_mtp_get_object_prop_desc(MTPState *s, MTPControl *c) +{ + MTPData *d = usb_mtp_data_alloc(c); + switch (c->argv[0]) { + case PROP_STORAGE_ID: + usb_mtp_add_u16(d, PROP_STORAGE_ID); + usb_mtp_add_u16(d, DATA_TYPE_UINT32); + usb_mtp_add_u8(d, 0x00); + usb_mtp_add_u32(d, 0x00000000); + usb_mtp_add_u32(d, 0x00000000); + usb_mtp_add_u8(d, 0x00); + break; + case PROP_OBJECT_FORMAT: + usb_mtp_add_u16(d, PROP_OBJECT_FORMAT); + usb_mtp_add_u16(d, DATA_TYPE_UINT16); + usb_mtp_add_u8(d, 0x00); + usb_mtp_add_u16(d, 0x0000); + usb_mtp_add_u32(d, 0x00000000); + usb_mtp_add_u8(d, 0x00); + break; + case PROP_OBJECT_COMPRESSED_SIZE: + usb_mtp_add_u16(d, PROP_OBJECT_COMPRESSED_SIZE); + usb_mtp_add_u16(d, DATA_TYPE_UINT64); + usb_mtp_add_u8(d, 0x00); + usb_mtp_add_u64(d, 0x0000000000000000); + usb_mtp_add_u32(d, 0x00000000); + usb_mtp_add_u8(d, 0x00); + break; + case PROP_PARENT_OBJECT: + usb_mtp_add_u16(d, PROP_PARENT_OBJECT); + usb_mtp_add_u16(d, DATA_TYPE_UINT32); + usb_mtp_add_u8(d, 0x00); + usb_mtp_add_u32(d, 0x00000000); + usb_mtp_add_u32(d, 0x00000000); + usb_mtp_add_u8(d, 0x00); + break; + case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER: + usb_mtp_add_u16(d, PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER); + usb_mtp_add_u16(d, DATA_TYPE_UINT128); + usb_mtp_add_u8(d, 0x00); + usb_mtp_add_u64(d, 0x0000000000000000); + usb_mtp_add_u64(d, 0x0000000000000000); + usb_mtp_add_u32(d, 0x00000000); + usb_mtp_add_u8(d, 0x00); + break; + case PROP_NAME: + usb_mtp_add_u16(d, PROP_NAME); + usb_mtp_add_u16(d, DATA_TYPE_STRING); + usb_mtp_add_u8(d, 0x00); + usb_mtp_add_u8(d, 0x00); + usb_mtp_add_u32(d, 0x00000000); + usb_mtp_add_u8(d, 0x00); + break; + default: + usb_mtp_data_free(d); + return NULL; + } + + return d; +} + +static MTPData *usb_mtp_get_object_prop_value(MTPState *s, MTPControl *c, + MTPObject *o) +{ + MTPData *d = usb_mtp_data_alloc(c); + switch (c->argv[1]) { + case PROP_STORAGE_ID: + usb_mtp_add_u32(d, QEMU_STORAGE_ID); + break; + case PROP_OBJECT_FORMAT: + usb_mtp_add_u16(d, o->format); + break; + case PROP_OBJECT_COMPRESSED_SIZE: + usb_mtp_add_u64(d, o->stat.st_size); + break; + case PROP_PARENT_OBJECT: + if (o->parent == NULL) { + usb_mtp_add_u32(d, 0x00000000); + } else { + usb_mtp_add_u32(d, o->parent->handle); + } + break; + case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER: + /* Should be persistant between sessions, + * but using our objedt ID is "good enough" + * for now */ + usb_mtp_add_u64(d, 0x0000000000000000); + usb_mtp_add_u64(d, o->handle); + break; + case PROP_NAME: + usb_mtp_add_str(d, o->name); + break; + default: + usb_mtp_data_free(d); + return NULL; + } + + return d; +} + static void usb_mtp_command(MTPState *s, MTPControl *c) { MTPData *data_in = NULL; @@ -1113,6 +1258,43 @@ static void usb_mtp_command(MTPState *s, MTPControl *c) nres = 1; res0 = data_in->length; break; + case CMD_GET_OBJECT_PROPS_SUPPORTED: + if (c->argv[0] != FMT_UNDEFINED_OBJECT && + c->argv[0] != FMT_ASSOCIATION) { + usb_mtp_queue_result(s, RES_INVALID_OBJECT_FORMAT_CODE, + c->trans, 0, 0, 0); + return; + } + data_in = usb_mtp_get_object_props_supported(s, c); + break; + case CMD_GET_OBJECT_PROP_DESC: + if (c->argv[1] != FMT_UNDEFINED_OBJECT && + c->argv[1] != FMT_ASSOCIATION) { + usb_mtp_queue_result(s, RES_INVALID_OBJECT_FORMAT_CODE, + c->trans, 0, 0, 0); + return; + } + data_in = usb_mtp_get_object_prop_desc(s, c); + if (data_in == NULL) { + usb_mtp_queue_result(s, RES_INVALID_OBJECT_PROP_CODE, + c->trans, 0, 0, 0); + return; + } + break; + case CMD_GET_OBJECT_PROP_VALUE: + o = usb_mtp_object_lookup(s, c->argv[0]); + if (o == NULL) { + usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE, + c->trans, 0, 0, 0); + return; + } + data_in = usb_mtp_get_object_prop_value(s, c, o); + if (data_in == NULL) { + usb_mtp_queue_result(s, RES_INVALID_OBJECT_PROP_CODE, + c->trans, 0, 0, 0); + return; + } + break; default: trace_usb_mtp_op_unknown(s->dev.addr, c->code); usb_mtp_queue_result(s, RES_OPERATION_NOT_SUPPORTED, @@ -1193,10 +1375,15 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) } if (s->data_in != NULL) { MTPData *d = s->data_in; - int dlen = d->length - d->offset; + uint64_t dlen = d->length - d->offset; if (d->first) { trace_usb_mtp_data_in(s->dev.addr, d->trans, d->length); - container.length = cpu_to_le32(d->length + sizeof(container)); + if (d->length + sizeof(container) > 0xFFFFFFFF) { + container.length = cpu_to_le32(0xFFFFFFFF); + } else { + container.length = + cpu_to_le32(d->length + sizeof(container)); + } container.type = cpu_to_le16(TYPE_DATA); container.code = cpu_to_le16(d->code); container.trans = cpu_to_le32(d->trans); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 188f95416a..726435c462 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1753,6 +1753,12 @@ static void xhci_xfer_report(XHCITransfer *xfer) unsigned int chunk = 0; switch (TRB_TYPE(*trb)) { + case TR_SETUP: + chunk = trb->status & 0x1ffff; + if (chunk > 8) { + chunk = 8; + } + break; case TR_DATA: case TR_NORMAL: case TR_ISOCH: @@ -3709,8 +3715,7 @@ static void usb_xhci_exit(PCIDevice *dev) /* destroy msix memory region */ if (dev->msix_table && dev->msix_pba && dev->msix_entry_used) { - memory_region_del_subregion(&xhci->mem, &dev->msix_table_mmio); - memory_region_del_subregion(&xhci->mem, &dev->msix_pba_mmio); + msix_uninit(dev, &xhci->mem, &xhci->mem); } usb_bus_release(&xhci->bus); diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index e94672c155..bd81d71a98 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -743,10 +743,13 @@ static void usb_host_speed_compat(USBHostDevice *s) rc = libusb_get_ss_endpoint_companion_descriptor (ctx, endp, &endp_ss_comp); if (rc == LIBUSB_SUCCESS) { + int streams = endp_ss_comp->bmAttributes & 0x1f; + if (streams) { + compat_full = false; + compat_high = false; + } libusb_free_ss_endpoint_companion_descriptor (endp_ss_comp); - compat_full = false; - compat_high = false; } #endif break; diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 7bfa17ce38..a5a620a0c4 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -496,7 +496,9 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, vfio_update_kvm_msi_virq(vector, *msg, pdev); } } else { - vfio_add_kvm_msi_virq(vdev, vector, nr, true); + if (msg) { + vfio_add_kvm_msi_virq(vdev, vector, nr, true); + } } /* |