usb: depricate legacy options and hmp commands

usb: fixes for ehci and hub, split xhci variants
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJZLB0FAAoJEEy22O7T6HE4VPcP/jGMAyulKQvzqbj4vbGT6gFJ
 Gul2dIMHE2f2O/LbfBvbMX1hySXCfXaoNrIVwoHll+o7mojjG8Jcc7kZ13XhhMZO
 qAPNNnDQTsL2SrixBKfa+EqQd3d3D4tJrnle8XyRckhsSevkE28/kt+ob3GW0lcV
 ayRVu+GwnWEI8oUC/+ukK+7OrhV8hW4zOkKzyH0DKqXO/GexywkhWwtVXy3vPx0u
 AZ2uuzcwzH6cxiCpukW6RcGPYQSNeedGejhtmPuZ9Vh3fYCOi9Fcsww0TDPbook0
 QmLea+DRPXIAk+lh9uVpdpQx8b9zDMbNXtgmQup9mPW8a5AGqYww/GoXfuIPjqGp
 1p5xGtqjwHr+V5R2rMnCHCPNqoov31bDzuWFdD2+Ej3xHS+CBnj/+05293umByuA
 j38o7pveG5jRt+Bu6zhiUs4pZbnmNUmMAINeaKWu7qmc5X5/VQvxGwTMkNrTktp8
 lrTIDZxWNw3jT42/ILjhqFdQw18tQXVi6/45JWNfQgwsWTKB0w7Xj6Gfhn4eE/Dy
 SpdTJkaqfkLmqKWnqhSy5ka5KBDzk+neEC7g7cocxLhP0fdtwQao+BB61alrTGvJ
 trKcQ3EgKxLzg3WGaYDZBIESBPjJlGmKelV+ZIUFf/yZxFTDLps33Fm9HSXvygFz
 UVdV4AtYRsPxNWB3jUqE
 =nhKy
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Stefan Hajnoczi 2017-05-30 14:15:09 +01:00
commit 697e42dec8
12 changed files with 348 additions and 263 deletions

View File

@ -7,6 +7,7 @@ CONFIG_USB_UHCI=y
CONFIG_USB_OHCI=y CONFIG_USB_OHCI=y
CONFIG_USB_EHCI=y CONFIG_USB_EHCI=y
CONFIG_USB_XHCI=y CONFIG_USB_XHCI=y
CONFIG_USB_XHCI_NEC=y
CONFIG_NE2000_PCI=y CONFIG_NE2000_PCI=y
CONFIG_EEPRO100_PCI=y CONFIG_EEPRO100_PCI=y
CONFIG_PCNET_PCI=y CONFIG_PCNET_PCI=y

View File

@ -676,7 +676,8 @@ ETEXI
STEXI STEXI
@item usb_add @var{devname} @item usb_add @var{devname}
@findex usb_add @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} @ref{usb_devices}
ETEXI ETEXI
@ -693,7 +694,8 @@ STEXI
@findex usb_del @findex usb_del
Remove the USB device @var{devname} from the QEMU virtual USB Remove the USB device @var{devname} from the QEMU virtual USB
hub. @var{devname} has the syntax @code{bus.addr}. Use the monitor 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 ETEXI
{ {

View File

@ -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) += hcd-ehci.o hcd-ehci-pci.o
common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o
common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.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 common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
obj-$(CONFIG_TUSB6010) += tusb6010.o obj-$(CONFIG_TUSB6010) += tusb6010.o

View File

@ -98,6 +98,14 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream)
USBDevice *dev = ep->dev; USBDevice *dev = ep->dev;
USBBus *bus = usb_bus_from_device(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) { if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
dev->port->ops->wakeup(dev->port); dev->port->ops->wakeup(dev->port);
} }

View File

@ -402,7 +402,20 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
port->wPortChange &= ~PORT_STAT_C_ENABLE; port->wPortChange &= ~PORT_STAT_C_ENABLE;
break; break;
case PORT_SUSPEND: 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; break;
case PORT_C_SUSPEND: case PORT_C_SUSPEND:
port->wPortChange &= ~PORT_STAT_C_SUSPEND; port->wPortChange &= ~PORT_STAT_C_SUSPEND;

View File

@ -516,27 +516,16 @@ static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
char label[32]; char label[32];
static int index; static int index;
while (*filename && *filename != ':') { if (*filename == ':') {
const char *p; filename++;
} else if (*filename) {
if (strstart(filename, "vendorid=", &p)) { error_report("unrecognized serial USB option %s", filename);
error_report("vendorid is not supported anymore"); return NULL;
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) { if (!*filename) {
error_report("character device specification needed"); error_report("character device specification needed");
return NULL; return NULL;
} }
filename++;
snprintf(label, sizeof(label), "usbserial%d", index++); snprintf(label, sizeof(label), "usbserial%d", index++);
cdrv = qemu_chr_new(label, filename); cdrv = qemu_chr_new(label, filename);

View File

@ -2232,13 +2232,13 @@ static void ehci_update_frindex(EHCIState *ehci, int uframes)
ehci->frindex = (ehci->frindex + uframes) % 0x4000; ehci->frindex = (ehci->frindex + uframes) % 0x4000;
} }
static void ehci_frame_timer(void *opaque) static void ehci_work_bh(void *opaque)
{ {
EHCIState *ehci = opaque; EHCIState *ehci = opaque;
int need_timer = 0; int need_timer = 0;
int64_t expire_time, t_now; int64_t expire_time, t_now;
uint64_t ns_elapsed; uint64_t ns_elapsed;
int uframes, skipped_uframes; uint64_t uframes, skipped_uframes;
int i; int i;
t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 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 = { static const MemoryRegionOps ehci_mmio_caps_ops = {
.read = ehci_caps_read, .read = ehci_caps_read,
.write = ehci_caps_write, .write = ehci_caps_write,
@ -2478,8 +2485,8 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp)
s->ports[i].dev = 0; s->ports[i].dev = 0;
} }
s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_frame_timer, s); s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_work_timer, s);
s->async_bh = qemu_bh_new(ehci_frame_timer, s); s->async_bh = qemu_bh_new(ehci_work_bh, s);
s->device = dev; s->device = dev;
s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);

63
hw/usb/hcd-xhci-nec.c Normal file
View File

@ -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)

View File

@ -29,6 +29,8 @@
#include "trace.h" #include "trace.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "hcd-xhci.h"
//#define DEBUG_XHCI //#define DEBUG_XHCI
//#define DEBUG_DATA //#define DEBUG_DATA
@ -40,16 +42,6 @@
#define FIXME(_msg) do { fprintf(stderr, "FIXME %s:%d %s\n", \ #define FIXME(_msg) do { fprintf(stderr, "FIXME %s:%d %s\n", \
__func__, __LINE__, _msg); abort(); } while (0) __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 TRB_LINK_LIMIT 32
#define COMMAND_LIMIT 256 #define COMMAND_LIMIT 256
#define TRANSFER_LIMIT 256 #define TRANSFER_LIMIT 256
@ -164,84 +156,8 @@ enum {
PLS_RESUME = 15, 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 #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_C (1<<0)
#define TRB_TYPE_SHIFT 10 #define TRB_TYPE_SHIFT 10
#define TRB_TYPE_MASK 0x3f #define TRB_TYPE_MASK 0x3f
@ -301,10 +217,6 @@ typedef enum TRBCCode {
#define SLOT_CONTEXT_ENTRIES_MASK 0x1f #define SLOT_CONTEXT_ENTRIES_MASK 0x1f
#define SLOT_CONTEXT_ENTRIES_SHIFT 27 #define SLOT_CONTEXT_ENTRIES_SHIFT 27
typedef struct XHCIState XHCIState;
typedef struct XHCIStreamContext XHCIStreamContext;
typedef struct XHCIEPContext XHCIEPContext;
#define get_field(data, field) \ #define get_field(data, field) \
(((data) >> field##_SHIFT) & field##_MASK) (((data) >> field##_SHIFT) & field##_MASK)
@ -326,21 +238,6 @@ typedef enum EPType {
ET_INTR_IN, ET_INTR_IN,
} EPType; } 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 { typedef struct XHCITransfer {
XHCIEPContext *epctx; XHCIEPContext *epctx;
USBPacket packet; USBPacket packet;
@ -402,101 +299,6 @@ struct XHCIEPContext {
QEMUTimer *kick_timer; 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 { typedef struct XHCIEvRingSeg {
uint32_t addr_low; uint32_t addr_low;
uint32_t addr_high; uint32_t addr_high;
@ -504,12 +306,6 @@ typedef struct XHCIEvRingSeg {
uint32_t rsvd; uint32_t rsvd;
} XHCIEvRingSeg; } 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, static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
unsigned int epid, unsigned int streamid); unsigned int epid, unsigned int streamid);
static void xhci_kick_epctx(XHCIEPContext *epctx, 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[] = { static Property xhci_properties[] = {
DEFINE_PROP_BIT("streams", XHCIState, flags, DEFINE_PROP_BIT("streams", XHCIState, flags,
XHCI_FLAG_ENABLE_STREAMS, true), XHCI_FLAG_ENABLE_STREAMS, true),
@ -3886,23 +3670,6 @@ static const TypeInfo xhci_info = {
.abstract = true, .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) static void qemu_xhci_class_init(ObjectClass *klass, void *data)
{ {
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
@ -3933,7 +3700,6 @@ static const TypeInfo qemu_xhci_info = {
static void xhci_register_types(void) static void xhci_register_types(void)
{ {
type_register_static(&xhci_info); type_register_static(&xhci_info);
type_register_static(&nec_xhci_info);
type_register_static(&qemu_xhci_info); type_register_static(&qemu_xhci_info);
} }

226
hw/usb/hcd-xhci.h Normal file
View File

@ -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;
};

View File

@ -984,12 +984,12 @@ STEXI
ETEXI ETEXI
DEF("usb", 0, QEMU_OPTION_usb, 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) QEMU_ARCH_ALL)
STEXI STEXI
@item -usb @item -usb
@findex -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 ETEXI
DEF("usbdevice", HAS_ARG, QEMU_OPTION_usbdevice, DEF("usbdevice", HAS_ARG, QEMU_OPTION_usbdevice,
@ -999,7 +999,8 @@ STEXI
@item -usbdevice @var{devname} @item -usbdevice @var{devname}
@findex -usbdevice @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 @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 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 @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 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 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 not using en-us. Valid syntax for the @var{display} is

8
vl.c
View File

@ -1436,6 +1436,9 @@ static int usb_parse(const char *cmdline)
void hmp_usb_add(Monitor *mon, const QDict *qdict) void hmp_usb_add(Monitor *mon, const QDict *qdict)
{ {
const char *devname = qdict_get_str(qdict, "devname"); 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) { if (usb_device_add(devname) < 0) {
error_report("could not add USB device '%s'", devname); 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) void hmp_usb_del(Monitor *mon, const QDict *qdict)
{ {
const char *devname = qdict_get_str(qdict, "devname"); 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) { if (usb_device_del(devname) < 0) {
error_report("could not delete USB device '%s'", devname); 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); qemu_opts_parse_noisily(olist, "usb=on", false);
break; break;
case QEMU_OPTION_usbdevice: case QEMU_OPTION_usbdevice:
error_report("'-usbdevice' is deprecated, please use "
"'-device usb-...' instead");
olist = qemu_find_opts("machine"); olist = qemu_find_opts("machine");
qemu_opts_parse_noisily(olist, "usb=on", false); qemu_opts_parse_noisily(olist, "usb=on", false);
add_device_config(DEV_USB, optarg); add_device_config(DEV_USB, optarg);