diff options
author | Peter Maydell | 2021-03-16 14:17:54 +0100 |
---|---|---|
committer | Peter Maydell | 2021-03-16 14:17:54 +0100 |
commit | 5b7f5586d182b0cafb1f8d558992a14763e2953e (patch) | |
tree | a402863844c68bbc43fd0488d0856a077bb44d1b /hw | |
parent | Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into st... (diff) | |
parent | usb/storage: clear csw on reset (diff) | |
download | qemu-5b7f5586d182b0cafb1f8d558992a14763e2953e.tar.gz qemu-5b7f5586d182b0cafb1f8d558992a14763e2953e.tar.xz qemu-5b7f5586d182b0cafb1f8d558992a14763e2953e.zip |
Merge remote-tracking branch 'remotes/kraxel/tags/usb-20210315-pull-request' into staging
usb: -usbdevice cleanup and un-deprecation.
usb: split usb-storage.
usb: misc fixes and cleanups.
# gpg: Signature made Mon 15 Mar 2021 18:02:28 GMT
# gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138
* remotes/kraxel/tags/usb-20210315-pull-request:
usb/storage: clear csw on reset
usb/storage: add kconfig symbols
usb/storage move usb-storage device to separate source file
usb/storage: move usb-bot device to separate source file
usb/storage: move declarations to usb/msd.h header
hw/usb: Extract VT82C686 UHCI PCI function into a new unit
hw/usb/hcd-uhci: Expose generic prototypes to local header
hw/southbridge: Add missing Kconfig dependency VT82C686 on USB_UHCI
usb: Document the missing -usbdevice options
usb: Un-deprecate -usbdevice (except for -usbdevice audio which gets removed)
usb: remove '-usbdevice u2f-key'
usb: remove support for -usbdevice parameters
hw/usb/bus: Remove the "full-path" property
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/isa/Kconfig | 1 | ||||
-rw-r--r-- | hw/usb/Kconfig | 13 | ||||
-rw-r--r-- | hw/usb/bus.c | 39 | ||||
-rw-r--r-- | hw/usb/dev-audio.c | 1 | ||||
-rw-r--r-- | hw/usb/dev-serial.c | 2 | ||||
-rw-r--r-- | hw/usb/dev-storage-bot.c | 63 | ||||
-rw-r--r-- | hw/usb/dev-storage-classic.c | 156 | ||||
-rw-r--r-- | hw/usb/dev-storage.c | 226 | ||||
-rw-r--r-- | hw/usb/hcd-uhci.c | 83 | ||||
-rw-r--r-- | hw/usb/hcd-uhci.h | 93 | ||||
-rw-r--r-- | hw/usb/meson.build | 5 | ||||
-rw-r--r-- | hw/usb/u2f.c | 1 | ||||
-rw-r--r-- | hw/usb/vt82c686-uhci-pci.c | 43 |
13 files changed, 391 insertions, 335 deletions
diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig index c7f07854f7..2691eae2f0 100644 --- a/hw/isa/Kconfig +++ b/hw/isa/Kconfig @@ -47,6 +47,7 @@ config VT82C686 select ACPI_SMBUS select SERIAL_ISA select FDC + select USB_UHCI config SMC37C669 bool diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig index 40093d7ea6..53f8283ffd 100644 --- a/hw/usb/Kconfig +++ b/hw/usb/Kconfig @@ -66,11 +66,22 @@ config USB_TABLET_WACOM default y depends on USB +config USB_STORAGE_CORE + bool + depends on USB + select SCSI + +config USB_STORAGE_CLASSIC + bool + default y + depends on USB + select USB_STORAGE_CORE + config USB_STORAGE_BOT bool default y depends on USB - select SCSI + select USB_STORAGE_CORE config USB_STORAGE_UAS bool diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 064f94e9c3..07083349f5 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -19,8 +19,6 @@ static void usb_qdev_unrealize(DeviceState *qdev); static Property usb_props[] = { DEFINE_PROP_STRING("port", USBDevice, port_path), DEFINE_PROP_STRING("serial", USBDevice, serial), - DEFINE_PROP_BIT("full-path", USBDevice, flags, - USB_DEV_FLAG_FULL_PATH, true), DEFINE_PROP_BIT("msos-desc", USBDevice, flags, USB_DEV_FLAG_MSOS_DESC_ENABLE, true), DEFINE_PROP_STRING("pcap", USBDevice, pcap_filename), @@ -312,13 +310,13 @@ typedef struct LegacyUSBFactory { const char *name; const char *usbdevice_name; - USBDevice *(*usbdevice_init)(const char *params); + USBDevice *(*usbdevice_init)(void); } LegacyUSBFactory; static GSList *legacy_usb_factory; void usb_legacy_register(const char *typename, const char *usbdevice_name, - USBDevice *(*usbdevice_init)(const char *params)) + USBDevice *(*usbdevice_init)(void)) { if (usbdevice_name) { LegacyUSBFactory *f = g_malloc0(sizeof(*f)); @@ -596,11 +594,8 @@ static char *usb_get_dev_path(DeviceState *qdev) { USBDevice *dev = USB_DEVICE(qdev); DeviceState *hcd = qdev->parent_bus->parent; - char *id = NULL; + char *id = qdev_get_dev_path(hcd); - if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) { - id = qdev_get_dev_path(hcd); - } if (id) { char *ret = g_strdup_printf("%s/%s", id, dev->port->path); g_free(id); @@ -663,27 +658,17 @@ void hmp_info_usb(Monitor *mon, const QDict *qdict) } /* handle legacy -usbdevice cmd line option */ -USBDevice *usbdevice_create(const char *cmdline) +USBDevice *usbdevice_create(const char *driver) { USBBus *bus = usb_bus_find(-1 /* any */); LegacyUSBFactory *f = NULL; Error *err = NULL; GSList *i; - char driver[32]; - const char *params; - int len; USBDevice *dev; - params = strchr(cmdline,':'); - if (params) { - params++; - len = params - cmdline; - if (len > sizeof(driver)) - len = sizeof(driver); - pstrcpy(driver, len, cmdline); - } else { - params = ""; - pstrcpy(driver, sizeof(driver), cmdline); + if (strchr(driver, ':')) { + error_report("usbdevice parameters are not supported anymore"); + return NULL; } for (i = legacy_usb_factory; i; i = i->next) { @@ -707,15 +692,7 @@ USBDevice *usbdevice_create(const char *cmdline) return NULL; } - if (f->usbdevice_init) { - dev = f->usbdevice_init(params); - } else { - if (*params) { - error_report("usbdevice %s accepts no params", driver); - return NULL; - } - dev = usb_new(f->name); - } + dev = f->usbdevice_init ? f->usbdevice_init() : usb_new(f->name); if (!dev) { error_report("Failed to create USB device '%s'", f->name); return NULL; diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index e1486f81e0..f5cb246792 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -1024,7 +1024,6 @@ static const TypeInfo usb_audio_info = { static void usb_audio_register_types(void) { type_register_static(&usb_audio_info); - usb_legacy_register(TYPE_USB_AUDIO, "audio", NULL); } type_init(usb_audio_register_types) diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index b58c4eb908..63047d79cf 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -614,7 +614,7 @@ static void usb_serial_realize(USBDevice *dev, Error **errp) s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); } -static USBDevice *usb_braille_init(const char *unused) +static USBDevice *usb_braille_init(void) { USBDevice *dev; Chardev *cdrv; diff --git a/hw/usb/dev-storage-bot.c b/hw/usb/dev-storage-bot.c new file mode 100644 index 0000000000..6aad026d11 --- /dev/null +++ b/hw/usb/dev-storage-bot.c @@ -0,0 +1,63 @@ +/* + * USB Mass Storage Device emulation + * + * Copyright (c) 2006 CodeSourcery. + * Written by Paul Brook + * + * This code is licensed under the LGPL. + */ + +#include "qemu/osdep.h" +#include "qemu/typedefs.h" +#include "qapi/error.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" +#include "hw/usb/msd.h" + +static const struct SCSIBusInfo usb_msd_scsi_info_bot = { + .tcq = false, + .max_target = 0, + .max_lun = 15, + + .transfer_data = usb_msd_transfer_data, + .complete = usb_msd_command_complete, + .cancel = usb_msd_request_cancelled, + .load_request = usb_msd_load_request, +}; + +static void usb_msd_bot_realize(USBDevice *dev, Error **errp) +{ + MSDState *s = USB_STORAGE_DEV(dev); + DeviceState *d = DEVICE(dev); + + usb_desc_create_serial(dev); + usb_desc_init(dev); + if (d->hotplugged) { + s->dev.auto_attach = 0; + } + + scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), + &usb_msd_scsi_info_bot, NULL); + usb_msd_handle_reset(dev); +} + +static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->realize = usb_msd_bot_realize; + uc->attached_settable = true; +} + +static const TypeInfo bot_info = { + .name = "usb-bot", + .parent = TYPE_USB_STORAGE, + .class_init = usb_msd_class_bot_initfn, +}; + +static void register_types(void) +{ + type_register_static(&bot_info); +} + +type_init(register_types) diff --git a/hw/usb/dev-storage-classic.c b/hw/usb/dev-storage-classic.c new file mode 100644 index 0000000000..00cb34b22f --- /dev/null +++ b/hw/usb/dev-storage-classic.c @@ -0,0 +1,156 @@ +/* + * USB Mass Storage Device emulation + * + * Copyright (c) 2006 CodeSourcery. + * Written by Paul Brook + * + * This code is licensed under the LGPL. + */ + +#include "qemu/osdep.h" +#include "qemu/typedefs.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" +#include "hw/usb/msd.h" +#include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" + +static const struct SCSIBusInfo usb_msd_scsi_info_storage = { + .tcq = false, + .max_target = 0, + .max_lun = 0, + + .transfer_data = usb_msd_transfer_data, + .complete = usb_msd_command_complete, + .cancel = usb_msd_request_cancelled, + .load_request = usb_msd_load_request, +}; + +static void usb_msd_storage_realize(USBDevice *dev, Error **errp) +{ + MSDState *s = USB_STORAGE_DEV(dev); + BlockBackend *blk = s->conf.blk; + SCSIDevice *scsi_dev; + + if (!blk) { + error_setg(errp, "drive property not set"); + return; + } + + if (!blkconf_blocksizes(&s->conf, errp)) { + return; + } + + if (!blkconf_apply_backend_options(&s->conf, !blk_supports_write_perm(blk), + true, errp)) { + return; + } + + /* + * Hack alert: this pretends to be a block device, but it's really + * a SCSI bus that can serve only a single device, which it + * creates automatically. But first it needs to detach from its + * blockdev, or else scsi_bus_legacy_add_drive() dies when it + * attaches again. We also need to take another reference so that + * blk_detach_dev() doesn't free blk while we still need it. + * + * The hack is probably a bad idea. + */ + blk_ref(blk); + blk_detach_dev(blk, DEVICE(s)); + s->conf.blk = NULL; + + usb_desc_create_serial(dev); + usb_desc_init(dev); + scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), + &usb_msd_scsi_info_storage, NULL); + scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable, + s->conf.bootindex, s->conf.share_rw, + s->conf.rerror, s->conf.werror, + dev->serial, + errp); + blk_unref(blk); + if (!scsi_dev) { + return; + } + usb_msd_handle_reset(dev); + s->scsi_dev = scsi_dev; +} + +static Property msd_properties[] = { + DEFINE_BLOCK_PROPERTIES(MSDState, conf), + DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf), + DEFINE_PROP_BOOL("removable", MSDState, removable, false), + DEFINE_PROP_BOOL("commandlog", MSDState, commandlog, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->realize = usb_msd_storage_realize; + device_class_set_props(dc, msd_properties); +} + +static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + USBDevice *dev = USB_DEVICE(obj); + MSDState *s = USB_STORAGE_DEV(dev); + + visit_type_int32(v, name, &s->conf.bootindex, errp); +} + +static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + USBDevice *dev = USB_DEVICE(obj); + MSDState *s = USB_STORAGE_DEV(dev); + int32_t boot_index; + Error *local_err = NULL; + + if (!visit_type_int32(v, name, &boot_index, errp)) { + return; + } + /* check whether bootindex is present in fw_boot_order list */ + check_boot_index(boot_index, &local_err); + if (local_err) { + goto out; + } + /* change bootindex to a new one */ + s->conf.bootindex = boot_index; + + if (s->scsi_dev) { + object_property_set_int(OBJECT(s->scsi_dev), "bootindex", boot_index, + &error_abort); + } + +out: + error_propagate(errp, local_err); +} + +static void usb_msd_instance_init(Object *obj) +{ + object_property_add(obj, "bootindex", "int32", + usb_msd_get_bootindex, + usb_msd_set_bootindex, NULL, NULL); + object_property_set_int(obj, "bootindex", -1, NULL); +} + +static const TypeInfo msd_info = { + .name = "usb-storage", + .parent = TYPE_USB_STORAGE, + .class_init = usb_msd_class_storage_initfn, + .instance_init = usb_msd_instance_init, +}; + +static void register_types(void) +{ + type_register_static(&msd_info); +} + +type_init(register_types) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index a5f76fc001..dca62d544f 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -14,13 +14,11 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "hw/usb.h" +#include "hw/usb/msd.h" #include "desc.h" #include "hw/qdev-properties.h" #include "hw/scsi/scsi.h" #include "migration/vmstate.h" -#include "sysemu/sysemu.h" -#include "sysemu/block-backend.h" -#include "qapi/visitor.h" #include "qemu/cutils.h" #include "qom/object.h" #include "trace.h" @@ -29,43 +27,6 @@ #define MassStorageReset 0xff #define GetMaxLun 0xfe -enum USBMSDMode { - USB_MSDM_CBW, /* Command Block. */ - USB_MSDM_DATAOUT, /* Transfer data to device. */ - USB_MSDM_DATAIN, /* Transfer data from device. */ - USB_MSDM_CSW /* Command Status. */ -}; - -struct usb_msd_csw { - uint32_t sig; - uint32_t tag; - uint32_t residue; - uint8_t status; -}; - -struct MSDState { - USBDevice dev; - enum USBMSDMode mode; - uint32_t scsi_off; - uint32_t scsi_len; - uint32_t data_len; - struct usb_msd_csw csw; - SCSIRequest *req; - SCSIBus bus; - /* For async completion. */ - USBPacket *packet; - /* usb-storage only */ - BlockConf conf; - bool removable; - bool commandlog; - SCSIDevice *scsi_dev; -}; -typedef struct MSDState MSDState; - -#define TYPE_USB_STORAGE "usb-storage-dev" -DECLARE_INSTANCE_CHECKER(MSDState, USB_STORAGE_DEV, - TYPE_USB_STORAGE) - struct usb_msd_cbw { uint32_t sig; uint32_t tag; @@ -259,7 +220,7 @@ static void usb_msd_packet_complete(MSDState *s) usb_packet_complete(&s->dev, p); } -static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) +void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) { MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); USBPacket *p = s->packet; @@ -277,7 +238,7 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) } } -static void usb_msd_command_complete(SCSIRequest *req, size_t resid) +void usb_msd_command_complete(SCSIRequest *req, size_t resid) { MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); USBPacket *p = s->packet; @@ -320,7 +281,7 @@ static void usb_msd_command_complete(SCSIRequest *req, size_t resid) s->req = NULL; } -static void usb_msd_request_cancelled(SCSIRequest *req) +void usb_msd_request_cancelled(SCSIRequest *req) { MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); @@ -337,7 +298,7 @@ static void usb_msd_request_cancelled(SCSIRequest *req) } } -static void usb_msd_handle_reset(USBDevice *dev) +void usb_msd_handle_reset(USBDevice *dev) { MSDState *s = (MSDState *)dev; @@ -352,6 +313,7 @@ static void usb_msd_handle_reset(USBDevice *dev) usb_msd_packet_complete(s); } + memset(&s->csw, 0, sizeof(s->csw)); s->mode = USB_MSDM_CBW; } @@ -565,7 +527,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) } } -static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req) +void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req) { MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); @@ -576,95 +538,6 @@ static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req) return NULL; } -static const struct SCSIBusInfo usb_msd_scsi_info_storage = { - .tcq = false, - .max_target = 0, - .max_lun = 0, - - .transfer_data = usb_msd_transfer_data, - .complete = usb_msd_command_complete, - .cancel = usb_msd_request_cancelled, - .load_request = usb_msd_load_request, -}; - -static const struct SCSIBusInfo usb_msd_scsi_info_bot = { - .tcq = false, - .max_target = 0, - .max_lun = 15, - - .transfer_data = usb_msd_transfer_data, - .complete = usb_msd_command_complete, - .cancel = usb_msd_request_cancelled, - .load_request = usb_msd_load_request, -}; - -static void usb_msd_storage_realize(USBDevice *dev, Error **errp) -{ - MSDState *s = USB_STORAGE_DEV(dev); - BlockBackend *blk = s->conf.blk; - SCSIDevice *scsi_dev; - - if (!blk) { - error_setg(errp, "drive property not set"); - return; - } - - if (!blkconf_blocksizes(&s->conf, errp)) { - return; - } - - if (!blkconf_apply_backend_options(&s->conf, !blk_supports_write_perm(blk), - true, errp)) { - return; - } - - /* - * Hack alert: this pretends to be a block device, but it's really - * a SCSI bus that can serve only a single device, which it - * creates automatically. But first it needs to detach from its - * blockdev, or else scsi_bus_legacy_add_drive() dies when it - * attaches again. We also need to take another reference so that - * blk_detach_dev() doesn't free blk while we still need it. - * - * The hack is probably a bad idea. - */ - blk_ref(blk); - blk_detach_dev(blk, DEVICE(s)); - s->conf.blk = NULL; - - usb_desc_create_serial(dev); - usb_desc_init(dev); - scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), - &usb_msd_scsi_info_storage, NULL); - scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable, - s->conf.bootindex, s->conf.share_rw, - s->conf.rerror, s->conf.werror, - dev->serial, - errp); - blk_unref(blk); - if (!scsi_dev) { - return; - } - usb_msd_handle_reset(dev); - s->scsi_dev = scsi_dev; -} - -static void usb_msd_bot_realize(USBDevice *dev, Error **errp) -{ - MSDState *s = USB_STORAGE_DEV(dev); - DeviceState *d = DEVICE(dev); - - usb_desc_create_serial(dev); - usb_desc_init(dev); - if (d->hotplugged) { - s->dev.auto_attach = 0; - } - - scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), - &usb_msd_scsi_info_bot, NULL); - usb_msd_handle_reset(dev); -} - static const VMStateDescription vmstate_usb_msd = { .name = "usb-storage", .version_id = 1, @@ -683,14 +556,6 @@ static const VMStateDescription vmstate_usb_msd = { } }; -static Property msd_properties[] = { - DEFINE_BLOCK_PROPERTIES(MSDState, conf), - DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf), - DEFINE_PROP_BOOL("removable", MSDState, removable, false), - DEFINE_PROP_BOOL("commandlog", MSDState, commandlog, false), - DEFINE_PROP_END_OF_LIST(), -}; - static void usb_msd_class_initfn_common(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -708,52 +573,6 @@ static void usb_msd_class_initfn_common(ObjectClass *klass, void *data) dc->vmsd = &vmstate_usb_msd; } -static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - - uc->realize = usb_msd_storage_realize; - device_class_set_props(dc, msd_properties); -} - -static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - USBDevice *dev = USB_DEVICE(obj); - MSDState *s = USB_STORAGE_DEV(dev); - - visit_type_int32(v, name, &s->conf.bootindex, errp); -} - -static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - USBDevice *dev = USB_DEVICE(obj); - MSDState *s = USB_STORAGE_DEV(dev); - int32_t boot_index; - Error *local_err = NULL; - - if (!visit_type_int32(v, name, &boot_index, errp)) { - return; - } - /* check whether bootindex is present in fw_boot_order list */ - check_boot_index(boot_index, &local_err); - if (local_err) { - goto out; - } - /* change bootindex to a new one */ - s->conf.bootindex = boot_index; - - if (s->scsi_dev) { - object_property_set_int(OBJECT(s->scsi_dev), "bootindex", boot_index, - &error_abort); - } - -out: - error_propagate(errp, local_err); -} - static const TypeInfo usb_storage_dev_type_info = { .name = TYPE_USB_STORAGE, .parent = TYPE_USB_DEVICE, @@ -762,40 +581,9 @@ static const TypeInfo usb_storage_dev_type_info = { .class_init = usb_msd_class_initfn_common, }; -static void usb_msd_instance_init(Object *obj) -{ - object_property_add(obj, "bootindex", "int32", - usb_msd_get_bootindex, - usb_msd_set_bootindex, NULL, NULL); - object_property_set_int(obj, "bootindex", -1, NULL); -} - -static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data) -{ - USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - - uc->realize = usb_msd_bot_realize; - uc->attached_settable = true; -} - -static const TypeInfo msd_info = { - .name = "usb-storage", - .parent = TYPE_USB_STORAGE, - .class_init = usb_msd_class_storage_initfn, - .instance_init = usb_msd_instance_init, -}; - -static const TypeInfo bot_info = { - .name = "usb-bot", - .parent = TYPE_USB_STORAGE, - .class_init = usb_msd_class_bot_initfn, -}; - static void usb_msd_register_types(void) { type_register_static(&usb_storage_dev_type_info); - type_register_static(&msd_info); - type_register_static(&bot_info); } type_init(usb_msd_register_types) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 5969eb86b3..0cb02a6432 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -40,6 +40,7 @@ #include "qemu/main-loop.h" #include "qemu/module.h" #include "qom/object.h" +#include "hcd-uhci.h" #define FRAME_TIMER_FREQ 1000 @@ -50,8 +51,6 @@ #define MAX_FRAMES_PER_TICK (QH_VALID / 2) -#define NB_PORTS 2 - enum { TD_RESULT_STOP_FRAME = 10, TD_RESULT_COMPLETE, @@ -62,20 +61,8 @@ enum { typedef struct UHCIState UHCIState; typedef struct UHCIAsync UHCIAsync; -typedef struct UHCIQueue UHCIQueue; -typedef struct UHCIInfo UHCIInfo; typedef struct UHCIPCIDeviceClass UHCIPCIDeviceClass; -struct UHCIInfo { - const char *name; - uint16_t vendor_id; - uint16_t device_id; - uint8_t revision; - uint8_t irq_pin; - void (*realize)(PCIDevice *dev, Error **errp); - bool unplug; -}; - struct UHCIPCIDeviceClass { PCIDeviceClass parent_class; UHCIInfo info; @@ -107,43 +94,6 @@ struct UHCIQueue { int8_t valid; }; -typedef struct UHCIPort { - USBPort port; - uint16_t ctrl; -} UHCIPort; - -struct UHCIState { - PCIDevice dev; - MemoryRegion io_bar; - USBBus bus; /* Note unused when we're a companion controller */ - uint16_t cmd; /* cmd register */ - uint16_t status; - uint16_t intr; /* interrupt enable register */ - uint16_t frnum; /* frame number */ - uint32_t fl_base_addr; /* frame list base address */ - uint8_t sof_timing; - uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */ - int64_t expire_time; - QEMUTimer *frame_timer; - QEMUBH *bh; - uint32_t frame_bytes; - uint32_t frame_bandwidth; - bool completions_only; - UHCIPort ports[NB_PORTS]; - - /* Interrupts that should be raised at the end of the current frame. */ - uint32_t pending_int_mask; - - /* Active packets */ - QTAILQ_HEAD(, UHCIQueue) queues; - uint8_t num_ports_vmstate; - - /* Properties */ - char *masterbus; - uint32_t firstport; - uint32_t maxframes; -}; - typedef struct UHCI_TD { uint32_t link; uint32_t ctrl; /* see TD_CTRL_xxx */ @@ -160,10 +110,6 @@ static void uhci_async_cancel(UHCIAsync *async); static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td); static void uhci_resume(void *opaque); -#define TYPE_UHCI "pci-uhci-usb" -DECLARE_INSTANCE_CHECKER(UHCIState, UHCI, - TYPE_UHCI) - static inline int32_t uhci_queue_token(UHCI_TD *td) { if ((td->token & (0xf << 15)) == 0) { @@ -1213,7 +1159,7 @@ static USBPortOps uhci_port_ops = { static USBBusOps uhci_bus_ops = { }; -static void usb_uhci_common_realize(PCIDevice *dev, Error **errp) +void usb_uhci_common_realize(PCIDevice *dev, Error **errp) { Error *err = NULL; PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); @@ -1261,21 +1207,6 @@ static void usb_uhci_common_realize(PCIDevice *dev, Error **errp) pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); } -static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp) -{ - UHCIState *s = UHCI(dev); - uint8_t *pci_conf = s->dev.config; - - /* USB misc control 1/2 */ - pci_set_long(pci_conf + 0x40,0x00001000); - /* PM capability */ - pci_set_long(pci_conf + 0x80,0x00020001); - /* USB legacy support */ - pci_set_long(pci_conf + 0xc0,0x00002000); - - usb_uhci_common_realize(dev, errp); -} - static void usb_uhci_exit(PCIDevice *dev) { UHCIState *s = UHCI(dev); @@ -1335,7 +1266,7 @@ static const TypeInfo uhci_pci_type_info = { }, }; -static void uhci_data_class_init(ObjectClass *klass, void *data) +void uhci_data_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); @@ -1373,14 +1304,6 @@ static UHCIInfo uhci_info[] = { .irq_pin = 3, .unplug = true, },{ - .name = "vt82c686b-usb-uhci", - .vendor_id = PCI_VENDOR_ID_VIA, - .device_id = PCI_DEVICE_ID_VIA_UHCI, - .revision = 0x01, - .irq_pin = 3, - .realize = usb_uhci_vt82c686b_realize, - .unplug = true, - },{ .name = "ich9-usb-uhci1", /* 00:1d.0 */ .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1, diff --git a/hw/usb/hcd-uhci.h b/hw/usb/hcd-uhci.h new file mode 100644 index 0000000000..e61d8fcb19 --- /dev/null +++ b/hw/usb/hcd-uhci.h @@ -0,0 +1,93 @@ +/* + * USB UHCI controller emulation + * + * Copyright (c) 2005 Fabrice Bellard + * + * Copyright (c) 2008 Max Krasnyansky + * Magor rewrite of the UHCI data structures parser and frame processor + * Support for fully async operation and multiple outstanding transactions + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef HW_USB_HCD_UHCI_H +#define HW_USB_HCD_UHCI_H + +#include "exec/memory.h" +#include "qemu/timer.h" +#include "hw/pci/pci.h" +#include "hw/usb.h" + +typedef struct UHCIQueue UHCIQueue; + +#define NB_PORTS 2 + +typedef struct UHCIPort { + USBPort port; + uint16_t ctrl; +} UHCIPort; + +typedef struct UHCIState { + PCIDevice dev; + MemoryRegion io_bar; + USBBus bus; /* Note unused when we're a companion controller */ + uint16_t cmd; /* cmd register */ + uint16_t status; + uint16_t intr; /* interrupt enable register */ + uint16_t frnum; /* frame number */ + uint32_t fl_base_addr; /* frame list base address */ + uint8_t sof_timing; + uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */ + int64_t expire_time; + QEMUTimer *frame_timer; + QEMUBH *bh; + uint32_t frame_bytes; + uint32_t frame_bandwidth; + bool completions_only; + UHCIPort ports[NB_PORTS]; + + /* Interrupts that should be raised at the end of the current frame. */ + uint32_t pending_int_mask; + + /* Active packets */ + QTAILQ_HEAD(, UHCIQueue) queues; + uint8_t num_ports_vmstate; + + /* Properties */ + char *masterbus; + uint32_t firstport; + uint32_t maxframes; +} UHCIState; + +#define TYPE_UHCI "pci-uhci-usb" +DECLARE_INSTANCE_CHECKER(UHCIState, UHCI, TYPE_UHCI) + +typedef struct UHCIInfo { + const char *name; + uint16_t vendor_id; + uint16_t device_id; + uint8_t revision; + uint8_t irq_pin; + void (*realize)(PCIDevice *dev, Error **errp); + bool unplug; +} UHCIInfo; + +void uhci_data_class_init(ObjectClass *klass, void *data); +void usb_uhci_common_realize(PCIDevice *dev, Error **errp); + +#endif diff --git a/hw/usb/meson.build b/hw/usb/meson.build index 653192cff6..fb7a74e73a 100644 --- a/hw/usb/meson.build +++ b/hw/usb/meson.build @@ -32,6 +32,7 @@ softmmu_ss.add(when: 'CONFIG_USB_DWC3', if_true: files('hcd-dwc3.c')) softmmu_ss.add(when: 'CONFIG_TUSB6010', if_true: files('tusb6010.c')) softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('chipidea.c')) softmmu_ss.add(when: 'CONFIG_IMX_USBPHY', if_true: files('imx-usb-phy.c')) +softmmu_ss.add(when: 'CONFIG_VT82C686', if_true: files('vt82c686-uhci-pci.c')) specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-usb2-ctrl-regs.c')) specific_ss.add(when: 'CONFIG_XLNX_USB_SUBSYS', if_true: files('xlnx-usb-subsystem.c')) @@ -39,7 +40,9 @@ specific_ss.add(when: 'CONFIG_XLNX_USB_SUBSYS', if_true: files('xlnx-usb-subsyst softmmu_ss.add(when: 'CONFIG_USB', if_true: files('dev-hub.c')) softmmu_ss.add(when: 'CONFIG_USB', if_true: files('dev-hid.c')) softmmu_ss.add(when: 'CONFIG_USB_TABLET_WACOM', if_true: files('dev-wacom.c')) -softmmu_ss.add(when: 'CONFIG_USB_STORAGE_BOT', if_true: files('dev-storage.c')) +softmmu_ss.add(when: 'CONFIG_USB_STORAGE_CORE', if_true: files('dev-storage.c')) +softmmu_ss.add(when: 'CONFIG_USB_STORAGE_BOT', if_true: files('dev-storage-bot.c')) +softmmu_ss.add(when: 'CONFIG_USB_STORAGE_CLASSIC', if_true: files('dev-storage-classic.c')) softmmu_ss.add(when: 'CONFIG_USB_STORAGE_UAS', if_true: files('dev-uas.c')) softmmu_ss.add(when: 'CONFIG_USB_AUDIO', if_true: files('dev-audio.c')) softmmu_ss.add(when: 'CONFIG_USB_SERIAL', if_true: files('dev-serial.c')) diff --git a/hw/usb/u2f.c b/hw/usb/u2f.c index bc09191f06..56001249a4 100644 --- a/hw/usb/u2f.c +++ b/hw/usb/u2f.c @@ -346,7 +346,6 @@ static const TypeInfo u2f_key_info = { static void u2f_key_register_types(void) { type_register_static(&u2f_key_info); - usb_legacy_register(TYPE_U2F_KEY, "u2f-key", NULL); } type_init(u2f_key_register_types) diff --git a/hw/usb/vt82c686-uhci-pci.c b/hw/usb/vt82c686-uhci-pci.c new file mode 100644 index 0000000000..b109c21603 --- /dev/null +++ b/hw/usb/vt82c686-uhci-pci.c @@ -0,0 +1,43 @@ +#include "qemu/osdep.h" +#include "hcd-uhci.h" + +static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp) +{ + UHCIState *s = UHCI(dev); + uint8_t *pci_conf = s->dev.config; + + /* USB misc control 1/2 */ + pci_set_long(pci_conf + 0x40, 0x00001000); + /* PM capability */ + pci_set_long(pci_conf + 0x80, 0x00020001); + /* USB legacy support */ + pci_set_long(pci_conf + 0xc0, 0x00002000); + + usb_uhci_common_realize(dev, errp); +} + +static UHCIInfo uhci_info[] = { + { + .name = "vt82c686b-usb-uhci", + .vendor_id = PCI_VENDOR_ID_VIA, + .device_id = PCI_DEVICE_ID_VIA_UHCI, + .revision = 0x01, + .irq_pin = 3, + .realize = usb_uhci_vt82c686b_realize, + .unplug = true, + } +}; + +static const TypeInfo vt82c686b_usb_uhci_type_info = { + .parent = TYPE_UHCI, + .name = "vt82c686b-usb-uhci", + .class_init = uhci_data_class_init, + .class_data = uhci_info, +}; + +static void vt82c686b_usb_uhci_register_types(void) +{ + type_register_static(&vt82c686b_usb_uhci_type_info); +} + +type_init(vt82c686b_usb_uhci_register_types) |