Merge remote-tracking branch 'remotes/kraxel/tags/usb-20200928-pull-request' into staging

usb: xhci sysbus support.
usb: use lock guards.

# gpg: Signature made Mon 28 Sep 2020 14:16:22 BST
# gpg:                using RSA key 4CB6D8EED3E87138
# 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-20200928-pull-request:
  hw/usb: Use lock guard macros
  usb: hcd-xhci-sysbus: Attach xhci to sysbus device
  usb/hcd-xhci: Split pci wrapper for xhci base model
  usb/hcd-xhci: Move qemu-xhci device to hcd-xhci-pci.c
  usb/hcd-xhci: Make dma read/writes hooks pci free

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2020-09-28 19:31:50 +01:00
10 changed files with 563 additions and 258 deletions
+11
View File
@@ -36,12 +36,23 @@ config USB_XHCI
depends on PCI
select USB
config USB_XHCI_PCI
bool
default y if PCI_DEVICES
depends on PCI
select USB_XHCI
config USB_XHCI_NEC
bool
default y if PCI_DEVICES
depends on PCI
select USB_XHCI
config USB_XHCI_SYSBUS
bool
default y if USB_XHCI
select USB
config USB_MUSB
bool
select USB
+27 -27
View File
@@ -30,6 +30,7 @@
#include <libcacard.h>
#include "qemu/thread.h"
#include "qemu/lockable.h"
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "ccid.h"
@@ -244,34 +245,34 @@ static void *handle_apdu_thread(void* arg)
card->quit_apdu_thread = 0; /* debugging */
break;
}
qemu_mutex_lock(&card->vreader_mutex);
while (!QSIMPLEQ_EMPTY(&card->guest_apdu_list)) {
event = QSIMPLEQ_FIRST(&card->guest_apdu_list);
assert((unsigned long)event > 1000);
QSIMPLEQ_REMOVE_HEAD(&card->guest_apdu_list, entry);
if (event->p.data.type != EMUL_GUEST_APDU) {
DPRINTF(card, 1, "unexpected message in handle_apdu_thread\n");
WITH_QEMU_LOCK_GUARD(&card->vreader_mutex) {
while (!QSIMPLEQ_EMPTY(&card->guest_apdu_list)) {
event = QSIMPLEQ_FIRST(&card->guest_apdu_list);
assert((unsigned long)event > 1000);
QSIMPLEQ_REMOVE_HEAD(&card->guest_apdu_list, entry);
if (event->p.data.type != EMUL_GUEST_APDU) {
DPRINTF(card, 1, "unexpected message in handle_apdu_thread\n");
g_free(event);
continue;
}
if (card->reader == NULL) {
DPRINTF(card, 1, "reader is NULL\n");
g_free(event);
continue;
}
recv_len = sizeof(recv_data);
reader_status = vreader_xfr_bytes(card->reader,
event->p.data.data, event->p.data.len,
recv_data, &recv_len);
DPRINTF(card, 2, "got back apdu of length %d\n", recv_len);
if (reader_status == VREADER_OK) {
emulated_push_response_apdu(card, recv_data, recv_len);
} else {
emulated_push_error(card, reader_status);
}
g_free(event);
continue;
}
if (card->reader == NULL) {
DPRINTF(card, 1, "reader is NULL\n");
g_free(event);
continue;
}
recv_len = sizeof(recv_data);
reader_status = vreader_xfr_bytes(card->reader,
event->p.data.data, event->p.data.len,
recv_data, &recv_len);
DPRINTF(card, 2, "got back apdu of length %d\n", recv_len);
if (reader_status == VREADER_OK) {
emulated_push_response_apdu(card, recv_data, recv_len);
} else {
emulated_push_error(card, reader_status);
}
g_free(event);
}
qemu_mutex_unlock(&card->vreader_mutex);
}
return NULL;
}
@@ -365,7 +366,7 @@ static void card_event_handler(EventNotifier *notifier)
EmulEvent *event, *next;
event_notifier_test_and_clear(&card->notifier);
qemu_mutex_lock(&card->event_list_mutex);
QEMU_LOCK_GUARD(&card->event_list_mutex);
QSIMPLEQ_FOREACH_SAFE(event, &card->event_list, entry, next) {
DPRINTF(card, 2, "event %s\n", emul_event_to_string(event->p.gen.type));
switch (event->p.gen.type) {
@@ -398,7 +399,6 @@ static void card_event_handler(EventNotifier *notifier)
g_free(event);
}
QSIMPLEQ_INIT(&card->event_list);
qemu_mutex_unlock(&card->event_list_mutex);
}
static int init_event_notifier(EmulatedState *card, Error **errp)
+9 -9
View File
@@ -25,17 +25,17 @@
#include "hw/pci/pci.h"
#include "hw/qdev-properties.h"
#include "hcd-xhci.h"
#include "hcd-xhci-pci.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,
DEFINE_PROP_ON_OFF_AUTO("msi", XHCIPciState, msi, ON_OFF_AUTO_AUTO),
DEFINE_PROP_ON_OFF_AUTO("msix", XHCIPciState, msix, ON_OFF_AUTO_AUTO),
DEFINE_PROP_BIT("superspeed-ports-first", XHCIPciState,
xhci.flags, XHCI_FLAG_SS_FIRST, true),
DEFINE_PROP_BIT("force-pcie-endcap", XHCIPciState, xhci.flags,
XHCI_FLAG_FORCE_PCIE_ENDCAP, false),
DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS),
DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS),
DEFINE_PROP_UINT32("intrs", XHCIPciState, xhci.numintrs, MAXINTRS),
DEFINE_PROP_UINT32("slots", XHCIPciState, xhci.numslots, MAXSLOTS),
DEFINE_PROP_END_OF_LIST(),
};
@@ -52,7 +52,7 @@ static void nec_xhci_class_init(ObjectClass *klass, void *data)
static const TypeInfo nec_xhci_info = {
.name = TYPE_NEC_XHCI,
.parent = TYPE_XHCI,
.parent = TYPE_XHCI_PCI,
.class_init = nec_xhci_class_init,
};
+261
View File
@@ -0,0 +1,261 @@
/*
* USB xHCI controller with PCI bus emulation
*
* SPDX-FileCopyrightText: 2011 Securiforest
* SPDX-FileContributor: Hector Martin <hector@marcansoft.com>
* SPDX-sourceInfo: Based on usb-ohci.c, emulates Renesas NEC USB 3.0
* SPDX-FileCopyrightText: 2020 Xilinx
* SPDX-FileContributor: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
* SPDX-sourceInfo: Moved the pci specific content for hcd-xhci.c to
* hcd-xhci-pci.c
*
* 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/pci/pci.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
#include "hcd-xhci-pci.h"
#include "trace.h"
#include "qapi/error.h"
#define OFF_MSIX_TABLE 0x3000
#define OFF_MSIX_PBA 0x3800
static void xhci_pci_intr_update(XHCIState *xhci, int n, bool enable)
{
XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
PCIDevice *pci_dev = PCI_DEVICE(s);
if (!msix_enabled(pci_dev)) {
return;
}
if (enable == !!xhci->intr[n].msix_used) {
return;
}
if (enable) {
trace_usb_xhci_irq_msix_use(n);
msix_vector_use(pci_dev, n);
xhci->intr[n].msix_used = true;
} else {
trace_usb_xhci_irq_msix_unuse(n);
msix_vector_unuse(pci_dev, n);
xhci->intr[n].msix_used = false;
}
}
static void xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
{
XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
PCIDevice *pci_dev = PCI_DEVICE(s);
if (n == 0 &&
!(msix_enabled(pci_dev) ||
msi_enabled(pci_dev))) {
pci_set_irq(pci_dev, level);
}
if (msix_enabled(pci_dev)) {
msix_notify(pci_dev, n);
return;
}
if (msi_enabled(pci_dev)) {
msi_notify(pci_dev, n);
return;
}
}
static void xhci_pci_reset(DeviceState *dev)
{
XHCIPciState *s = XHCI_PCI(dev);
device_legacy_reset(DEVICE(&s->xhci));
}
static int xhci_pci_vmstate_post_load(void *opaque, int version_id)
{
XHCIPciState *s = XHCI_PCI(opaque);
PCIDevice *pci_dev = PCI_DEVICE(s);
int intr;
for (intr = 0; intr < s->xhci.numintrs; intr++) {
if (s->xhci.intr[intr].msix_used) {
msix_vector_use(pci_dev, intr);
} else {
msix_vector_unuse(pci_dev, intr);
}
}
return 0;
}
static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp)
{
int ret;
Error *err = NULL;
XHCIPciState *s = XHCI_PCI(dev);
dev->config[PCI_CLASS_PROG] = 0x30; /* xHCI */
dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
dev->config[PCI_CACHE_LINE_SIZE] = 0x10;
dev->config[0x60] = 0x30; /* release number */
object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL);
s->xhci.intr_update = xhci_pci_intr_update;
s->xhci.intr_raise = xhci_pci_intr_raise;
object_property_set_bool(OBJECT(&s->xhci), "realized", true, &err);
if (err) {
error_propagate(errp, err);
return;
}
if (strcmp(object_get_typename(OBJECT(dev)), TYPE_NEC_XHCI) == 0) {
s->xhci.nec_quirks = true;
}
if (s->msi != ON_OFF_AUTO_OFF) {
ret = msi_init(dev, 0x70, s->xhci.numintrs, true, false, &err);
/*
* Any error other than -ENOTSUP(board's MSI support is broken)
* is a programming error
*/
assert(!ret || ret == -ENOTSUP);
if (ret && s->msi == ON_OFF_AUTO_ON) {
/* Can't satisfy user's explicit msi=on request, fail */
error_append_hint(&err, "You have to use msi=auto (default) or "
"msi=off with this machine type.\n");
error_propagate(errp, err);
return;
}
assert(!err || s->msi == ON_OFF_AUTO_AUTO);
/* With msi=auto, we fall back to MSI off silently */
error_free(err);
}
pci_register_bar(dev, 0,
PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_TYPE_64,
&s->xhci.mem);
if (pci_bus_is_express(pci_get_bus(dev)) ||
xhci_get_flag(&s->xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) {
ret = pcie_endpoint_cap_init(dev, 0xa0);
assert(ret > 0);
}
if (s->msix != ON_OFF_AUTO_OFF) {
/* TODO check for errors, and should fail when msix=on */
msix_init(dev, s->xhci.numintrs,
&s->xhci.mem, 0, OFF_MSIX_TABLE,
&s->xhci.mem, 0, OFF_MSIX_PBA,
0x90, NULL);
}
s->xhci.as = pci_get_address_space(dev);
}
static void usb_xhci_pci_exit(PCIDevice *dev)
{
XHCIPciState *s = XHCI_PCI(dev);
/* destroy msix memory region */
if (dev->msix_table && dev->msix_pba
&& dev->msix_entry_used) {
msix_uninit(dev, &s->xhci.mem, &s->xhci.mem);
}
}
static const VMStateDescription vmstate_xhci_pci = {
.name = "xhci",
.version_id = 1,
.post_load = xhci_pci_vmstate_post_load,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj, XHCIPciState),
VMSTATE_MSIX(parent_obj, XHCIPciState),
VMSTATE_STRUCT(xhci, XHCIPciState, 1, vmstate_xhci, XHCIState),
VMSTATE_END_OF_LIST()
}
};
static void xhci_instance_init(Object *obj)
{
XHCIPciState *s = XHCI_PCI(obj);
/*
* QEMU_PCI_CAP_EXPRESS initialization does not depend on QEMU command
* line, therefore, no need to wait to realize like other devices
*/
PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS;
object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI);
qdev_alias_all_properties(DEVICE(&s->xhci), obj);
}
static void xhci_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = xhci_pci_reset;
dc->vmsd = &vmstate_xhci_pci;
set_bit(DEVICE_CATEGORY_USB, dc->categories);
k->realize = usb_xhci_pci_realize;
k->exit = usb_xhci_pci_exit;
k->class_id = PCI_CLASS_SERIAL_USB;
}
static const TypeInfo xhci_pci_info = {
.name = TYPE_XHCI_PCI,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(XHCIPciState),
.class_init = xhci_class_init,
.instance_init = xhci_instance_init,
.abstract = true,
.interfaces = (InterfaceInfo[]) {
{ INTERFACE_PCIE_DEVICE },
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
{ }
},
};
static void qemu_xhci_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->vendor_id = PCI_VENDOR_ID_REDHAT;
k->device_id = PCI_DEVICE_ID_REDHAT_XHCI;
k->revision = 0x01;
}
static void qemu_xhci_instance_init(Object *obj)
{
XHCIPciState *s = XHCI_PCI(obj);
XHCIState *xhci = &s->xhci;
s->msi = ON_OFF_AUTO_OFF;
s->msix = ON_OFF_AUTO_AUTO;
xhci->numintrs = MAXINTRS;
xhci->numslots = MAXSLOTS;
xhci_set_flag(xhci, XHCI_FLAG_SS_FIRST);
}
static const TypeInfo qemu_xhci_info = {
.name = TYPE_QEMU_XHCI,
.parent = TYPE_XHCI_PCI,
.class_init = qemu_xhci_class_init,
.instance_init = qemu_xhci_instance_init,
};
static void xhci_register_types(void)
{
type_register_static(&xhci_pci_info);
type_register_static(&qemu_xhci_info);
}
type_init(xhci_register_types)
+44
View File
@@ -0,0 +1,44 @@
/*
* 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
* Date: 2020-01-1; Author: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
* PCI hooks are moved from XHCIState to XHCIPciState
*
* 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/>.
*/
#ifndef HW_USB_HCD_XHCI_PCI_H
#define HW_USB_HCD_XHCI_PCI_H
#include "hw/usb.h"
#include "hcd-xhci.h"
#define TYPE_XHCI_PCI "pci-xhci"
#define XHCI_PCI(obj) \
OBJECT_CHECK(XHCIPciState, (obj), TYPE_XHCI_PCI)
typedef struct XHCIPciState {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
XHCIState xhci;
OnOffAuto msi;
OnOffAuto msix;
} XHCIPciState;
#endif
+109
View File
@@ -0,0 +1,109 @@
/*
* USB xHCI controller for system-bus interface
* Based on hcd-echi-sysbus.c
* SPDX-FileCopyrightText: 2020 Xilinx
* SPDX-FileContributor: Author: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "trace.h"
#include "qapi/error.h"
#include "hcd-xhci-sysbus.h"
#include "hw/irq.h"
static void xhci_sysbus_intr_raise(XHCIState *xhci, int n, bool level)
{
XHCISysbusState *s = container_of(xhci, XHCISysbusState, xhci);
qemu_set_irq(s->irq[n], level);
}
void xhci_sysbus_reset(DeviceState *dev)
{
XHCISysbusState *s = XHCI_SYSBUS(dev);
device_legacy_reset(DEVICE(&s->xhci));
}
static void xhci_sysbus_realize(DeviceState *dev, Error **errp)
{
XHCISysbusState *s = XHCI_SYSBUS(dev);
Error *err = NULL;
object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL);
object_property_set_bool(OBJECT(&s->xhci), "realized", true, &err);
if (err) {
error_propagate(errp, err);
return;
}
s->irq = g_new0(qemu_irq, s->xhci.numintrs);
qdev_init_gpio_out_named(dev, s->irq, SYSBUS_DEVICE_GPIO_IRQ,
s->xhci.numintrs);
if (s->xhci.dma_mr) {
s->xhci.as = g_malloc0(sizeof(AddressSpace));
address_space_init(s->xhci.as, s->xhci.dma_mr, NULL);
} else {
s->xhci.as = &address_space_memory;
}
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->xhci.mem);
}
static void xhci_sysbus_instance_init(Object *obj)
{
XHCISysbusState *s = XHCI_SYSBUS(obj);
object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI);
qdev_alias_all_properties(DEVICE(&s->xhci), obj);
object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
(Object **)&s->xhci.dma_mr,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_STRONG);
s->xhci.intr_update = NULL;
s->xhci.intr_raise = xhci_sysbus_intr_raise;
}
static Property xhci_sysbus_props[] = {
DEFINE_PROP_UINT32("intrs", XHCISysbusState, xhci.numintrs, MAXINTRS),
DEFINE_PROP_UINT32("slots", XHCISysbusState, xhci.numslots, MAXSLOTS),
DEFINE_PROP_END_OF_LIST(),
};
static const VMStateDescription vmstate_xhci_sysbus = {
.name = "xhci-sysbus",
.version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(xhci, XHCISysbusState, 1, vmstate_xhci, XHCIState),
VMSTATE_END_OF_LIST()
}
};
static void xhci_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = xhci_sysbus_reset;
dc->realize = xhci_sysbus_realize;
dc->vmsd = &vmstate_xhci_sysbus;
device_class_set_props(dc, xhci_sysbus_props);
}
static const TypeInfo xhci_sysbus_info = {
.name = TYPE_XHCI_SYSBUS,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(XHCISysbusState),
.class_init = xhci_sysbus_class_init,
.instance_init = xhci_sysbus_instance_init
};
static void xhci_sysbus_register_types(void)
{
type_register_static(&xhci_sysbus_info);
}
type_init(xhci_sysbus_register_types);
+32
View File
@@ -0,0 +1,32 @@
/*
* USB xHCI controller for system-bus interface
*
* SPDX-FileCopyrightText: 2020 Xilinx
* SPDX-FileContributor: Author: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
* SPDX-sourceInfo: Based on hcd-echi-sysbus
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef HW_USB_HCD_XHCI_SYSBUS_H
#define HW_USB_HCD_XHCI_SYSBUS_H
#include "hw/usb.h"
#include "hcd-xhci.h"
#include "hw/sysbus.h"
#define TYPE_XHCI_SYSBUS "sysbus-xhci"
#define XHCI_SYSBUS(obj) \
OBJECT_CHECK(XHCISysbusState, (obj), TYPE_XHCI_SYSBUS)
typedef struct XHCISysbusState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
XHCIState xhci;
qemu_irq *irq;
} XHCISysbusState;
void xhci_sysbus_reset(DeviceState *dev);
#endif
+54 -215
View File
File diff suppressed because it is too large Load Diff
+14 -7
View File
@@ -23,6 +23,9 @@
#define HW_USB_HCD_XHCI_H
#include "qom/object.h"
#include "hw/usb.h"
#include "sysemu/dma.h"
#define TYPE_XHCI "base-xhci"
#define TYPE_NEC_XHCI "nec-usb-xhci"
#define TYPE_QEMU_XHCI "qemu-xhci"
@@ -181,13 +184,13 @@ typedef struct XHCIInterrupter {
} XHCIInterrupter;
struct XHCIState {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
typedef struct XHCIState {
DeviceState parent;
USBBus bus;
MemoryRegion mem;
MemoryRegion *dma_mr;
AddressSpace *as;
MemoryRegion mem_cap;
MemoryRegion mem_oper;
MemoryRegion mem_runtime;
@@ -200,8 +203,9 @@ struct XHCIState {
uint32_t numslots;
uint32_t flags;
uint32_t max_pstreams_mask;
OnOffAuto msi;
OnOffAuto msix;
void (*intr_update)(XHCIState *s, int n, bool enable);
void (*intr_raise)(XHCIState *s, int n, bool level);
DeviceState *hostOpaque;
/* Operational Registers */
uint32_t usbcmd;
@@ -226,6 +230,9 @@ struct XHCIState {
XHCIRing cmd_ring;
bool nec_quirks;
};
} XHCIState;
extern const VMStateDescription vmstate_xhci;
bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit);
void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit);
#endif
+2
View File
@@ -21,6 +21,8 @@ softmmu_ss.add(when: 'CONFIG_USB_EHCI', if_true: files('hcd-ehci.c'))
softmmu_ss.add(when: 'CONFIG_USB_EHCI_PCI', if_true: files('hcd-ehci-pci.c'))
softmmu_ss.add(when: 'CONFIG_USB_EHCI_SYSBUS', if_true: files('hcd-ehci.c', 'hcd-ehci-sysbus.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI', if_true: files('hcd-xhci.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI_PCI', if_true: files('hcd-xhci-pci.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI_SYSBUS', if_true: files('hcd-xhci-sysbus.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI_NEC', if_true: files('hcd-xhci-nec.c'))
softmmu_ss.add(when: 'CONFIG_USB_MUSB', if_true: files('hcd-musb.c'))
softmmu_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('hcd-dwc2.c'))