aboutsummaryrefslogtreecommitdiff
path: root/hw/usb/hcd-ohci.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-01-08 10:36:20 -0600
committerAnthony Liguori <aliguori@us.ibm.com>2013-01-08 10:36:20 -0600
commit560c30b1db1d40fe45c5104185367c4de43399d3 (patch)
treed3fff38fd167ad08c8d45136c4095263f5d6d1da /hw/usb/hcd-ohci.c
parentc3dd94b129e222e00a4ed00689e11afdd85c740f (diff)
parent89eb147c2cfd2c797d3662aa2f55254441f0595a (diff)
Merge remote-tracking branch 'kraxel/usb.75' into staging
* kraxel/usb.75: (32 commits) uhci: stop using portio lists usbredir: Add support for buffered bulk input (v2) exynos4210: Add EHCI support usb/ehci: Add SysBus EHCI device for Exynos4210 usb/ehci: Move capsbase and opregbase into SysBus EHCI class usb/ehci: Clean up SysBus and PCI EHCI split xhci: call set-address with dummy usbpacket usb-redir: Add debugging to bufpq save / restore usbredir: Add usbredir_init_endpoints() helper usbredir: Verify we have 32 bits bulk length cap when redirecting to xhci usbredir: Add ep_stopped USBDevice method usbredir: Add USBEP2I and I2USBEP helper macros usbredir: Add an usbredir_stop_ep helper function usb: Add an usb_device_ep_stopped USBDevice method usb: Fix usb_ep_find_packet_by_id hid: Change idle handling to use a timer uhci: Maximize how many frames we catch up when behind uhci: Limit amount of frames processed in one go uhci: Add a QH_VALID define uhci: Fix pending interrupts getting lost on migration ... Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/usb/hcd-ohci.c')
-rw-r--r--hw/usb/hcd-ohci.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 052c4a3037..29bafa6da9 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -430,6 +430,23 @@ static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
return NULL;
}
+static void ohci_stop_endpoints(OHCIState *ohci)
+{
+ USBDevice *dev;
+ int i, j;
+
+ for (i = 0; i < ohci->num_ports; i++) {
+ dev = ohci->rhport[i].port.dev;
+ if (dev && dev->attached) {
+ usb_device_ep_stopped(dev, &dev->ep_ctl);
+ for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
+ usb_device_ep_stopped(dev, &dev->ep_in[j]);
+ usb_device_ep_stopped(dev, &dev->ep_out[j]);
+ }
+ }
+ }
+}
+
/* Reset the controller */
static void ohci_reset(void *opaque)
{
@@ -478,6 +495,7 @@ static void ohci_reset(void *opaque)
usb_cancel_packet(&ohci->usb_packet);
ohci->async_td = 0;
}
+ ohci_stop_endpoints(ohci);
DPRINTF("usb-ohci: Reset %s\n", ohci->name);
}
@@ -1147,6 +1165,8 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
if (ohci->async_td && addr == ohci->async_td) {
usb_cancel_packet(&ohci->usb_packet);
ohci->async_td = 0;
+ usb_device_ep_stopped(ohci->usb_packet.ep->dev,
+ ohci->usb_packet.ep);
}
continue;
}
@@ -1227,10 +1247,12 @@ static void ohci_frame_boundary(void *opaque)
}
/* Cancel all pending packets if either of the lists has been disabled. */
- if (ohci->async_td &&
- ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
- usb_cancel_packet(&ohci->usb_packet);
- ohci->async_td = 0;
+ if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
+ if (ohci->async_td) {
+ usb_cancel_packet(&ohci->usb_packet);
+ ohci->async_td = 0;
+ }
+ ohci_stop_endpoints(ohci);
}
ohci->old_ctl = ohci->ctl;
ohci_process_lists(ohci, 0);