render / rpms / qemu

Forked from rpms/qemu 10 months ago
Clone
Hans de Goede c8dfc6
From ed16ece865cb40c9ad8ddf28905c0af3ad80e118 Mon Sep 17 00:00:00 2001
Hans de Goede c8dfc6
From: Gerd Hoffmann <kraxel@redhat.com>
Hans de Goede c8dfc6
Date: Tue, 28 Aug 2012 13:38:01 +0200
Hans de Goede c8dfc6
Subject: [PATCH 340/366] xhci: update port handling
Hans de Goede c8dfc6
Hans de Goede c8dfc6
This patch changes the way xhci ports are linked to USBPorts.  The fixed
Hans de Goede c8dfc6
1:1 relationship between xhci ports and USBPorts is gone.  Now each
Hans de Goede c8dfc6
USBPort represents a physical plug which has usually two xhci ports
Hans de Goede c8dfc6
assigned: one usb2 and ond usb3 port.  usb devices show up at one or the
Hans de Goede c8dfc6
other, depending on whenever they support superspeed or not.
Hans de Goede c8dfc6
Hans de Goede c8dfc6
This patch also makes the number of usb2 and usb3 ports runtime
Hans de Goede c8dfc6
configurable by adding 'p2' and 'p3' properties.  It is allowed to
Hans de Goede c8dfc6
have different numbers of usb2 and usb3 ports.  Specifying p2=4,p3=2
Hans de Goede c8dfc6
will give you an xhci adapter which supports all speeds on physical
Hans de Goede c8dfc6
ports 1+2 and usb2 only on ports 3+4.
Hans de Goede c8dfc6
---
Hans de Goede c8dfc6
 hw/usb/hcd-xhci.c | 137 ++++++++++++++++++++++++++++++++++++++----------------
Hans de Goede c8dfc6
 1 file changed, 97 insertions(+), 40 deletions(-)
Hans de Goede c8dfc6
Hans de Goede c8dfc6
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
Hans de Goede c8dfc6
index 414b633..e08312e 100644
Hans de Goede c8dfc6
--- a/hw/usb/hcd-xhci.c
Hans de Goede c8dfc6
+++ b/hw/usb/hcd-xhci.c
Hans de Goede c8dfc6
@@ -36,10 +36,10 @@
Hans de Goede c8dfc6
 #define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \
Hans de Goede c8dfc6
                              __func__, __LINE__); abort(); } while (0)
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-#define USB2_PORTS 4
Hans de Goede c8dfc6
-#define USB3_PORTS 4
Hans de Goede c8dfc6
+#define MAXPORTS_2 8
Hans de Goede c8dfc6
+#define MAXPORTS_3 8
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-#define MAXPORTS (USB2_PORTS+USB3_PORTS)
Hans de Goede c8dfc6
+#define MAXPORTS (MAXPORTS_2+MAXPORTS_3)
Hans de Goede c8dfc6
 #define MAXSLOTS MAXPORTS
Hans de Goede c8dfc6
 #define MAXINTRS 1 /* MAXPORTS */
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -300,8 +300,10 @@ typedef struct XHCIRing {
Hans de Goede c8dfc6
 } XHCIRing;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 typedef struct XHCIPort {
Hans de Goede c8dfc6
-    USBPort port;
Hans de Goede c8dfc6
     uint32_t portsc;
Hans de Goede c8dfc6
+    uint32_t portnr;
Hans de Goede c8dfc6
+    USBPort  *uport;
Hans de Goede c8dfc6
+    uint32_t speedmask;
Hans de Goede c8dfc6
 } XHCIPort;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 struct XHCIState;
Hans de Goede c8dfc6
@@ -379,9 +381,13 @@ struct XHCIState {
Hans de Goede c8dfc6
     qemu_irq irq;
Hans de Goede c8dfc6
     MemoryRegion mem;
Hans de Goede c8dfc6
     const char *name;
Hans de Goede c8dfc6
-    uint32_t msi;
Hans de Goede c8dfc6
     unsigned int devaddr;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+    /* properties */
Hans de Goede c8dfc6
+    uint32_t numports_2;
Hans de Goede c8dfc6
+    uint32_t numports_3;
Hans de Goede c8dfc6
+    uint32_t msi;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
     /* Operational Registers */
Hans de Goede c8dfc6
     uint32_t usbcmd;
Hans de Goede c8dfc6
     uint32_t usbsts;
Hans de Goede c8dfc6
@@ -392,8 +398,10 @@ struct XHCIState {
Hans de Goede c8dfc6
     uint32_t dcbaap_high;
Hans de Goede c8dfc6
     uint32_t config;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+    USBPort  uports[MAX(MAXPORTS_2, MAXPORTS_3)];
Hans de Goede c8dfc6
     XHCIPort ports[MAXPORTS];
Hans de Goede c8dfc6
     XHCISlot slots[MAXSLOTS];
Hans de Goede c8dfc6
+    uint32_t numports;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     /* Runtime Registers */
Hans de Goede c8dfc6
     uint32_t iman;
Hans de Goede c8dfc6
@@ -578,6 +586,28 @@ static inline dma_addr_t xhci_mask64(uint64_t addr)
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
Hans de Goede c8dfc6
+{
Hans de Goede c8dfc6
+    int index;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (!uport->dev) {
Hans de Goede c8dfc6
+        return NULL;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+    switch (uport->dev->speed) {
Hans de Goede c8dfc6
+    case USB_SPEED_LOW:
Hans de Goede c8dfc6
+    case USB_SPEED_FULL:
Hans de Goede c8dfc6
+    case USB_SPEED_HIGH:
Hans de Goede c8dfc6
+        index = uport->index;
Hans de Goede c8dfc6
+        break;
Hans de Goede c8dfc6
+    case USB_SPEED_SUPER:
Hans de Goede c8dfc6
+        index = uport->index + xhci->numports_2;
Hans de Goede c8dfc6
+        break;
Hans de Goede c8dfc6
+    default:
Hans de Goede c8dfc6
+        return NULL;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+    return &xhci->ports[index];
Hans de Goede c8dfc6
+}
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
 static void xhci_irq_update(XHCIState *xhci)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     int level = 0;
Hans de Goede c8dfc6
@@ -1126,7 +1156,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
Hans de Goede c8dfc6
         ep |= 0x80;
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    dev = xhci->ports[xhci->slots[slotid-1].port-1].port.dev;
Hans de Goede c8dfc6
+    dev = xhci->ports[xhci->slots[slotid-1].port-1].uport->dev;
Hans de Goede c8dfc6
     if (!dev) {
Hans de Goede c8dfc6
         return CC_USB_TRANSACTION_ERROR;
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
@@ -1313,7 +1343,7 @@ static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
Hans de Goede c8dfc6
     if (!(port->portsc & PORTSC_PED)) {
Hans de Goede c8dfc6
         return NULL;
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
-    return usb_find_device(&port->port, addr);
Hans de Goede c8dfc6
+    return usb_find_device(port->uport, addr);
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 static int xhci_setup_packet(XHCITransfer *xfer)
Hans de Goede c8dfc6
@@ -1736,9 +1766,9 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
Hans de Goede c8dfc6
             ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     port = (slot_ctx[1]>>16) & 0xFF;
Hans de Goede c8dfc6
-    dev = xhci->ports[port-1].port.dev;
Hans de Goede c8dfc6
+    dev = xhci->ports[port-1].uport->dev;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    if (port < 1 || port > MAXPORTS) {
Hans de Goede c8dfc6
+    if (port < 1 || port > xhci->numports) {
Hans de Goede c8dfc6
         fprintf(stderr, "xhci: bad port %d\n", port);
Hans de Goede c8dfc6
         return CC_TRB_ERROR;
Hans de Goede c8dfc6
     } else if (!dev) {
Hans de Goede c8dfc6
@@ -1987,7 +2017,7 @@ static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *tr
Hans de Goede c8dfc6
 static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     dma_addr_t ctx;
Hans de Goede c8dfc6
-    uint8_t bw_ctx[MAXPORTS+1];
Hans de Goede c8dfc6
+    uint8_t bw_ctx[xhci->numports+1];
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     DPRINTF("xhci_get_port_bandwidth()\n");
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -1997,7 +2027,7 @@ static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     /* TODO: actually implement real values here */
Hans de Goede c8dfc6
     bw_ctx[0] = 0;
Hans de Goede c8dfc6
-    memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */
Hans de Goede c8dfc6
+    memset(&bw_ctx[1], 80, xhci->numports); /* 80% */
Hans de Goede c8dfc6
     pci_dma_write(&xhci->pci_dev, ctx, bw_ctx, sizeof(bw_ctx));
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     return CC_SUCCESS;
Hans de Goede c8dfc6
@@ -2167,12 +2197,11 @@ static void xhci_process_commands(XHCIState *xhci)
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
-    int nr = port->port.index + 1;
Hans de Goede c8dfc6
-
Hans de Goede c8dfc6
     port->portsc = PORTSC_PP;
Hans de Goede c8dfc6
-    if (port->port.dev && port->port.dev->attached && !is_detach) {
Hans de Goede c8dfc6
+    if (port->uport->dev && port->uport->dev->attached && !is_detach &&
Hans de Goede c8dfc6
+        (1 << port->uport->dev->speed) & port->speedmask) {
Hans de Goede c8dfc6
         port->portsc |= PORTSC_CCS;
Hans de Goede c8dfc6
-        switch (port->port.dev->speed) {
Hans de Goede c8dfc6
+        switch (port->uport->dev->speed) {
Hans de Goede c8dfc6
         case USB_SPEED_LOW:
Hans de Goede c8dfc6
             port->portsc |= PORTSC_SPEED_LOW;
Hans de Goede c8dfc6
             break;
Hans de Goede c8dfc6
@@ -2182,14 +2211,18 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
Hans de Goede c8dfc6
         case USB_SPEED_HIGH:
Hans de Goede c8dfc6
             port->portsc |= PORTSC_SPEED_HIGH;
Hans de Goede c8dfc6
             break;
Hans de Goede c8dfc6
+        case USB_SPEED_SUPER:
Hans de Goede c8dfc6
+            port->portsc |= PORTSC_SPEED_SUPER;
Hans de Goede c8dfc6
+            break;
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     if (xhci_running(xhci)) {
Hans de Goede c8dfc6
         port->portsc |= PORTSC_CSC;
Hans de Goede c8dfc6
-        XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
Hans de Goede c8dfc6
+        XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS,
Hans de Goede c8dfc6
+                         port->portnr << 24};
Hans de Goede c8dfc6
         xhci_event(xhci, &ev;;
Hans de Goede c8dfc6
-        DPRINTF("xhci: port change event for port %d\n", nr);
Hans de Goede c8dfc6
+        DPRINTF("xhci: port change event for port %d\n", port->portnr);
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -2217,7 +2250,7 @@ static void xhci_reset(DeviceState *dev)
Hans de Goede c8dfc6
         xhci_disable_slot(xhci, i+1);
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    for (i = 0; i < MAXPORTS; i++) {
Hans de Goede c8dfc6
+    for (i = 0; i < xhci->numports; i++) {
Hans de Goede c8dfc6
         xhci_update_port(xhci, xhci->ports + i, 0);
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -2248,7 +2281,8 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
Hans de Goede c8dfc6
         ret = 0x01000000 | LEN_CAP;
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case 0x04: /* HCSPARAMS 1 */
Hans de Goede c8dfc6
-        ret = (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
Hans de Goede c8dfc6
+        ret = ((xhci->numports_2+xhci->numports_3)<<24)
Hans de Goede c8dfc6
+            | (MAXINTRS<<8) | MAXSLOTS;
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case 0x08: /* HCSPARAMS 2 */
Hans de Goede c8dfc6
         ret = 0x0000000f;
Hans de Goede c8dfc6
@@ -2278,7 +2312,7 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
Hans de Goede c8dfc6
         ret = 0x20425455; /* "USB " */
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case 0x28: /* Supported Protocol:08 */
Hans de Goede c8dfc6
-        ret = 0x00000001 | (USB2_PORTS<<8);
Hans de Goede c8dfc6
+        ret = 0x00000001 | (xhci->numports_2<<8);
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case 0x2c: /* Supported Protocol:0c */
Hans de Goede c8dfc6
         ret = 0x00000000; /* reserved */
Hans de Goede c8dfc6
@@ -2290,7 +2324,7 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
Hans de Goede c8dfc6
         ret = 0x20425455; /* "USB " */
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case 0x38: /* Supported Protocol:08 */
Hans de Goede c8dfc6
-        ret = 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
Hans de Goede c8dfc6
+        ret = 0x00000000 | (xhci->numports_2+1) | (xhci->numports_3<<8);
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case 0x3c: /* Supported Protocol:0c */
Hans de Goede c8dfc6
         ret = 0x00000000; /* reserved */
Hans de Goede c8dfc6
@@ -2309,7 +2343,7 @@ static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
Hans de Goede c8dfc6
     uint32_t port = reg >> 4;
Hans de Goede c8dfc6
     uint32_t ret;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    if (port >= MAXPORTS) {
Hans de Goede c8dfc6
+    if (port >= xhci->numports) {
Hans de Goede c8dfc6
         fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
Hans de Goede c8dfc6
         ret = 0;
Hans de Goede c8dfc6
         goto out;
Hans de Goede c8dfc6
@@ -2342,7 +2376,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     trace_usb_xhci_port_write(port, reg & 0x0f, val);
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    if (port >= MAXPORTS) {
Hans de Goede c8dfc6
+    if (port >= xhci->numports) {
Hans de Goede c8dfc6
         fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
Hans de Goede c8dfc6
         return;
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
@@ -2364,7 +2398,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
Hans de Goede c8dfc6
         /* write-1-to-start bits */
Hans de Goede c8dfc6
         if (val & PORTSC_PR) {
Hans de Goede c8dfc6
             DPRINTF("xhci: port %d reset\n", port);
Hans de Goede c8dfc6
-            usb_device_reset(xhci->ports[port].port.dev);
Hans de Goede c8dfc6
+            usb_device_reset(xhci->ports[port].uport->dev);
Hans de Goede c8dfc6
             portsc |= PORTSC_PRC | PORTSC_PED;
Hans de Goede c8dfc6
         }
Hans de Goede c8dfc6
         xhci->ports[port].portsc = portsc;
Hans de Goede c8dfc6
@@ -2659,7 +2693,7 @@ static const MemoryRegionOps xhci_mem_ops = {
Hans de Goede c8dfc6
 static void xhci_attach(USBPort *usbport)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     XHCIState *xhci = usbport->opaque;
Hans de Goede c8dfc6
-    XHCIPort *port = &xhci->ports[usbport->index];
Hans de Goede c8dfc6
+    XHCIPort *port = xhci_lookup_port(xhci, usbport);
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     xhci_update_port(xhci, port, 0);
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
@@ -2667,7 +2701,7 @@ static void xhci_attach(USBPort *usbport)
Hans de Goede c8dfc6
 static void xhci_detach(USBPort *usbport)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     XHCIState *xhci = usbport->opaque;
Hans de Goede c8dfc6
-    XHCIPort *port = &xhci->ports[usbport->index];
Hans de Goede c8dfc6
+    XHCIPort *port = xhci_lookup_port(xhci, usbport);
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     xhci_update_port(xhci, port, 1);
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
@@ -2675,9 +2709,9 @@ static void xhci_detach(USBPort *usbport)
Hans de Goede c8dfc6
 static void xhci_wakeup(USBPort *usbport)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     XHCIState *xhci = usbport->opaque;
Hans de Goede c8dfc6
-    XHCIPort *port = &xhci->ports[usbport->index];
Hans de Goede c8dfc6
-    int nr = port->port.index + 1;
Hans de Goede c8dfc6
-    XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
Hans de Goede c8dfc6
+    XHCIPort *port = xhci_lookup_port(xhci, usbport);
Hans de Goede c8dfc6
+    XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS,
Hans de Goede c8dfc6
+                     port->portnr << 24};
Hans de Goede c8dfc6
     uint32_t pls;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK;
Hans de Goede c8dfc6
@@ -2759,22 +2793,43 @@ static USBBusOps xhci_bus_ops = {
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
-    int i;
Hans de Goede c8dfc6
+    XHCIPort *port;
Hans de Goede c8dfc6
+    int i, usbports, speedmask;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     xhci->usbsts = USBSTS_HCH;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+    if (xhci->numports_2 > MAXPORTS_2) {
Hans de Goede c8dfc6
+        xhci->numports_2 = MAXPORTS_2;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+    if (xhci->numports_3 > MAXPORTS_3) {
Hans de Goede c8dfc6
+        xhci->numports_3 = MAXPORTS_3;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+    usbports = MAX(xhci->numports_2, xhci->numports_3);
Hans de Goede c8dfc6
+    xhci->numports = xhci->numports_2 + xhci->numports_3;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
     usb_bus_new(&xhci->bus, &xhci_bus_ops, &xhci->pci_dev.qdev);
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    for (i = 0; i < MAXPORTS; i++) {
Hans de Goede c8dfc6
-        memset(&xhci->ports[i], 0, sizeof(xhci->ports[i]));
Hans de Goede c8dfc6
-        usb_register_port(&xhci->bus, &xhci->ports[i].port, xhci, i,
Hans de Goede c8dfc6
-                          &xhci_port_ops,
Hans de Goede c8dfc6
-                          USB_SPEED_MASK_LOW  |
Hans de Goede c8dfc6
-                          USB_SPEED_MASK_FULL |
Hans de Goede c8dfc6
-                          USB_SPEED_MASK_HIGH);
Hans de Goede c8dfc6
-    }
Hans de Goede c8dfc6
-    for (i = 0; i < MAXSLOTS; i++) {
Hans de Goede c8dfc6
-        xhci->slots[i].enabled = 0;
Hans de Goede c8dfc6
+    for (i = 0; i < usbports; i++) {
Hans de Goede c8dfc6
+        speedmask = 0;
Hans de Goede c8dfc6
+        if (i < xhci->numports_2) {
Hans de Goede c8dfc6
+            port = &xhci->ports[i];
Hans de Goede c8dfc6
+            port->portnr = i + 1;
Hans de Goede c8dfc6
+            port->uport = &xhci->uports[i];
Hans de Goede c8dfc6
+            port->speedmask =
Hans de Goede c8dfc6
+                USB_SPEED_MASK_LOW  |
Hans de Goede c8dfc6
+                USB_SPEED_MASK_FULL |
Hans de Goede c8dfc6
+                USB_SPEED_MASK_HIGH;
Hans de Goede c8dfc6
+            speedmask |= port->speedmask;
Hans de Goede c8dfc6
+        }
Hans de Goede c8dfc6
+        if (i < xhci->numports_3) {
Hans de Goede c8dfc6
+            port = &xhci->ports[i + xhci->numports_2];
Hans de Goede c8dfc6
+            port->portnr = i + 1 + xhci->numports_2;
Hans de Goede c8dfc6
+            port->uport = &xhci->uports[i];
Hans de Goede c8dfc6
+            port->speedmask = USB_SPEED_MASK_SUPER;
Hans de Goede c8dfc6
+            speedmask |= port->speedmask;
Hans de Goede c8dfc6
+        }
Hans de Goede c8dfc6
+        usb_register_port(&xhci->bus, &xhci->uports[i], xhci, i,
Hans de Goede c8dfc6
+                          &xhci_port_ops, speedmask);
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -2830,6 +2885,8 @@ static const VMStateDescription vmstate_xhci = {
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 static Property xhci_properties[] = {
Hans de Goede c8dfc6
     DEFINE_PROP_UINT32("msi", XHCIState, msi, 0),
Hans de Goede c8dfc6
+    DEFINE_PROP_UINT32("p2",  XHCIState, numports_2, 4),
Hans de Goede c8dfc6
+    DEFINE_PROP_UINT32("p3",  XHCIState, numports_3, 4),
Hans de Goede c8dfc6
     DEFINE_PROP_END_OF_LIST(),
Hans de Goede c8dfc6
 };
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-- 
Hans de Goede c8dfc6
1.7.12
Hans de Goede c8dfc6