]> xenbits.xensource.com Git - seabios.git/commitdiff
usb-xhci: use hub portmap
authorGerd Hoffmann <kraxel@redhat.com>
Tue, 18 Jul 2017 11:15:42 +0000 (13:15 +0200)
committerGerd Hoffmann <kraxel@redhat.com>
Tue, 25 Jul 2017 11:02:11 +0000 (13:02 +0200)
xhci controllers have two virtual ports per (usb3 capable) physical
port, one for usb2 and one for usb3 devices.  Add a hub portmap callback
to map the virtual ports to physical ports.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
src/hw/usb-xhci.c

index 69954b9d8d7f7a7681c3b288c5ca937d960713d7..50b3b86d6b48b80804cc7436fea3354edce83bf3 100644 (file)
@@ -226,6 +226,11 @@ struct xhci_ring {
     struct mutex_s       lock;
 };
 
+struct xhci_portmap {
+    u8 start;
+    u8 count;
+};
+
 struct usb_xhci_s {
     struct usb_s         usb;
 
@@ -234,6 +239,8 @@ struct usb_xhci_s {
     u32                  ports;
     u32                  slots;
     u8                   context64;
+    struct xhci_portmap  usb2;
+    struct xhci_portmap  usb3;
 
     /* xhci registers */
     struct xhci_caps     *caps;
@@ -374,6 +381,23 @@ xhci_hub_reset(struct usbhub_s *hub, u32 port)
     return rc;
 }
 
+static int
+xhci_hub_portmap(struct usbhub_s *hub, u32 vport)
+{
+    struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
+    u32 pport = vport + 1;
+
+    if (vport + 1 >= xhci->usb3.start &&
+        vport + 1 < xhci->usb3.start + xhci->usb3.count)
+        pport = vport + 2 - xhci->usb3.start;
+
+    if (vport + 1 >= xhci->usb2.start &&
+        vport + 1 < xhci->usb2.start + xhci->usb2.count)
+        pport = vport + 2 - xhci->usb2.start;
+
+    return pport;
+}
+
 static void
 xhci_hub_disconnect(struct usbhub_s *hub, u32 port)
 {
@@ -383,6 +407,7 @@ xhci_hub_disconnect(struct usbhub_s *hub, u32 port)
 static struct usbhub_op_s xhci_hub_ops = {
     .detect = xhci_hub_detect,
     .reset = xhci_hub_reset,
+    .portmap = xhci_hub_portmap,
     .disconnect = xhci_hub_disconnect,
 };
 
@@ -553,17 +578,29 @@ xhci_controller_setup(struct pci_device *pci)
             case 0x02:
                 name  = readl(&xcap->data[0]);
                 ports = readl(&xcap->data[1]);
+                u8 major = (cap >> 24) & 0xff;
+                u8 minor = (cap >> 16) & 0xff;
+                u8 count = (ports >> 8) & 0xff;
+                u8 start = (ports >> 0) & 0xff;
                 dprintf(1, "XHCI    protocol %c%c%c%c %x.%02x"
                         ", %d ports (offset %d), def %x\n"
                         , (name >>  0) & 0xff
                         , (name >>  8) & 0xff
                         , (name >> 16) & 0xff
                         , (name >> 24) & 0xff
-                        , (cap >> 24) & 0xff
-                        , (cap >> 16) & 0xff
-                        , (ports >>  8) & 0xff
-                        , (ports >>  0) & 0xff
+                        , major, minor
+                        , count, start
                         , ports >> 16);
+                if (name == 0x20425355 /* "USB " */) {
+                    if (major == 2) {
+                        xhci->usb2.start = start;
+                        xhci->usb2.count = count;
+                    }
+                    if (major == 3) {
+                        xhci->usb3.start = start;
+                        xhci->usb3.count = count;
+                    }
+                }
                 break;
             default:
                 dprintf(1, "XHCI    extcap 0x%x @ %p\n", cap & 0xff, addr);