#include "usb.h" // struct usb_s
#include "farptr.h" // GET_FLATPTR
#include "biosvar.h" // GET_GLOBAL
+#include "usb-hub.h" // struct usbhub_s
+
+
+/****************************************************************
+ * Root hub
+ ****************************************************************/
+
+static void
+init_uhci_port(void *data)
+{
+ struct usbhub_s *hub = data;
+ u32 port = hub->port; // XXX - find better way to pass port
+ u16 ioport = hub->cntl->uhci.iobase + USBPORTSC1 + port * 2;
+
+ u16 status = inw(ioport);
+ if (!(status & USBPORTSC_CCS))
+ // No device
+ goto done;
+
+ // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
+
+ // Reset port
+ outw(USBPORTSC_PR, ioport);
+ msleep(USB_TIME_DRSTR);
+ mutex_lock(&hub->cntl->resetlock);
+ outw(0, ioport);
+ udelay(6); // 64 high-speed bit times
+ status = inw(ioport);
+ if (!(status & USBPORTSC_CCS))
+ // No longer connected
+ goto resetfail;
+ outw(USBPORTSC_PE, ioport);
+ struct usb_pipe *pipe = usb_set_address(
+ hub->cntl, !!(status & USBPORTSC_LSDA));
+ if (!pipe)
+ goto resetfail;
+ mutex_unlock(&hub->cntl->resetlock);
+
+ // Configure port
+ int count = configure_usb_device(pipe);
+ free_pipe(pipe);
+ if (! count)
+ // Disable port
+ outw(0, ioport);
+ hub->devcount += count;
+done:
+ hub->threads--;
+ return;
+
+resetfail:
+ outw(0, ioport);
+ mutex_unlock(&hub->cntl->resetlock);
+ goto done;
+}
+
+// Find any devices connected to the root hub.
+static int
+check_ports(struct usb_s *cntl)
+{
+ ASSERT32FLAT();
+ struct usbhub_s hub;
+ memset(&hub, 0, sizeof(hub));
+ hub.cntl = cntl;
+ hub.threads = 2;
+
+ // Launch a thread for every port.
+ run_thread(init_uhci_port, &hub);
+ hub.port = 1;
+ run_thread(init_uhci_port, &hub);
+
+ // Wait for threads to complete.
+ while (hub.threads)
+ yield();
+
+ return hub.devcount;
+}
/****************************************************************
outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->uhci.iobase + USBCMD);
}
-// Find any devices connected to the root hub.
-static int
-check_ports(struct usb_s *cntl)
-{
- // XXX - if just powered up, need to wait for USB_TIME_SIGATT?
- u16 port1 = inw(cntl->uhci.iobase + USBPORTSC1);
- u16 port2 = inw(cntl->uhci.iobase + USBPORTSC2);
-
- if (!((port1 & USBPORTSC_CCS) || (port2 & USBPORTSC_CCS)))
- // No devices
- return 0;
-
- // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
-
- // reset ports
- if (port1 & USBPORTSC_CCS)
- outw(USBPORTSC_PR, cntl->uhci.iobase + USBPORTSC1);
- if (port2 & USBPORTSC_CCS)
- outw(USBPORTSC_PR, cntl->uhci.iobase + USBPORTSC2);
- msleep(USB_TIME_DRSTR);
-
- // Configure ports
- int totalcount = 0;
- outw(0, cntl->uhci.iobase + USBPORTSC1);
- udelay(6); // 64 high-speed bit times
- port1 = inw(cntl->uhci.iobase + USBPORTSC1);
- if (port1 & USBPORTSC_CCS) {
- outw(USBPORTSC_PE, cntl->uhci.iobase + USBPORTSC1);
- msleep(USB_TIME_RSTRCY);
- int count = configure_usb_device(cntl, !!(port1 & USBPORTSC_LSDA));
- if (! count)
- outw(0, cntl->uhci.iobase + USBPORTSC1);
- totalcount += count;
- }
- outw(0, cntl->uhci.iobase + USBPORTSC2);
- udelay(6);
- port2 = inw(cntl->uhci.iobase + USBPORTSC2);
- if (port2 & USBPORTSC_CCS) {
- outw(USBPORTSC_PE, cntl->uhci.iobase + USBPORTSC2);
- msleep(USB_TIME_RSTRCY);
- int count = configure_usb_device(cntl, !!(port2 & USBPORTSC_LSDA));
- if (! count)
- outw(0, cntl->uhci.iobase + USBPORTSC2);
- totalcount += count;
- }
- return totalcount;
-}
-
void
uhci_init(void *data)
{