diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2017-05-30 14:15:09 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2017-05-30 14:15:10 +0100 |
commit | 697e42dec86d9ae706d4ed42c71acb5f35a463c8 (patch) | |
tree | 9a07c0d1490c761bb0165b2d0d1f4206b7870c49 | |
parent | a3203e7dd375d4f619b72b854fcb6d3f2d14bfef (diff) | |
parent | 3bfecee2cb71f21cd39d6183f18b446c01917573 (diff) | |
download | qemu-697e42dec86d9ae706d4ed42c71acb5f35a463c8.zip qemu-697e42dec86d9ae706d4ed42c71acb5f35a463c8.tar.gz qemu-697e42dec86d9ae706d4ed42c71acb5f35a463c8.tar.bz2 |
Merge remote-tracking branch 'kraxel/tags/pull-usb-20170529-1' into staging
usb: depricate legacy options and hmp commands
usb: fixes for ehci and hub, split xhci variants
# gpg: Signature made Mon 29 May 2017 02:07:17 PM BST
# gpg: using RSA key 0x4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138
* kraxel/tags/pull-usb-20170529-1:
ehci: fix frame timer invocation.
usb: don't wakeup during coldplug
usb-hub: set PORT_STAT_C_SUSPEND on host-initiated wake-up
xhci: add CONFIG_USB_XHCI_NEC option
xhci: split into multiple files
usb: Simplify the parameter parsing of the legacy usb serial device
usb: Deprecate HMP commands usb_add and usb_del
usb: Deprecate the legacy -usbdevice option
ehci: fix overflow in frame timer code
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | default-configs/pci.mak | 1 | ||||
-rw-r--r-- | hmp-commands.hx | 6 | ||||
-rw-r--r-- | hw/usb/Makefile.objs | 1 | ||||
-rw-r--r-- | hw/usb/core.c | 8 | ||||
-rw-r--r-- | hw/usb/dev-hub.c | 15 | ||||
-rw-r--r-- | hw/usb/dev-serial.c | 21 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.c | 15 | ||||
-rw-r--r-- | hw/usb/hcd-xhci-nec.c | 63 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 238 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.h | 226 | ||||
-rw-r--r-- | qemu-options.hx | 9 | ||||
-rw-r--r-- | vl.c | 8 |
12 files changed, 348 insertions, 263 deletions
diff --git a/default-configs/pci.mak b/default-configs/pci.mak index 60dc651..3bbeb62 100644 --- a/default-configs/pci.mak +++ b/default-configs/pci.mak @@ -7,6 +7,7 @@ CONFIG_USB_UHCI=y CONFIG_USB_OHCI=y CONFIG_USB_EHCI=y CONFIG_USB_XHCI=y +CONFIG_USB_XHCI_NEC=y CONFIG_NE2000_PCI=y CONFIG_EEPRO100_PCI=y CONFIG_PCNET_PCI=y diff --git a/hmp-commands.hx b/hmp-commands.hx index baeac47..e763606 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -676,7 +676,8 @@ ETEXI STEXI @item usb_add @var{devname} @findex usb_add -Add the USB device @var{devname}. For details of available devices see +Add the USB device @var{devname}. This command is deprecated, please +use @code{device_add} instead. For details of available devices see @ref{usb_devices} ETEXI @@ -693,7 +694,8 @@ STEXI @findex usb_del Remove the USB device @var{devname} from the QEMU virtual USB hub. @var{devname} has the syntax @code{bus.addr}. Use the monitor -command @code{info usb} to see the devices you can remove. +command @code{info usb} to see the devices you can remove. This +command is deprecated, please use @code{device_del} instead. ETEXI { diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 5958be8..97f1c456 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -8,6 +8,7 @@ common-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o hcd-ehci-pci.o common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o +common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o obj-$(CONFIG_TUSB6010) += tusb6010.o diff --git a/hw/usb/core.c b/hw/usb/core.c index 45fa00c..241ae66 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -98,6 +98,14 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream) USBDevice *dev = ep->dev; USBBus *bus = usb_bus_from_device(dev); + if (!qdev_hotplug) { + /* + * This is machine init cold plug. No need to wakeup anyone, + * all devices will be reset anyway. And trying to wakeup can + * cause problems due to hitting uninitialized devices. + */ + return; + } if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) { dev->port->ops->wakeup(dev->port); } diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 47b7519..e82a6a6 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -402,7 +402,20 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p, port->wPortChange &= ~PORT_STAT_C_ENABLE; break; case PORT_SUSPEND: - port->wPortStatus &= ~PORT_STAT_SUSPEND; + if (port->wPortStatus & PORT_STAT_SUSPEND) { + port->wPortStatus &= ~PORT_STAT_SUSPEND; + + /* + * USB Spec rev2.0 11.24.2.7.2.3 C_PORT_SUSPEND + * "This bit is set on the following transitions: + * - On transition from the Resuming state to the + * SendEOP [sic] state" + * + * Note that this includes both remote wake-up and + * explicit ClearPortFeature(PORT_SUSPEND). + */ + port->wPortChange |= PORT_STAT_C_SUSPEND; + } break; case PORT_C_SUSPEND: port->wPortChange &= ~PORT_STAT_C_SUSPEND; diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 83a4f0e..76ceca1 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -516,27 +516,16 @@ static USBDevice *usb_serial_init(USBBus *bus, const char *filename) char label[32]; static int index; - while (*filename && *filename != ':') { - const char *p; - - if (strstart(filename, "vendorid=", &p)) { - error_report("vendorid is not supported anymore"); - return NULL; - } else if (strstart(filename, "productid=", &p)) { - error_report("productid is not supported anymore"); - return NULL; - } else { - error_report("unrecognized serial USB option %s", filename); - return NULL; - } - while(*filename == ',') - filename++; + if (*filename == ':') { + filename++; + } else if (*filename) { + error_report("unrecognized serial USB option %s", filename); + return NULL; } if (!*filename) { error_report("character device specification needed"); return NULL; } - filename++; snprintf(label, sizeof(label), "usbserial%d", index++); cdrv = qemu_chr_new(label, filename); diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 50ef817..17c572c 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2232,13 +2232,13 @@ static void ehci_update_frindex(EHCIState *ehci, int uframes) ehci->frindex = (ehci->frindex + uframes) % 0x4000; } -static void ehci_frame_timer(void *opaque) +static void ehci_work_bh(void *opaque) { EHCIState *ehci = opaque; int need_timer = 0; int64_t expire_time, t_now; uint64_t ns_elapsed; - int uframes, skipped_uframes; + uint64_t uframes, skipped_uframes; int i; t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -2324,6 +2324,13 @@ static void ehci_frame_timer(void *opaque) } } +static void ehci_work_timer(void *opaque) +{ + EHCIState *ehci = opaque; + + qemu_bh_schedule(ehci->async_bh); +} + static const MemoryRegionOps ehci_mmio_caps_ops = { .read = ehci_caps_read, .write = ehci_caps_write, @@ -2478,8 +2485,8 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp) s->ports[i].dev = 0; } - s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_frame_timer, s); - s->async_bh = qemu_bh_new(ehci_frame_timer, s); + s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_work_timer, s); + s->async_bh = qemu_bh_new(ehci_work_bh, s); s->device = dev; s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); diff --git a/hw/usb/hcd-xhci-nec.c b/hw/usb/hcd-xhci-nec.c new file mode 100644 index 0000000..75715a0 --- /dev/null +++ b/hw/usb/hcd-xhci-nec.c @@ -0,0 +1,63 @@ +/* + * USB xHCI controller emulation + * + * Copyright (c) 2011 Securiforest + * Date: 2011-05-11 ; Author: Hector Martin <hector@marcansoft.com> + * Based on usb-ohci.c, emulates Renesas NEC USB 3.0 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "hw/usb.h" +#include "hw/pci/pci.h" + +#include "hcd-xhci.h" + +static Property nec_xhci_properties[] = { + DEFINE_PROP_ON_OFF_AUTO("msi", XHCIState, msi, ON_OFF_AUTO_AUTO), + DEFINE_PROP_ON_OFF_AUTO("msix", XHCIState, msix, ON_OFF_AUTO_AUTO), + DEFINE_PROP_BIT("superspeed-ports-first", + XHCIState, flags, XHCI_FLAG_SS_FIRST, true), + DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags, + XHCI_FLAG_FORCE_PCIE_ENDCAP, false), + DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS), + DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS), + DEFINE_PROP_END_OF_LIST(), +}; + +static void nec_xhci_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->props = nec_xhci_properties; + k->vendor_id = PCI_VENDOR_ID_NEC; + k->device_id = PCI_DEVICE_ID_NEC_UPD720200; + k->revision = 0x03; +} + +static const TypeInfo nec_xhci_info = { + .name = TYPE_NEC_XHCI, + .parent = TYPE_XHCI, + .class_init = nec_xhci_class_init, +}; + +static void nec_xhci_register_types(void) +{ + type_register_static(&nec_xhci_info); +} + +type_init(nec_xhci_register_types) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 77d8e11..a0c7960 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -29,6 +29,8 @@ #include "trace.h" #include "qapi/error.h" +#include "hcd-xhci.h" + //#define DEBUG_XHCI //#define DEBUG_DATA @@ -40,16 +42,6 @@ #define FIXME(_msg) do { fprintf(stderr, "FIXME %s:%d %s\n", \ __func__, __LINE__, _msg); abort(); } while (0) -#define MAXPORTS_2 15 -#define MAXPORTS_3 15 - -#define MAXPORTS (MAXPORTS_2+MAXPORTS_3) -#define MAXSLOTS 64 -#define MAXINTRS 16 - -/* Very pessimistic, let's hope it's enough for all cases */ -#define EV_QUEUE (((3 * 24) + 16) * MAXSLOTS) - #define TRB_LINK_LIMIT 32 #define COMMAND_LIMIT 256 #define TRANSFER_LIMIT 256 @@ -164,84 +156,8 @@ enum { PLS_RESUME = 15, }; -typedef enum TRBType { - TRB_RESERVED = 0, - TR_NORMAL, - TR_SETUP, - TR_DATA, - TR_STATUS, - TR_ISOCH, - TR_LINK, - TR_EVDATA, - TR_NOOP, - CR_ENABLE_SLOT, - CR_DISABLE_SLOT, - CR_ADDRESS_DEVICE, - CR_CONFIGURE_ENDPOINT, - CR_EVALUATE_CONTEXT, - CR_RESET_ENDPOINT, - CR_STOP_ENDPOINT, - CR_SET_TR_DEQUEUE, - CR_RESET_DEVICE, - CR_FORCE_EVENT, - CR_NEGOTIATE_BW, - CR_SET_LATENCY_TOLERANCE, - CR_GET_PORT_BANDWIDTH, - CR_FORCE_HEADER, - CR_NOOP, - ER_TRANSFER = 32, - ER_COMMAND_COMPLETE, - ER_PORT_STATUS_CHANGE, - ER_BANDWIDTH_REQUEST, - ER_DOORBELL, - ER_HOST_CONTROLLER, - ER_DEVICE_NOTIFICATION, - ER_MFINDEX_WRAP, - /* vendor specific bits */ - CR_VENDOR_NEC_FIRMWARE_REVISION = 49, - CR_VENDOR_NEC_CHALLENGE_RESPONSE = 50, -} TRBType; - #define CR_LINK TR_LINK -typedef enum TRBCCode { - CC_INVALID = 0, - CC_SUCCESS, - CC_DATA_BUFFER_ERROR, - CC_BABBLE_DETECTED, - CC_USB_TRANSACTION_ERROR, - CC_TRB_ERROR, - CC_STALL_ERROR, - CC_RESOURCE_ERROR, - CC_BANDWIDTH_ERROR, - CC_NO_SLOTS_ERROR, - CC_INVALID_STREAM_TYPE_ERROR, - CC_SLOT_NOT_ENABLED_ERROR, - CC_EP_NOT_ENABLED_ERROR, - CC_SHORT_PACKET, - CC_RING_UNDERRUN, - CC_RING_OVERRUN, - CC_VF_ER_FULL, - CC_PARAMETER_ERROR, - CC_BANDWIDTH_OVERRUN, - CC_CONTEXT_STATE_ERROR, - CC_NO_PING_RESPONSE_ERROR, - CC_EVENT_RING_FULL_ERROR, - CC_INCOMPATIBLE_DEVICE_ERROR, - CC_MISSED_SERVICE_ERROR, - CC_COMMAND_RING_STOPPED, - CC_COMMAND_ABORTED, - CC_STOPPED, - CC_STOPPED_LENGTH_INVALID, - CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29, - CC_ISOCH_BUFFER_OVERRUN = 31, - CC_EVENT_LOST_ERROR, - CC_UNDEFINED_ERROR, - CC_INVALID_STREAM_ID_ERROR, - CC_SECONDARY_BANDWIDTH_ERROR, - CC_SPLIT_TRANSACTION_ERROR -} TRBCCode; - #define TRB_C (1<<0) #define TRB_TYPE_SHIFT 10 #define TRB_TYPE_MASK 0x3f @@ -301,10 +217,6 @@ typedef enum TRBCCode { #define SLOT_CONTEXT_ENTRIES_MASK 0x1f #define SLOT_CONTEXT_ENTRIES_SHIFT 27 -typedef struct XHCIState XHCIState; -typedef struct XHCIStreamContext XHCIStreamContext; -typedef struct XHCIEPContext XHCIEPContext; - #define get_field(data, field) \ (((data) >> field##_SHIFT) & field##_MASK) @@ -326,21 +238,6 @@ typedef enum EPType { ET_INTR_IN, } EPType; -typedef struct XHCIRing { - dma_addr_t dequeue; - bool ccs; -} XHCIRing; - -typedef struct XHCIPort { - XHCIState *xhci; - uint32_t portsc; - uint32_t portnr; - USBPort *uport; - uint32_t speedmask; - char name[16]; - MemoryRegion mem; -} XHCIPort; - typedef struct XHCITransfer { XHCIEPContext *epctx; USBPacket packet; @@ -402,101 +299,6 @@ struct XHCIEPContext { QEMUTimer *kick_timer; }; -typedef struct XHCISlot { - bool enabled; - bool addressed; - dma_addr_t ctx; - USBPort *uport; - XHCIEPContext * eps[31]; -} XHCISlot; - -typedef struct XHCIEvent { - TRBType type; - TRBCCode ccode; - uint64_t ptr; - uint32_t length; - uint32_t flags; - uint8_t slotid; - uint8_t epid; -} XHCIEvent; - -typedef struct XHCIInterrupter { - uint32_t iman; - uint32_t imod; - uint32_t erstsz; - uint32_t erstba_low; - uint32_t erstba_high; - uint32_t erdp_low; - uint32_t erdp_high; - - bool msix_used, er_pcs; - - dma_addr_t er_start; - uint32_t er_size; - unsigned int er_ep_idx; - - /* kept for live migration compat only */ - bool er_full_unused; - XHCIEvent ev_buffer[EV_QUEUE]; - unsigned int ev_buffer_put; - unsigned int ev_buffer_get; - -} XHCIInterrupter; - -struct XHCIState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - USBBus bus; - MemoryRegion mem; - MemoryRegion mem_cap; - MemoryRegion mem_oper; - MemoryRegion mem_runtime; - MemoryRegion mem_doorbell; - - /* properties */ - uint32_t numports_2; - uint32_t numports_3; - uint32_t numintrs; - uint32_t numslots; - uint32_t flags; - uint32_t max_pstreams_mask; - OnOffAuto msi; - OnOffAuto msix; - - /* Operational Registers */ - uint32_t usbcmd; - uint32_t usbsts; - uint32_t dnctrl; - uint32_t crcr_low; - uint32_t crcr_high; - uint32_t dcbaap_low; - uint32_t dcbaap_high; - uint32_t config; - - USBPort uports[MAX(MAXPORTS_2, MAXPORTS_3)]; - XHCIPort ports[MAXPORTS]; - XHCISlot slots[MAXSLOTS]; - uint32_t numports; - - /* Runtime Registers */ - int64_t mfindex_start; - QEMUTimer *mfwrap_timer; - XHCIInterrupter intr[MAXINTRS]; - - XHCIRing cmd_ring; - - bool nec_quirks; -}; - -#define TYPE_XHCI "base-xhci" -#define TYPE_NEC_XHCI "nec-usb-xhci" -#define TYPE_QEMU_XHCI "qemu-xhci" - -#define XHCI(obj) \ - OBJECT_CHECK(XHCIState, (obj), TYPE_XHCI) - typedef struct XHCIEvRingSeg { uint32_t addr_low; uint32_t addr_high; @@ -504,12 +306,6 @@ typedef struct XHCIEvRingSeg { uint32_t rsvd; } XHCIEvRingSeg; -enum xhci_flags { - XHCI_FLAG_SS_FIRST = 1, - XHCI_FLAG_FORCE_PCIE_ENDCAP, - XHCI_FLAG_ENABLE_STREAMS, -}; - static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid, unsigned int streamid); static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid); @@ -3843,18 +3639,6 @@ static const VMStateDescription vmstate_xhci = { } }; -static Property nec_xhci_properties[] = { - DEFINE_PROP_ON_OFF_AUTO("msi", XHCIState, msi, ON_OFF_AUTO_AUTO), - DEFINE_PROP_ON_OFF_AUTO("msix", XHCIState, msix, ON_OFF_AUTO_AUTO), - DEFINE_PROP_BIT("superspeed-ports-first", - XHCIState, flags, XHCI_FLAG_SS_FIRST, true), - DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags, - XHCI_FLAG_FORCE_PCIE_ENDCAP, false), - DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS), - DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS), - DEFINE_PROP_END_OF_LIST(), -}; - static Property xhci_properties[] = { DEFINE_PROP_BIT("streams", XHCIState, flags, XHCI_FLAG_ENABLE_STREAMS, true), @@ -3886,23 +3670,6 @@ static const TypeInfo xhci_info = { .abstract = true, }; -static void nec_xhci_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->props = nec_xhci_properties; - k->vendor_id = PCI_VENDOR_ID_NEC; - k->device_id = PCI_DEVICE_ID_NEC_UPD720200; - k->revision = 0x03; -} - -static const TypeInfo nec_xhci_info = { - .name = TYPE_NEC_XHCI, - .parent = TYPE_XHCI, - .class_init = nec_xhci_class_init, -}; - static void qemu_xhci_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); @@ -3933,7 +3700,6 @@ static const TypeInfo qemu_xhci_info = { static void xhci_register_types(void) { type_register_static(&xhci_info); - type_register_static(&nec_xhci_info); type_register_static(&qemu_xhci_info); } diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h new file mode 100644 index 0000000..fc36a4c --- /dev/null +++ b/hw/usb/hcd-xhci.h @@ -0,0 +1,226 @@ +/* + * USB xHCI controller emulation + * + * Copyright (c) 2011 Securiforest + * Date: 2011-05-11 ; Author: Hector Martin <hector@marcansoft.com> + * Based on usb-ohci.c, emulates Renesas NEC USB 3.0 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#define TYPE_XHCI "base-xhci" +#define TYPE_NEC_XHCI "nec-usb-xhci" +#define TYPE_QEMU_XHCI "qemu-xhci" + +#define XHCI(obj) \ + OBJECT_CHECK(XHCIState, (obj), TYPE_XHCI) + +#define MAXPORTS_2 15 +#define MAXPORTS_3 15 + +#define MAXPORTS (MAXPORTS_2 + MAXPORTS_3) +#define MAXSLOTS 64 +#define MAXINTRS 16 + +/* Very pessimistic, let's hope it's enough for all cases */ +#define EV_QUEUE (((3 * 24) + 16) * MAXSLOTS) + +typedef struct XHCIState XHCIState; +typedef struct XHCIStreamContext XHCIStreamContext; +typedef struct XHCIEPContext XHCIEPContext; + +enum xhci_flags { + XHCI_FLAG_SS_FIRST = 1, + XHCI_FLAG_FORCE_PCIE_ENDCAP, + XHCI_FLAG_ENABLE_STREAMS, +}; + +typedef enum TRBType { + TRB_RESERVED = 0, + TR_NORMAL, + TR_SETUP, + TR_DATA, + TR_STATUS, + TR_ISOCH, + TR_LINK, + TR_EVDATA, + TR_NOOP, + CR_ENABLE_SLOT, + CR_DISABLE_SLOT, + CR_ADDRESS_DEVICE, + CR_CONFIGURE_ENDPOINT, + CR_EVALUATE_CONTEXT, + CR_RESET_ENDPOINT, + CR_STOP_ENDPOINT, + CR_SET_TR_DEQUEUE, + CR_RESET_DEVICE, + CR_FORCE_EVENT, + CR_NEGOTIATE_BW, + CR_SET_LATENCY_TOLERANCE, + CR_GET_PORT_BANDWIDTH, + CR_FORCE_HEADER, + CR_NOOP, + ER_TRANSFER = 32, + ER_COMMAND_COMPLETE, + ER_PORT_STATUS_CHANGE, + ER_BANDWIDTH_REQUEST, + ER_DOORBELL, + ER_HOST_CONTROLLER, + ER_DEVICE_NOTIFICATION, + ER_MFINDEX_WRAP, + /* vendor specific bits */ + CR_VENDOR_NEC_FIRMWARE_REVISION = 49, + CR_VENDOR_NEC_CHALLENGE_RESPONSE = 50, +} TRBType; + +typedef enum TRBCCode { + CC_INVALID = 0, + CC_SUCCESS, + CC_DATA_BUFFER_ERROR, + CC_BABBLE_DETECTED, + CC_USB_TRANSACTION_ERROR, + CC_TRB_ERROR, + CC_STALL_ERROR, + CC_RESOURCE_ERROR, + CC_BANDWIDTH_ERROR, + CC_NO_SLOTS_ERROR, + CC_INVALID_STREAM_TYPE_ERROR, + CC_SLOT_NOT_ENABLED_ERROR, + CC_EP_NOT_ENABLED_ERROR, + CC_SHORT_PACKET, + CC_RING_UNDERRUN, + CC_RING_OVERRUN, + CC_VF_ER_FULL, + CC_PARAMETER_ERROR, + CC_BANDWIDTH_OVERRUN, + CC_CONTEXT_STATE_ERROR, + CC_NO_PING_RESPONSE_ERROR, + CC_EVENT_RING_FULL_ERROR, + CC_INCOMPATIBLE_DEVICE_ERROR, + CC_MISSED_SERVICE_ERROR, + CC_COMMAND_RING_STOPPED, + CC_COMMAND_ABORTED, + CC_STOPPED, + CC_STOPPED_LENGTH_INVALID, + CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29, + CC_ISOCH_BUFFER_OVERRUN = 31, + CC_EVENT_LOST_ERROR, + CC_UNDEFINED_ERROR, + CC_INVALID_STREAM_ID_ERROR, + CC_SECONDARY_BANDWIDTH_ERROR, + CC_SPLIT_TRANSACTION_ERROR +} TRBCCode; + +typedef struct XHCIRing { + dma_addr_t dequeue; + bool ccs; +} XHCIRing; + +typedef struct XHCIPort { + XHCIState *xhci; + uint32_t portsc; + uint32_t portnr; + USBPort *uport; + uint32_t speedmask; + char name[16]; + MemoryRegion mem; +} XHCIPort; + +typedef struct XHCISlot { + bool enabled; + bool addressed; + dma_addr_t ctx; + USBPort *uport; + XHCIEPContext *eps[31]; +} XHCISlot; + +typedef struct XHCIEvent { + TRBType type; + TRBCCode ccode; + uint64_t ptr; + uint32_t length; + uint32_t flags; + uint8_t slotid; + uint8_t epid; +} XHCIEvent; + +typedef struct XHCIInterrupter { + uint32_t iman; + uint32_t imod; + uint32_t erstsz; + uint32_t erstba_low; + uint32_t erstba_high; + uint32_t erdp_low; + uint32_t erdp_high; + + bool msix_used, er_pcs; + + dma_addr_t er_start; + uint32_t er_size; + unsigned int er_ep_idx; + + /* kept for live migration compat only */ + bool er_full_unused; + XHCIEvent ev_buffer[EV_QUEUE]; + unsigned int ev_buffer_put; + unsigned int ev_buffer_get; + +} XHCIInterrupter; + +struct XHCIState { + /*< private >*/ + PCIDevice parent_obj; + /*< public >*/ + + USBBus bus; + MemoryRegion mem; + MemoryRegion mem_cap; + MemoryRegion mem_oper; + MemoryRegion mem_runtime; + MemoryRegion mem_doorbell; + + /* properties */ + uint32_t numports_2; + uint32_t numports_3; + uint32_t numintrs; + uint32_t numslots; + uint32_t flags; + uint32_t max_pstreams_mask; + OnOffAuto msi; + OnOffAuto msix; + + /* Operational Registers */ + uint32_t usbcmd; + uint32_t usbsts; + uint32_t dnctrl; + uint32_t crcr_low; + uint32_t crcr_high; + uint32_t dcbaap_low; + uint32_t dcbaap_high; + uint32_t config; + + USBPort uports[MAX(MAXPORTS_2, MAXPORTS_3)]; + XHCIPort ports[MAXPORTS]; + XHCISlot slots[MAXSLOTS]; + uint32_t numports; + + /* Runtime Registers */ + int64_t mfindex_start; + QEMUTimer *mfwrap_timer; + XHCIInterrupter intr[MAXINTRS]; + + XHCIRing cmd_ring; + + bool nec_quirks; +}; diff --git a/qemu-options.hx b/qemu-options.hx index 0c67319..a6c9b9e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -984,12 +984,12 @@ STEXI ETEXI DEF("usb", 0, QEMU_OPTION_usb, - "-usb enable the USB driver (will be the default soon)\n", + "-usb enable the USB driver (if it is not used by default yet)\n", QEMU_ARCH_ALL) STEXI @item -usb @findex -usb -Enable the USB driver (will be the default soon) +Enable the USB driver (if it is not used by default yet). ETEXI DEF("usbdevice", HAS_ARG, QEMU_OPTION_usbdevice, @@ -999,7 +999,8 @@ STEXI @item -usbdevice @var{devname} @findex -usbdevice -Add the USB device @var{devname}. @xref{usb_devices}. +Add the USB device @var{devname}. Note that this option is deprecated, +please use @code{-device usb-...} instead. @xref{usb_devices}. @table @option @@ -1377,7 +1378,7 @@ output such as guest graphics, guest console, and the QEMU monitor in a window. With this option, you can have QEMU listen on VNC display @var{display} and redirect the VGA display over the VNC session. It is very useful to enable the usb tablet device when using this option -(option @option{-usbdevice tablet}). When using the VNC display, you +(option @option{-device usb-tablet}). When using the VNC display, you must use the @option{-k} parameter to set the keyboard layout if you are not using en-us. Valid syntax for the @var{display} is @@ -1436,6 +1436,9 @@ static int usb_parse(const char *cmdline) void hmp_usb_add(Monitor *mon, const QDict *qdict) { const char *devname = qdict_get_str(qdict, "devname"); + + error_report("usb_add is deprecated, please use device_add instead"); + if (usb_device_add(devname) < 0) { error_report("could not add USB device '%s'", devname); } @@ -1444,6 +1447,9 @@ void hmp_usb_add(Monitor *mon, const QDict *qdict) void hmp_usb_del(Monitor *mon, const QDict *qdict) { const char *devname = qdict_get_str(qdict, "devname"); + + error_report("usb_del is deprecated, please use device_del instead"); + if (usb_device_del(devname) < 0) { error_report("could not delete USB device '%s'", devname); } @@ -3770,6 +3776,8 @@ int main(int argc, char **argv, char **envp) qemu_opts_parse_noisily(olist, "usb=on", false); break; case QEMU_OPTION_usbdevice: + error_report("'-usbdevice' is deprecated, please use " + "'-device usb-...' instead"); olist = qemu_find_opts("machine"); qemu_opts_parse_noisily(olist, "usb=on", false); add_device_config(DEV_USB, optarg); |