EHCI controller setup needs to occur prior to checking any UHCI or
OHCI ports to ensure a high speed device is not mistakenly configured
on a full speed "companion" controller. However, only the UHCI/OHCI
port scan needs to be delayed, not the full UHCI/OHCI controller init.
This change moves back the ehci controller setup check until port
scan in UHCI/OHCI.
Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
---
src/hw/usb-ehci.c | 8 ++++++--
src/hw/usb-ehci.h | 1 +
src/hw/usb-ohci.c | 3 +++
src/hw/usb-uhci.c | 4 ++++
4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c
index 41f8579..010746c 100644
--- a/src/hw/usb-ehci.c
+++ b/src/hw/usb-ehci.c
@@ -337,9 +337,13 @@ ehci_setup(void)
if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_EHCI)
ehci_controller_setup(pci);
}
+}
- // Wait for all EHCI controllers to initialize. This forces OHCI/UHCI
- // setup to always be after any EHCI ports are routed to EHCI.
+// Wait for all EHCI controllers to initialize. This forces OHCI/UHCI
+// setup to always be after any EHCI ports are routed to EHCI.
+void
+ehci_wait_controllers(void)
+{
while (PendingEHCI)
yield();
}
diff --git a/src/hw/usb-ehci.h b/src/hw/usb-ehci.h
index 88f7b6a..0442188 100644
--- a/src/hw/usb-ehci.h
+++ b/src/hw/usb-ehci.h
@@ -3,6 +3,7 @@
// usb-ehci.c
void ehci_setup(void);
+void ehci_wait_controllers(void);
struct usbdevice_s;
struct usb_endpoint_descriptor;
struct usb_pipe;
diff --git a/src/hw/usb-ohci.c b/src/hw/usb-ohci.c
index 42f8a06..7ed964f 100644
--- a/src/hw/usb-ohci.c
+++ b/src/hw/usb-ohci.c
@@ -14,6 +14,7 @@
#include "pci_regs.h" // PCI_BASE_ADDRESS_0
#include "string.h" // memset
#include "usb.h" // struct usb_s
+#include "usb-ehci.h" // ehci_wait_controllers
#include "usb-ohci.h" // struct ohci_hcca
#include "util.h" // msleep
#include "x86.h" // readl
@@ -96,6 +97,8 @@ static int
check_ohci_ports(struct usb_ohci_s *cntl)
{
ASSERT32FLAT();
+ // Wait for ehci init - in case this is a "companion controller"
+ ehci_wait_controllers();
// Turn on power for all devices on roothub.
u32 rha = readl(&cntl->regs->roothub_a);
rha &= ~(RH_A_PSM | RH_A_OCPM);
diff --git a/src/hw/usb-uhci.c b/src/hw/usb-uhci.c
index 69c33ee..6d8aa47 100644
--- a/src/hw/usb-uhci.c
+++ b/src/hw/usb-uhci.c
@@ -13,6 +13,7 @@
#include "pci_regs.h" // PCI_BASE_ADDRESS_4
#include "string.h" // memset
#include "usb.h" // struct usb_s
+#include "usb-ehci.h" // ehci_wait_controllers
#include "usb-uhci.h" // USBLEGSUP
#include "util.h" // msleep
#include "x86.h" // outw
@@ -94,6 +95,9 @@ static int
check_uhci_ports(struct usb_uhci_s *cntl)
{
ASSERT32FLAT();
+ // Wait for ehci init - in case this is a "companion controller"
+ ehci_wait_controllers();
+
struct usbhub_s hub;
memset(&hub, 0, sizeof(hub));
hub.cntl = &cntl->usb;
--
2.5.0