aboutsummaryrefslogtreecommitdiff
path: root/src/hw
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2014-09-10 11:33:01 -0400
committerKevin O'Connor <kevin@koconnor.net>2014-09-16 11:16:40 -0400
commit0f6813009fd8630ee89545f74f728eac742369aa (patch)
tree139310ab7b6b56f85729cd4b96258439fddcefbb /src/hw
parente2d6fddcd956b3bbcb9852d8f87ff41eab239a2e (diff)
downloadseabios-0f6813009fd8630ee89545f74f728eac742369aa.zip
seabios-0f6813009fd8630ee89545f74f728eac742369aa.tar.gz
seabios-0f6813009fd8630ee89545f74f728eac742369aa.tar.bz2
usb: Perform device detect polling on all usb controllers.
Move the 100ms (USB_TIME_SIGATT) device detect polling from the ohci/uhci/usb-hub code to the generic usb_hub_port_setup() code. This extends the 100ms polling to ehci and xhci controllers. The code in usb_hub_port_setup() now compares USB_TIME_SIGATT to the start of usb_enumerate(), which may make boots faster when threads are disabled. This patch also changes the meaning of the return code for hub->op->detect() calls. Now 1 indicates device found, 0 indicates device not found, and -1 indicates permanent failure. Also, the xhci controller generic delay of 100ms is replaced with a 20ms root hub power stabilize time. This in combination with the 100ms for USB_TIME_SIGATT should be closer to the USB2 spec (the USB3 spec does not seem to declare an equivalent of USB_TIME_SIGATT). Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/hw')
-rw-r--r--src/hw/usb-ehci.c4
-rw-r--r--src/hw/usb-hub.c26
-rw-r--r--src/hw/usb-ohci.c17
-rw-r--r--src/hw/usb-uhci.c18
-rw-r--r--src/hw/usb-xhci.c8
-rw-r--r--src/hw/usb.c21
-rw-r--r--src/hw/usb.h1
7 files changed, 35 insertions, 60 deletions
diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c
index 86496ce..20e387b 100644
--- a/src/hw/usb-ehci.c
+++ b/src/hw/usb-ehci.c
@@ -52,7 +52,7 @@ ehci_hub_detect(struct usbhub_s *hub, u32 port)
if (!(portsc & PORT_CONNECT))
// No device present
- return -1;
+ return 0;
if ((portsc & PORT_LINESTATUS_MASK) == PORT_LINESTATUS_KSTATE) {
// low speed device
@@ -66,7 +66,7 @@ ehci_hub_detect(struct usbhub_s *hub, u32 port)
portsc = (portsc & ~PORT_PE) | PORT_RESET;
writel(portreg, portsc);
msleep(USB_TIME_DRSTR);
- return 0;
+ return 1;
}
// Reset device on port
diff --git a/src/hw/usb-hub.c b/src/hw/usb-hub.c
index 2a34e57..4731a91 100644
--- a/src/hw/usb-hub.c
+++ b/src/hw/usb-hub.c
@@ -72,29 +72,13 @@ get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts)
static int
usb_hub_detect(struct usbhub_s *hub, u32 port)
{
- // Check periodically for a device connect.
struct usb_port_status sts;
- u32 end = timer_calc(USB_TIME_SIGATT);
- for (;;) {
- int ret = get_port_status(hub, port, &sts);
- if (ret)
- goto fail;
- if (sts.wPortStatus & USB_PORT_STAT_CONNECTION)
- // Device connected.
- break;
- if (timer_check(end))
- // No device found.
- return -1;
- msleep(5);
+ int ret = get_port_status(hub, port, &sts);
+ if (ret) {
+ dprintf(1, "Failure on hub port %d detect\n", port);
+ return -1;
}
-
- // XXX - wait USB_TIME_ATTDB time?
-
- return 0;
-
-fail:
- dprintf(1, "Failure on hub port %d detect\n", port);
- return -1;
+ return (sts.wPortStatus & USB_PORT_STAT_CONNECTION) ? 1 : 0;
}
// Disable port
diff --git a/src/hw/usb-ohci.c b/src/hw/usb-ohci.c
index 8089e13..7a22057 100644
--- a/src/hw/usb-ohci.c
+++ b/src/hw/usb-ohci.c
@@ -42,21 +42,8 @@ static int
ohci_hub_detect(struct usbhub_s *hub, u32 port)
{
struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
- u32 end = timer_calc(USB_TIME_SIGATT);
- for (;;) {
- u32 sts = readl(&cntl->regs->roothub_portstatus[port]);
- if (sts & RH_PS_CCS)
- // Device connected.
- break;
- if (timer_check(end))
- // No device found.
- return -1;
- msleep(5);
- }
-
- // XXX - need to wait for USB_TIME_ATTDB if just powered up?
-
- return 0;
+ u32 sts = readl(&cntl->regs->roothub_portstatus[port]);
+ return (sts & RH_PS_CCS) ? 1 : 0;
}
// Disable port
diff --git a/src/hw/usb-uhci.c b/src/hw/usb-uhci.c
index 406af90..a34f6db 100644
--- a/src/hw/usb-uhci.c
+++ b/src/hw/usb-uhci.c
@@ -43,25 +43,17 @@ uhci_hub_detect(struct usbhub_s *hub, u32 port)
{
struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
-
- u32 end = timer_calc(USB_TIME_SIGATT);
- for (;;) {
- u16 status = inw(ioport);
- if (status & USBPORTSC_CCS)
- // Device connected.
- break;
- if (timer_check(end))
- // No device found.
- return -1;
- msleep(5);
- }
+ u16 status = inw(ioport);
+ if (!(status & USBPORTSC_CCS))
+ // No device found.
+ return 0;
// XXX - if just powered up, need to wait for USB_TIME_ATTDB?
// Begin reset on port
outw(USBPORTSC_PR, ioport);
msleep(USB_TIME_DRSTR);
- return 0;
+ return 1;
}
// Reset device on port
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c
index 5f91d89..eafa4cb 100644
--- a/src/hw/usb-xhci.c
+++ b/src/hw/usb-xhci.c
@@ -320,6 +320,8 @@ static int wait_bit(u32 *reg, u32 mask, int value, u32 timeout)
* Root hub
****************************************************************/
+#define XHCI_TIME_POSTPOWER 20
+
// Check if device attached to port
static void
xhci_print_port_state(int loglevel, const char *prefix, u32 port, u32 portsc)
@@ -339,7 +341,7 @@ xhci_hub_detect(struct usbhub_s *hub, u32 port)
{
struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
u32 portsc = readl(&xhci->pr[port].portsc);
- return (portsc & XHCI_PORTSC_CCS) ? 0 : -1;
+ return (portsc & XHCI_PORTSC_CCS) ? 1 : 0;
}
// Reset device on port
@@ -388,8 +390,8 @@ static struct usbhub_op_s xhci_hub_ops = {
static int
xhci_check_ports(struct usb_xhci_s *xhci)
{
- // FIXME: try find a more elegant way than a fixed delay
- msleep(100);
+ // Wait for port power to stabilize.
+ msleep(XHCI_TIME_POSTPOWER);
struct usbhub_s hub;
memset(&hub, 0, sizeof(hub));
diff --git a/src/hw/usb.c b/src/hw/usb.c
index 930b5d9..153e153 100644
--- a/src/hw/usb.c
+++ b/src/hw/usb.c
@@ -404,15 +404,23 @@ usb_hub_port_setup(void *data)
struct usbhub_s *hub = usbdev->hub;
u32 port = usbdev->port;
- // Detect if device present (and possibly start reset)
- int ret = hub->op->detect(hub, port);
- if (ret)
- // No device present
- goto done;
+ for (;;) {
+ // Detect if device present (and possibly start reset)
+ int ret = hub->op->detect(hub, port);
+ if (ret > 0)
+ // Device connected.
+ break;
+ if (ret < 0 || timer_check(hub->detectend))
+ // No device found.
+ goto done;
+ msleep(5);
+ }
+
+ // XXX - wait USB_TIME_ATTDB time?
// Reset port and determine device speed
mutex_lock(&hub->cntl->resetlock);
- ret = hub->op->reset(hub, port);
+ int ret = hub->op->reset(hub, port);
if (ret < 0)
// Reset failed
goto resetfail;
@@ -447,6 +455,7 @@ usb_enumerate(struct usbhub_s *hub)
{
u32 portcount = hub->portcount;
hub->threads = portcount;
+ hub->detectend = timer_calc(USB_TIME_SIGATT);
// Launch a thread for every port.
int i;
diff --git a/src/hw/usb.h b/src/hw/usb.h
index 223e4d6..fe80ea6 100644
--- a/src/hw/usb.h
+++ b/src/hw/usb.h
@@ -46,6 +46,7 @@ struct usbhub_s {
struct usbdevice_s *usbdev;
struct usb_s *cntl;
struct mutex_s lock;
+ u32 detectend;
u32 port;
u32 threads;
u32 portcount;