|
Hans de Goede |
3f1f29 |
From a0f20940be744556be844ac857fa6dd679dc7af0 Mon Sep 17 00:00:00 2001
|
|
Hans de Goede |
3f1f29 |
From: Hans de Goede <hdegoede@redhat.com>
|
|
Hans de Goede |
3f1f29 |
Date: Fri, 24 Jun 2011 12:31:11 +0200
|
|
Hans de Goede |
3f1f29 |
Subject: [PATCH 06/35] usb: Replace device_destroy bus op with a child_detach
|
|
Hans de Goede |
3f1f29 |
port op
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
Note this fixes 2 things in one go, first of all the device_destroy bus
|
|
Hans de Goede |
3f1f29 |
op should be a device_detach bus op, as pending async packets from the
|
|
Hans de Goede |
3f1f29 |
device should be cancelled on detach not on destroy.
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
Secondly having this as a bus op won't work with companion controllers, since
|
|
Hans de Goede |
3f1f29 |
then there will be 1 bus driven by the ehci controller and thus 1 set of bus
|
|
Hans de Goede |
3f1f29 |
ops, but the device being detached may be downstream of a handed over port.
|
|
Hans de Goede |
3f1f29 |
Making the detach of a downstream device a port op allows the ehci controller
|
|
Hans de Goede |
3f1f29 |
to forward this to the companion controller port for handed over ports.
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Hans de Goede |
3f1f29 |
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
Hans de Goede |
3f1f29 |
---
|
|
Hans de Goede |
3f1f29 |
hw/milkymist-softusb.c | 9 +++++++--
|
|
Hans de Goede |
3f1f29 |
hw/usb-bus.c | 2 --
|
|
Hans de Goede |
3f1f29 |
hw/usb-ehci.c | 18 ++++++++++--------
|
|
Hans de Goede |
3f1f29 |
hw/usb-hub.c | 12 ++++++++++++
|
|
Hans de Goede |
3f1f29 |
hw/usb-musb.c | 17 +++++++++++++----
|
|
Hans de Goede |
3f1f29 |
hw/usb-ohci.c | 16 ++++++++++++----
|
|
Hans de Goede |
3f1f29 |
hw/usb-uhci.c | 18 ++++++++++--------
|
|
Hans de Goede |
3f1f29 |
hw/usb.h | 6 +++++-
|
|
Hans de Goede |
3f1f29 |
8 files changed, 69 insertions(+), 29 deletions(-)
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
|
|
Hans de Goede |
3f1f29 |
index 5ab35c3..ce2bfc6 100644
|
|
Hans de Goede |
3f1f29 |
--- a/hw/milkymist-softusb.c
|
|
Hans de Goede |
3f1f29 |
+++ b/hw/milkymist-softusb.c
|
|
Hans de Goede |
3f1f29 |
@@ -247,16 +247,21 @@ static void softusb_attach(USBPort *port)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
-static void softusb_device_destroy(USBBus *bus, USBDevice *dev)
|
|
Hans de Goede |
3f1f29 |
+static void softusb_detach(USBPort *port)
|
|
Hans de Goede |
3f1f29 |
+{
|
|
Hans de Goede |
3f1f29 |
+}
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
+static void softusb_child_detach(USBPort *port, USBDevice *child)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static USBPortOps softusb_ops = {
|
|
Hans de Goede |
3f1f29 |
.attach = softusb_attach,
|
|
Hans de Goede |
3f1f29 |
+ .detach = softusb_detach,
|
|
Hans de Goede |
3f1f29 |
+ .child_detach = softusb_child_detach,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static USBBusOps softusb_bus_ops = {
|
|
Hans de Goede |
3f1f29 |
- .device_destroy = softusb_device_destroy,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static void milkymist_softusb_reset(DeviceState *d)
|
|
Hans de Goede |
3f1f29 |
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
|
|
Hans de Goede |
3f1f29 |
index b511bac..c8347e9 100644
|
|
Hans de Goede |
3f1f29 |
--- a/hw/usb-bus.c
|
|
Hans de Goede |
3f1f29 |
+++ b/hw/usb-bus.c
|
|
Hans de Goede |
3f1f29 |
@@ -82,12 +82,10 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
|
|
Hans de Goede |
3f1f29 |
static int usb_qdev_exit(DeviceState *qdev)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
|
|
Hans de Goede |
3f1f29 |
- USBBus *bus = usb_bus_from_device(dev);
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
if (dev->attached) {
|
|
Hans de Goede |
3f1f29 |
usb_device_detach(dev);
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
- bus->ops->device_destroy(bus, dev);
|
|
Hans de Goede |
3f1f29 |
if (dev->info->handle_destroy) {
|
|
Hans de Goede |
3f1f29 |
dev->info->handle_destroy(dev);
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
|
Hans de Goede |
3f1f29 |
index 428c90b..96451f3 100644
|
|
Hans de Goede |
3f1f29 |
--- a/hw/usb-ehci.c
|
|
Hans de Goede |
3f1f29 |
+++ b/hw/usb-ehci.c
|
|
Hans de Goede |
3f1f29 |
@@ -751,6 +751,8 @@ static void ehci_detach(USBPort *port)
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
trace_usb_ehci_port_detach(port->index);
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+ ehci_queues_rip_device(s, port->dev);
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
*portsc &= ~PORTSC_CONNECT;
|
|
Hans de Goede |
3f1f29 |
*portsc |= PORTSC_CSC;
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
@@ -764,6 +766,13 @@ static void ehci_detach(USBPort *port)
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+static void ehci_child_detach(USBPort *port, USBDevice *child)
|
|
Hans de Goede |
3f1f29 |
+{
|
|
Hans de Goede |
3f1f29 |
+ EHCIState *s = port->opaque;
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
+ ehci_queues_rip_device(s, child);
|
|
Hans de Goede |
3f1f29 |
+}
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
/* 4.1 host controller initialization */
|
|
Hans de Goede |
3f1f29 |
static void ehci_reset(void *opaque)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
@@ -2117,23 +2126,16 @@ static void ehci_map(PCIDevice *pci_dev, int region_num,
|
|
Hans de Goede |
3f1f29 |
cpu_register_physical_memory(addr, size, s->mem);
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
-static void ehci_device_destroy(USBBus *bus, USBDevice *dev)
|
|
Hans de Goede |
3f1f29 |
-{
|
|
Hans de Goede |
3f1f29 |
- EHCIState *s = container_of(bus, EHCIState, bus);
|
|
Hans de Goede |
3f1f29 |
-
|
|
Hans de Goede |
3f1f29 |
- ehci_queues_rip_device(s, dev);
|
|
Hans de Goede |
3f1f29 |
-}
|
|
Hans de Goede |
3f1f29 |
-
|
|
Hans de Goede |
3f1f29 |
static int usb_ehci_initfn(PCIDevice *dev);
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static USBPortOps ehci_port_ops = {
|
|
Hans de Goede |
3f1f29 |
.attach = ehci_attach,
|
|
Hans de Goede |
3f1f29 |
.detach = ehci_detach,
|
|
Hans de Goede |
3f1f29 |
+ .child_detach = ehci_child_detach,
|
|
Hans de Goede |
3f1f29 |
.complete = ehci_async_complete_packet,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static USBBusOps ehci_bus_ops = {
|
|
Hans de Goede |
3f1f29 |
- .device_destroy = ehci_device_destroy,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static PCIDeviceInfo ehci_info = {
|
|
Hans de Goede |
3f1f29 |
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
|
|
Hans de Goede |
3f1f29 |
index d324bba..b7557ce 100644
|
|
Hans de Goede |
3f1f29 |
--- a/hw/usb-hub.c
|
|
Hans de Goede |
3f1f29 |
+++ b/hw/usb-hub.c
|
|
Hans de Goede |
3f1f29 |
@@ -238,6 +238,9 @@ static void usb_hub_detach(USBPort *port1)
|
|
Hans de Goede |
3f1f29 |
USBHubState *s = port1->opaque;
|
|
Hans de Goede |
3f1f29 |
USBHubPort *port = &s->ports[port1->index];
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+ /* Let upstream know the device on this port is gone */
|
|
Hans de Goede |
3f1f29 |
+ s->dev.port->ops->child_detach(s->dev.port, port1->dev);
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
port->wPortStatus &= ~PORT_STAT_CONNECTION;
|
|
Hans de Goede |
3f1f29 |
port->wPortChange |= PORT_STAT_C_CONNECTION;
|
|
Hans de Goede |
3f1f29 |
if (port->wPortStatus & PORT_STAT_ENABLE) {
|
|
Hans de Goede |
3f1f29 |
@@ -246,6 +249,14 @@ static void usb_hub_detach(USBPort *port1)
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
|
|
Hans de Goede |
3f1f29 |
+{
|
|
Hans de Goede |
3f1f29 |
+ USBHubState *s = port1->opaque;
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
+ /* Pass along upstream */
|
|
Hans de Goede |
3f1f29 |
+ s->dev.port->ops->child_detach(s->dev.port, child);
|
|
Hans de Goede |
3f1f29 |
+}
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
static void usb_hub_wakeup(USBPort *port1)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
USBHubState *s = port1->opaque;
|
|
Hans de Goede |
3f1f29 |
@@ -537,6 +548,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
|
|
Hans de Goede |
3f1f29 |
static USBPortOps usb_hub_port_ops = {
|
|
Hans de Goede |
3f1f29 |
.attach = usb_hub_attach,
|
|
Hans de Goede |
3f1f29 |
.detach = usb_hub_detach,
|
|
Hans de Goede |
3f1f29 |
+ .child_detach = usb_hub_child_detach,
|
|
Hans de Goede |
3f1f29 |
.wakeup = usb_hub_wakeup,
|
|
Hans de Goede |
3f1f29 |
.complete = usb_hub_complete,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
|
|
Hans de Goede |
3f1f29 |
index 580bdc8..035dda8 100644
|
|
Hans de Goede |
3f1f29 |
--- a/hw/usb-musb.c
|
|
Hans de Goede |
3f1f29 |
+++ b/hw/usb-musb.c
|
|
Hans de Goede |
3f1f29 |
@@ -261,17 +261,18 @@
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static void musb_attach(USBPort *port);
|
|
Hans de Goede |
3f1f29 |
static void musb_detach(USBPort *port);
|
|
Hans de Goede |
3f1f29 |
+static void musb_child_detach(USBPort *port, USBDevice *child);
|
|
Hans de Goede |
3f1f29 |
static void musb_schedule_cb(USBPort *port, USBPacket *p);
|
|
Hans de Goede |
3f1f29 |
-static void musb_device_destroy(USBBus *bus, USBDevice *dev);
|
|
Hans de Goede |
3f1f29 |
+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev);
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static USBPortOps musb_port_ops = {
|
|
Hans de Goede |
3f1f29 |
.attach = musb_attach,
|
|
Hans de Goede |
3f1f29 |
.detach = musb_detach,
|
|
Hans de Goede |
3f1f29 |
+ .child_detach = musb_child_detach,
|
|
Hans de Goede |
3f1f29 |
.complete = musb_schedule_cb,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static USBBusOps musb_bus_ops = {
|
|
Hans de Goede |
3f1f29 |
- .device_destroy = musb_device_destroy,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
typedef struct MUSBPacket MUSBPacket;
|
|
Hans de Goede |
3f1f29 |
@@ -497,10 +498,19 @@ static void musb_detach(USBPort *port)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
MUSBState *s = (MUSBState *) port->opaque;
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+ musb_async_cancel_device(s, port->dev);
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
musb_intr_set(s, musb_irq_disconnect, 1);
|
|
Hans de Goede |
3f1f29 |
musb_session_update(s, 1, s->session);
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+static void musb_child_detach(USBPort *port, USBDevice *child)
|
|
Hans de Goede |
3f1f29 |
+{
|
|
Hans de Goede |
3f1f29 |
+ MUSBState *s = (MUSBState *) port->opaque;
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
+ musb_async_cancel_device(s, child);
|
|
Hans de Goede |
3f1f29 |
+}
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
static void musb_cb_tick0(void *opaque)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
|
|
Hans de Goede |
3f1f29 |
@@ -782,9 +792,8 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
|
|
Hans de Goede |
3f1f29 |
musb_rx_intr_set(s, epnum, 1);
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
-static void musb_device_destroy(USBBus *bus, USBDevice *dev)
|
|
Hans de Goede |
3f1f29 |
+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
- MUSBState *s = container_of(bus, MUSBState, bus);
|
|
Hans de Goede |
3f1f29 |
int ep, dir;
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
for (ep = 0; ep < 16; ep++) {
|
|
Hans de Goede |
3f1f29 |
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
|
|
Hans de Goede |
3f1f29 |
index bd92c31..46f0bcb 100644
|
|
Hans de Goede |
3f1f29 |
--- a/hw/usb-ohci.c
|
|
Hans de Goede |
3f1f29 |
+++ b/hw/usb-ohci.c
|
|
Hans de Goede |
3f1f29 |
@@ -124,6 +124,7 @@ struct ohci_hcca {
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static void ohci_bus_stop(OHCIState *ohci);
|
|
Hans de Goede |
3f1f29 |
+static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
/* Bitfields for the first word of an Endpoint Desciptor. */
|
|
Hans de Goede |
3f1f29 |
#define OHCI_ED_FA_SHIFT 0
|
|
Hans de Goede |
3f1f29 |
@@ -351,6 +352,8 @@ static void ohci_detach(USBPort *port1)
|
|
Hans de Goede |
3f1f29 |
OHCIPort *port = &s->rhport[port1->index];
|
|
Hans de Goede |
3f1f29 |
uint32_t old_state = port->ctrl;
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+ ohci_async_cancel_device(s, port1->dev);
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
/* set connect status */
|
|
Hans de Goede |
3f1f29 |
if (port->ctrl & OHCI_PORT_CCS) {
|
|
Hans de Goede |
3f1f29 |
port->ctrl &= ~OHCI_PORT_CCS;
|
|
Hans de Goede |
3f1f29 |
@@ -392,6 +395,13 @@ static void ohci_wakeup(USBPort *port1)
|
|
Hans de Goede |
3f1f29 |
ohci_set_interrupt(s, intr);
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+static void ohci_child_detach(USBPort *port1, USBDevice *child)
|
|
Hans de Goede |
3f1f29 |
+{
|
|
Hans de Goede |
3f1f29 |
+ OHCIState *s = port1->opaque;
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
+ ohci_async_cancel_device(s, child);
|
|
Hans de Goede |
3f1f29 |
+}
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
/* Reset the controller */
|
|
Hans de Goede |
3f1f29 |
static void ohci_reset(void *opaque)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
@@ -1673,10 +1683,8 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
-static void ohci_device_destroy(USBBus *bus, USBDevice *dev)
|
|
Hans de Goede |
3f1f29 |
+static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
- OHCIState *ohci = container_of(bus, OHCIState, bus);
|
|
Hans de Goede |
3f1f29 |
-
|
|
Hans de Goede |
3f1f29 |
if (ohci->async_td && ohci->usb_packet.owner == dev) {
|
|
Hans de Goede |
3f1f29 |
usb_cancel_packet(&ohci->usb_packet);
|
|
Hans de Goede |
3f1f29 |
ohci->async_td = 0;
|
|
Hans de Goede |
3f1f29 |
@@ -1700,12 +1708,12 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
|
|
Hans de Goede |
3f1f29 |
static USBPortOps ohci_port_ops = {
|
|
Hans de Goede |
3f1f29 |
.attach = ohci_attach,
|
|
Hans de Goede |
3f1f29 |
.detach = ohci_detach,
|
|
Hans de Goede |
3f1f29 |
+ .child_detach = ohci_child_detach,
|
|
Hans de Goede |
3f1f29 |
.wakeup = ohci_wakeup,
|
|
Hans de Goede |
3f1f29 |
.complete = ohci_async_complete_packet,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static USBBusOps ohci_bus_ops = {
|
|
Hans de Goede |
3f1f29 |
- .device_destroy = ohci_device_destroy,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
|
|
Hans de Goede |
3f1f29 |
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
|
|
Hans de Goede |
3f1f29 |
index ab635f6..a46d61a 100644
|
|
Hans de Goede |
3f1f29 |
--- a/hw/usb-uhci.c
|
|
Hans de Goede |
3f1f29 |
+++ b/hw/usb-uhci.c
|
|
Hans de Goede |
3f1f29 |
@@ -606,6 +606,8 @@ static void uhci_detach(USBPort *port1)
|
|
Hans de Goede |
3f1f29 |
UHCIState *s = port1->opaque;
|
|
Hans de Goede |
3f1f29 |
UHCIPort *port = &s->ports[port1->index];
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+ uhci_async_cancel_device(s, port1->dev);
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
/* set connect status */
|
|
Hans de Goede |
3f1f29 |
if (port->ctrl & UHCI_PORT_CCS) {
|
|
Hans de Goede |
3f1f29 |
port->ctrl &= ~UHCI_PORT_CCS;
|
|
Hans de Goede |
3f1f29 |
@@ -620,6 +622,13 @@ static void uhci_detach(USBPort *port1)
|
|
Hans de Goede |
3f1f29 |
uhci_resume(s);
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
+static void uhci_child_detach(USBPort *port1, USBDevice *child)
|
|
Hans de Goede |
3f1f29 |
+{
|
|
Hans de Goede |
3f1f29 |
+ UHCIState *s = port1->opaque;
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
+ uhci_async_cancel_device(s, child);
|
|
Hans de Goede |
3f1f29 |
+}
|
|
Hans de Goede |
3f1f29 |
+
|
|
Hans de Goede |
3f1f29 |
static void uhci_wakeup(USBPort *port1)
|
|
Hans de Goede |
3f1f29 |
{
|
|
Hans de Goede |
3f1f29 |
UHCIState *s = port1->opaque;
|
|
Hans de Goede |
3f1f29 |
@@ -1095,22 +1104,15 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
|
|
Hans de Goede |
3f1f29 |
register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
|
|
Hans de Goede |
3f1f29 |
}
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
-static void uhci_device_destroy(USBBus *bus, USBDevice *dev)
|
|
Hans de Goede |
3f1f29 |
-{
|
|
Hans de Goede |
3f1f29 |
- UHCIState *s = container_of(bus, UHCIState, bus);
|
|
Hans de Goede |
3f1f29 |
-
|
|
Hans de Goede |
3f1f29 |
- uhci_async_cancel_device(s, dev);
|
|
Hans de Goede |
3f1f29 |
-}
|
|
Hans de Goede |
3f1f29 |
-
|
|
Hans de Goede |
3f1f29 |
static USBPortOps uhci_port_ops = {
|
|
Hans de Goede |
3f1f29 |
.attach = uhci_attach,
|
|
Hans de Goede |
3f1f29 |
.detach = uhci_detach,
|
|
Hans de Goede |
3f1f29 |
+ .child_detach = uhci_child_detach,
|
|
Hans de Goede |
3f1f29 |
.wakeup = uhci_wakeup,
|
|
Hans de Goede |
3f1f29 |
.complete = uhci_async_complete,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static USBBusOps uhci_bus_ops = {
|
|
Hans de Goede |
3f1f29 |
- .device_destroy = uhci_device_destroy,
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
static int usb_uhci_common_initfn(PCIDevice *dev)
|
|
Hans de Goede |
3f1f29 |
diff --git a/hw/usb.h b/hw/usb.h
|
|
Hans de Goede |
3f1f29 |
index 65f45a0..ded2de2 100644
|
|
Hans de Goede |
3f1f29 |
--- a/hw/usb.h
|
|
Hans de Goede |
3f1f29 |
+++ b/hw/usb.h
|
|
Hans de Goede |
3f1f29 |
@@ -252,6 +252,11 @@ struct USBDeviceInfo {
|
|
Hans de Goede |
3f1f29 |
typedef struct USBPortOps {
|
|
Hans de Goede |
3f1f29 |
void (*attach)(USBPort *port);
|
|
Hans de Goede |
3f1f29 |
void (*detach)(USBPort *port);
|
|
Hans de Goede |
3f1f29 |
+ /*
|
|
Hans de Goede |
3f1f29 |
+ * This gets called when a device downstream from the device attached to
|
|
Hans de Goede |
3f1f29 |
+ * the port (iow attached through a hub) gets detached.
|
|
Hans de Goede |
3f1f29 |
+ */
|
|
Hans de Goede |
3f1f29 |
+ void (*child_detach)(USBPort *port, USBDevice *child);
|
|
Hans de Goede |
3f1f29 |
void (*wakeup)(USBPort *port);
|
|
Hans de Goede |
3f1f29 |
/*
|
|
Hans de Goede |
3f1f29 |
* Note that port->dev will be different then the device from which
|
|
Hans de Goede |
3f1f29 |
@@ -351,7 +356,6 @@ struct USBBus {
|
|
Hans de Goede |
3f1f29 |
struct USBBusOps {
|
|
Hans de Goede |
3f1f29 |
int (*register_companion)(USBBus *bus, USBPort *ports[],
|
|
Hans de Goede |
3f1f29 |
uint32_t portcount, uint32_t firstport);
|
|
Hans de Goede |
3f1f29 |
- void (*device_destroy)(USBBus *bus, USBDevice *dev);
|
|
Hans de Goede |
3f1f29 |
};
|
|
Hans de Goede |
3f1f29 |
|
|
Hans de Goede |
3f1f29 |
void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
|
|
Hans de Goede |
3f1f29 |
--
|
|
Hans de Goede |
3f1f29 |
1.7.5.1
|
|
Hans de Goede |
3f1f29 |
|