summaryrefslogtreecommitdiff
path: root/hw/usb
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2014-08-29 14:40:08 +0200
committerGerd Hoffmann <kraxel@redhat.com>2014-09-23 12:51:08 +0200
commitec56214f6f23c1e2f78de6afa6835acc35fc03ed (patch)
treee2c91b868430a9a6a92e5b95b2e98784cd21ec06 /hw/usb
parent638ca939d80886545b1b279be240e511da16584f (diff)
downloadqemu-ec56214f6f23c1e2f78de6afa6835acc35fc03ed.tar.gz
usb: tag standalone ehci as hotpluggable
Add a flag to EHCIPCIInfo saying whenever the controller supports companions or not. Make sure we only allow registering companions for ehci versions supporting that. Enable pci hotplug for the ehci variants not supporting companions. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/usb')
-rw-r--r--hw/usb/hcd-ehci-pci.c12
-rw-r--r--hw/usb/hcd-ehci.c8
-rw-r--r--hw/usb/hcd-ehci.h1
3 files changed, 18 insertions, 3 deletions
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 289ca3b853..490f2b6af9 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -23,6 +23,7 @@ typedef struct EHCIPCIInfo {
uint16_t vendor_id;
uint16_t device_id;
uint8_t revision;
+ bool companion;
} EHCIPCIInfo;
static int usb_ehci_pci_initfn(PCIDevice *dev)
@@ -71,6 +72,7 @@ static int usb_ehci_pci_initfn(PCIDevice *dev)
static void usb_ehci_pci_init(Object *obj)
{
+ DeviceClass *dc = OBJECT_GET_CLASS(DeviceClass, obj, TYPE_DEVICE);
EHCIPCIState *i = PCI_EHCI(obj);
EHCIState *s = &i->ehci;
@@ -81,6 +83,10 @@ static void usb_ehci_pci_init(Object *obj)
s->portscbase = 0x44;
s->portnr = NB_PORTS;
+ if (!dc->hotpluggable) {
+ s->companion_enable = true;
+ }
+
usb_ehci_init(s, DEVICE(obj));
}
@@ -137,7 +143,6 @@ static void ehci_class_init(ObjectClass *klass, void *data)
k->exit = usb_ehci_pci_exit;
k->class_id = PCI_CLASS_SERIAL_USB;
k->config_write = usb_ehci_pci_write_config;
- dc->hotpluggable = false;
dc->vmsd = &vmstate_ehci_pci;
dc->props = ehci_pci_properties;
}
@@ -161,6 +166,9 @@ static void ehci_data_class_init(ObjectClass *klass, void *data)
k->device_id = i->device_id;
k->revision = i->revision;
set_bit(DEVICE_CATEGORY_USB, dc->categories);
+ if (i->companion) {
+ dc->hotpluggable = false;
+ }
}
static struct EHCIPCIInfo ehci_pci_info[] = {
@@ -174,11 +182,13 @@ static struct EHCIPCIInfo ehci_pci_info[] = {
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1,
.revision = 0x03,
+ .companion = true,
},{
.name = "ich9-usb-ehci2", /* 00:1a.7 */
.vendor_id = PCI_VENDOR_ID_INTEL,
.device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI2,
.revision = 0x03,
+ .companion = true,
}
};
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index bacb7ceac9..1cc0fc116d 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2347,10 +2347,13 @@ static USBPortOps ehci_port_ops = {
.complete = ehci_async_complete_packet,
};
-static USBBusOps ehci_bus_ops = {
+static USBBusOps ehci_bus_ops_companion = {
.register_companion = ehci_register_companion,
.wakeup_endpoint = ehci_wakeup_endpoint,
};
+static USBBusOps ehci_bus_ops_standalone = {
+ .wakeup_endpoint = ehci_wakeup_endpoint,
+};
static void usb_ehci_pre_save(void *opaque)
{
@@ -2456,7 +2459,8 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp)
return;
}
- usb_bus_new(&s->bus, sizeof(s->bus), &ehci_bus_ops, dev);
+ usb_bus_new(&s->bus, sizeof(s->bus), s->companion_enable ?
+ &ehci_bus_ops_companion : &ehci_bus_ops_standalone, dev);
for (i = 0; i < s->portnr; i++) {
usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops,
USB_SPEED_MASK_HIGH);
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 4858b7e80c..2bc259c9b4 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -262,6 +262,7 @@ struct EHCIState {
MemoryRegion mem_opreg;
MemoryRegion mem_ports;
int companion_count;
+ bool companion_enable;
uint16_t capsbase;
uint16_t opregbase;
uint16_t portscbase;